コード例 #1
0
ACPI_STATUS
AcpiEvQueueNotifyRequest (
    ACPI_NAMESPACE_NODE     *Node,
    UINT32                  NotifyValue)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj = NULL;
    ACPI_GENERIC_STATE      *NotifyInfo;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_NAME (EvQueueNotifyRequest);


    /*
     * For value 3 (Ejection Request), some device method may need to be run.
     * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
     *   to be run.
     * For value 0x80 (Status Change) on the power button or sleep button,
     *   initiate soft-off or sleep operation?
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n",
        AcpiUtGetNodeName (Node), Node, NotifyValue,
        AcpiUtGetNotifyName (NotifyValue)));

    /* Get the notify object attached to the NS Node */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (ObjDesc)
    {
        /* We have the notify object, Get the right handler */

        switch (Node->Type)
        {
        /* Notify allowed only on these types */

        case ACPI_TYPE_DEVICE:
        case ACPI_TYPE_THERMAL:
        case ACPI_TYPE_PROCESSOR:

            if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
            {
                HandlerObj = ObjDesc->CommonNotify.SystemNotify;
            }
            else
            {
                HandlerObj = ObjDesc->CommonNotify.DeviceNotify;
            }
            break;

        default:
            /* All other types are not supported */
            return (AE_TYPE);
        }
    }

    /*
     * If there is any handler to run, schedule the dispatcher.
     * Check for:
     * 1) Global system notify handler
     * 2) Global device notify handler
     * 3) Per-device notify handler
     */
    if ((AcpiGbl_SystemNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) ||
        (AcpiGbl_DeviceNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY))  ||
        HandlerObj)
    {
        NotifyInfo = AcpiUtCreateGenericState ();
        if (!NotifyInfo)
        {
            return (AE_NO_MEMORY);
        }

        if (!HandlerObj)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Executing system notify handler for Notify (%4.4s, %X) node %p\n",
                AcpiUtGetNodeName (Node), NotifyValue, Node));
        }

        NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY;
        NotifyInfo->Notify.Node = Node;
        NotifyInfo->Notify.Value = (UINT16) NotifyValue;
        NotifyInfo->Notify.HandlerObj = HandlerObj;

        Status = AcpiOsExecute (
                    OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo);
        if (ACPI_FAILURE (Status))
        {
            AcpiUtDeleteGenericState (NotifyInfo);
        }
    }
    else
    {
        /*
         * There is no notify handler (per-device or system) for this device.
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "No notify handler for Notify (%4.4s, %X) node %p\n",
            AcpiUtGetNodeName (Node), NotifyValue, Node));
    }

    return (Status);
}
コード例 #2
0
ファイル: dsinit.c プロジェクト: hoangduit/reactos
static ACPI_STATUS
AcpiDsInitOneObject (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     *ObjDesc;


    ACPI_FUNCTION_ENTRY ();


    /*
     * We are only interested in NS nodes owned by the table that
     * was just loaded
     */
    if (Node->OwnerId != Info->OwnerId)
    {
        return (AE_OK);
    }

    Info->ObjectCount++;

    /* And even then, we are only interested in a few object types */

    switch (AcpiNsGetType (ObjHandle))
    {
    case ACPI_TYPE_REGION:

        Status = AcpiDsInitializeRegion (ObjHandle);
        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "During Region initialization %p [%4.4s]",
                ObjHandle, AcpiUtGetNodeName (ObjHandle)));
        }

        Info->OpRegionCount++;
        break;

    case ACPI_TYPE_METHOD:
        /*
         * Auto-serialization support. We will examine each method that is
         * NotSerialized to determine if it creates any Named objects. If
         * it does, it will be marked serialized to prevent problems if
         * the method is entered by two or more threads and an attempt is
         * made to create the same named object twice -- which results in
         * an AE_ALREADY_EXISTS exception and method abort.
         */
        Info->MethodCount++;
        ObjDesc = AcpiNsGetAttachedObject (Node);
        if (!ObjDesc)
        {
            break;
        }

        /* Ignore if already serialized */

        if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
        {
            Info->SerialMethodCount++;
            break;
        }

        if (AcpiGbl_AutoSerializeMethods)
        {
            /* Parse/scan method and serialize it if necessary */

            AcpiDsAutoSerializeMethod (Node, ObjDesc);
            if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
            {
                /* Method was just converted to Serialized */

                Info->SerialMethodCount++;
                Info->SerializedMethodCount++;
                break;
            }
        }

        Info->NonSerialMethodCount++;
        break;

    case ACPI_TYPE_DEVICE:

        Info->DeviceCount++;
        break;

    default:

        break;
    }

    /*
     * We ignore errors from above, and always return OK, since
     * we don't want to abort the walk on a single error.
     */
    return (AE_OK);
}
コード例 #3
0
void
AcpiUtDumpAllocations (
    UINT32                  Component,
    const char              *Module)
{
    ACPI_DEBUG_MEM_BLOCK    *Element;
    ACPI_DESCRIPTOR         *Descriptor;
    UINT32                  NumOutstanding = 0;
    UINT8                   DescriptorType;


    ACPI_FUNCTION_TRACE (UtDumpAllocations);


    if (AcpiGbl_DisableMemTracking)
    {
        return_VOID;
    }

    /*
     * Walk the allocation list.
     */
    if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
    {
        return_VOID;
    }

    Element = AcpiGbl_GlobalList->ListHead;
    while (Element)
    {
        if ((Element->Component & Component) &&
            ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module))))
        {
            Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace);

            if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
            {
                AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u "
                    "[Not a Descriptor - too small]\n",
                    Descriptor, Element->Size, Element->Module,
                    Element->Line);
            }
            else
            {
                /* Ignore allocated objects that are in a cache */

                if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED)
                {
                    AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ",
                        Descriptor, Element->Size, Element->Module,
                        Element->Line, AcpiUtGetDescriptorName (Descriptor));

                    /* Validate the descriptor type using Type field and length */

                    DescriptorType = 0; /* Not a valid descriptor type */

                    switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
                    {
                    case ACPI_DESC_TYPE_OPERAND:

                        if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
                        {
                            DescriptorType = ACPI_DESC_TYPE_OPERAND;
                        }
                        break;

                    case ACPI_DESC_TYPE_PARSER:

                        if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
                        {
                            DescriptorType = ACPI_DESC_TYPE_PARSER;
                        }
                        break;

                    case ACPI_DESC_TYPE_NAMED:

                        if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
                        {
                            DescriptorType = ACPI_DESC_TYPE_NAMED;
                        }
                        break;

                    default:

                        break;
                    }

                    /* Display additional info for the major descriptor types */

                    switch (DescriptorType)
                    {
                    case ACPI_DESC_TYPE_OPERAND:

                        AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
                            AcpiUtGetTypeName (Descriptor->Object.Common.Type),
                            Descriptor->Object.Common.ReferenceCount);
                        break;

                    case ACPI_DESC_TYPE_PARSER:

                        AcpiOsPrintf ("AmlOpcode 0x%04hX\n",
                            Descriptor->Op.Asl.AmlOpcode);
                        break;

                    case ACPI_DESC_TYPE_NAMED:

                        AcpiOsPrintf ("%4.4s\n",
                            AcpiUtGetNodeName (&Descriptor->Node));
                        break;

                    default:

                        AcpiOsPrintf ( "\n");
                        break;
                    }
                }
            }

            NumOutstanding++;
        }

        Element = Element->Next;
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);

    /* Print summary */

    if (!NumOutstanding)
    {
        ACPI_INFO ((AE_INFO, "No outstanding allocations"));
    }
    else
    {
        ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations",
            NumOutstanding, NumOutstanding));
    }

    return_VOID;
}
コード例 #4
0
void
AcpiDbDisplayMethodInfo (
    ACPI_PARSE_OBJECT       *StartOp)
{
    ACPI_WALK_STATE         *WalkState;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_PARSE_OBJECT       *RootOp;
    ACPI_PARSE_OBJECT       *Op;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  NumOps = 0;
    UINT32                  NumOperands = 0;
    UINT32                  NumOperators = 0;
    UINT32                  NumRemainingOps = 0;
    UINT32                  NumRemainingOperands = 0;
    UINT32                  NumRemainingOperators = 0;
    BOOLEAN                 CountRemaining = FALSE;


    WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
    if (!WalkState)
    {
        AcpiOsPrintf ("There is no method currently executing\n");
        return;
    }

    ObjDesc = WalkState->MethodDesc;
    Node    = WalkState->MethodNode;

    AcpiOsPrintf ("Currently executing control method is [%4.4s]\n",
            AcpiUtGetNodeName (Node));
    AcpiOsPrintf ("%X Arguments, SyncLevel = %X\n",
            (UINT32) ObjDesc->Method.ParamCount,
            (UINT32) ObjDesc->Method.SyncLevel);


    RootOp = StartOp;
    while (RootOp->Common.Parent)
    {
        RootOp = RootOp->Common.Parent;
    }

    Op = RootOp;

    while (Op)
    {
        if (Op == StartOp)
        {
            CountRemaining = TRUE;
        }

        NumOps++;
        if (CountRemaining)
        {
            NumRemainingOps++;
        }

        /* Decode the opcode */

        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
        switch (OpInfo->Class)
        {
        case AML_CLASS_ARGUMENT:
            if (CountRemaining)
            {
                NumRemainingOperands++;
            }

            NumOperands++;
            break;

        case AML_CLASS_UNKNOWN:
            /* Bad opcode or ASCII character */

            continue;

        default:
            if (CountRemaining)
            {
                NumRemainingOperators++;
            }

            NumOperators++;
            break;
        }

        Op = AcpiPsGetDepthNext (StartOp, Op);
    }

    AcpiOsPrintf (
        "Method contains:       %X AML Opcodes - %X Operators, %X Operands\n",
        NumOps, NumOperators, NumOperands);

    AcpiOsPrintf (
        "Remaining to execute:  %X AML Opcodes - %X Operators, %X Operands\n",
        NumRemainingOps, NumRemainingOperators, NumRemainingOperands);
}
コード例 #5
0
ファイル: dswload.c プロジェクト: ModeenF/haiku
ACPI_STATUS
AcpiDsLoad1BeginOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       **OutOp)
{
    ACPI_PARSE_OBJECT       *Op;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        ObjectType;
    char                    *Path;
    UINT32                  Flags;


    ACPI_FUNCTION_TRACE (DsLoad1BeginOp);


    Op = WalkState->Op;
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState));

    /* We are only interested in opcodes that have an associated name */

    if (Op)
    {
        if (!(WalkState->OpInfo->Flags & AML_NAMED))
        {
            *OutOp = Op;
            return_ACPI_STATUS (AE_OK);
        }

        /* Check if this object has already been installed in the namespace */

        if (Op->Common.Node)
        {
            *OutOp = Op;
            return_ACPI_STATUS (AE_OK);
        }
    }

    Path = AcpiPsGetNextNamestring (&WalkState->ParserState);

    /* Map the raw opcode into an internal object type */

    ObjectType = WalkState->OpInfo->ObjectType;

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "State=%p Op=%p [%s]\n", WalkState, Op, AcpiUtGetTypeName (ObjectType)));

    switch (WalkState->Opcode)
    {
    case AML_SCOPE_OP:
        /*
         * The target name of the Scope() operator must exist at this point so
         * that we can actually open the scope to enter new names underneath it.
         * Allow search-to-root for single namesegs.
         */
        Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
                        ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node));
#ifdef ACPI_ASL_COMPILER
        if (Status == AE_NOT_FOUND)
        {
            /*
             * Table disassembly:
             * Target of Scope() not found. Generate an External for it, and
             * insert the name into the namespace.
             */
            AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0, 0);
            Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
                       ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
                       WalkState, &Node);
        }
#endif
        if (ACPI_FAILURE (Status))
        {
            ACPI_ERROR_NAMESPACE (Path, Status);
            return_ACPI_STATUS (Status);
        }

        /*
         * Check to make sure that the target is
         * one of the opcodes that actually opens a scope
         */
        switch (Node->Type)
        {
        case ACPI_TYPE_ANY:
        case ACPI_TYPE_LOCAL_SCOPE:         /* Scope  */
        case ACPI_TYPE_DEVICE:
        case ACPI_TYPE_POWER:
        case ACPI_TYPE_PROCESSOR:
        case ACPI_TYPE_THERMAL:

            /* These are acceptable types */
            break;

        case ACPI_TYPE_INTEGER:
        case ACPI_TYPE_STRING:
        case ACPI_TYPE_BUFFER:
            /*
             * These types we will allow, but we will change the type.
             * This enables some existing code of the form:
             *
             *  Name (DEB, 0)
             *  Scope (DEB) { ... }
             *
             * Note: silently change the type here. On the second pass,
             * we will report a warning
             */
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Type override - [%4.4s] had invalid type (%s) "
                "for Scope operator, changed to type ANY\n",
                AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type)));

            Node->Type = ACPI_TYPE_ANY;
            WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY;
            break;

        case ACPI_TYPE_METHOD:
            /*
             * Allow scope change to root during execution of module-level
             * code. Root is typed METHOD during this time.
             */
            if ((Node == AcpiGbl_RootNode) &&
                (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL))
            {
                break;
            }

            /*lint -fallthrough */

        default:

            /* All other types are an error */

            ACPI_ERROR ((AE_INFO,
                "Invalid type (%s) for target of "
                "Scope operator [%4.4s] (Cannot override)",
                AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node)));

            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }
        break;

    default:
        /*
         * For all other named opcodes, we will enter the name into
         * the namespace.
         *
         * Setup the search flags.
         * Since we are entering a name into the namespace, we do not want to
         * enable the search-to-root upsearch.
         *
         * There are only two conditions where it is acceptable that the name
         * already exists:
         *    1) the Scope() operator can reopen a scoping object that was
         *       previously defined (Scope, Method, Device, etc.)
         *    2) Whenever we are parsing a deferred opcode (OpRegion, Buffer,
         *       BufferField, or Package), the name of the object is already
         *       in the namespace.
         */
        if (WalkState->DeferredNode)
        {
            /* This name is already in the namespace, get the node */

            Node = WalkState->DeferredNode;
            Status = AE_OK;
            break;
        }

        /*
         * If we are executing a method, do not create any namespace objects
         * during the load phase, only during execution.
         */
        if (WalkState->MethodNode)
        {
            Node = NULL;
            Status = AE_OK;
            break;
        }

        Flags = ACPI_NS_NO_UPSEARCH;
        if ((WalkState->Opcode != AML_SCOPE_OP) &&
            (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP)))
        {
            if (WalkState->NamespaceOverride)
            {
                Flags |= ACPI_NS_OVERRIDE_IF_FOUND;
                ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Override allowed\n",
                        AcpiUtGetTypeName (ObjectType)));
            }
            else
            {
                Flags |= ACPI_NS_ERROR_IF_FOUND;
                ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n",
                        AcpiUtGetTypeName (ObjectType)));
            }
        }
        else
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "[%s] Both Find or Create allowed\n",
                    AcpiUtGetTypeName (ObjectType)));
        }

        /*
         * Enter the named type into the internal namespace. We enter the name
         * as we go downward in the parse tree. Any necessary subobjects that
         * involve arguments to the opcode must be created as we go back up the
         * parse tree later.
         */
        Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
                        ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node);
        if (ACPI_FAILURE (Status))
        {
            if (Status == AE_ALREADY_EXISTS)
            {
                /* The name already exists in this scope */

                if (Node->Flags & ANOBJ_IS_EXTERNAL)
                {
                    /*
                     * Allow one create on an object or segment that was
                     * previously declared External
                     */
                    Node->Flags &= ~ANOBJ_IS_EXTERNAL;
                    Node->Type = (UINT8) ObjectType;

                    /* Just retyped a node, probably will need to open a scope */

                    if (AcpiNsOpensScope (ObjectType))
                    {
                        Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState);
                        if (ACPI_FAILURE (Status))
                        {
                            return_ACPI_STATUS (Status);
                        }
                    }

                    Status = AE_OK;
                }
            }

            if (ACPI_FAILURE (Status))
            {
                ACPI_ERROR_NAMESPACE (Path, Status);
                return_ACPI_STATUS (Status);
            }
        }
        break;
    }

    /* Common exit */

    if (!Op)
    {
        /* Create a new op */

        Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml);
        if (!Op)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }
    }

    /* Initialize the op */

#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
    Op->Named.Path = ACPI_CAST_PTR (UINT8, Path);
#endif

    if (Node)
    {
        /*
         * Put the Node in the "op" object that the parser uses, so we
         * can get it again quickly when this scope is closed
         */
        Op->Common.Node = Node;
        Op->Named.Name = Node->Name.Integer;
    }

    AcpiPsAppendArg (AcpiPsGetParentScope (&WalkState->ParserState), Op);
    *OutOp = Op;
    return_ACPI_STATUS (Status);
}
コード例 #6
0
ファイル: nsobject.c プロジェクト: 2asoft/freebsd
ACPI_STATUS
AcpiNsAttachObject (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_OPERAND_OBJECT     *Object,
    ACPI_OBJECT_TYPE        Type)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *LastObjDesc;
    ACPI_OBJECT_TYPE        ObjectType = ACPI_TYPE_ANY;


    ACPI_FUNCTION_TRACE (NsAttachObject);


    /*
     * Parameter validation
     */
    if (!Node)
    {
        /* Invalid handle */

        ACPI_ERROR ((AE_INFO, "Null NamedObj handle"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    if (!Object && (ACPI_TYPE_ANY != Type))
    {
        /* Null object */

        ACPI_ERROR ((AE_INFO,
            "Null object, but type not ACPI_TYPE_ANY"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
    {
        /* Not a name handle */

        ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]",
            Node, AcpiUtGetDescriptorName (Node)));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Check if this object is already attached */

    if (Node->Object == Object)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Obj %p already installed in NameObj %p\n",
            Object, Node));

        return_ACPI_STATUS (AE_OK);
    }

    /* If null object, we will just install it */

    if (!Object)
    {
        ObjDesc    = NULL;
        ObjectType = ACPI_TYPE_ANY;
    }

    /*
     * If the source object is a namespace Node with an attached object,
     * we will use that (attached) object
     */
    else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) &&
            ((ACPI_NAMESPACE_NODE *) Object)->Object)
    {
        /*
         * Value passed is a name handle and that name has a
         * non-null value. Use that name's value and type.
         */
        ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object;
        ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type;
    }

    /*
     * Otherwise, we will use the parameter object, but we must type
     * it first
     */
    else
    {
        ObjDesc = (ACPI_OPERAND_OBJECT  *) Object;

        /* Use the given type */

        ObjectType = Type;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
        ObjDesc, Node, AcpiUtGetNodeName (Node)));

    /* Detach an existing attached object if present */

    if (Node->Object)
    {
        AcpiNsDetachObject (Node);
    }

    if (ObjDesc)
    {
        /*
         * Must increment the new value's reference count
         * (if it is an internal object)
         */
        AcpiUtAddReference (ObjDesc);

        /*
         * Handle objects with multiple descriptors - walk
         * to the end of the descriptor list
         */
        LastObjDesc = ObjDesc;
        while (LastObjDesc->Common.NextObject)
        {
            LastObjDesc = LastObjDesc->Common.NextObject;
        }

        /* Install the object at the front of the object list */

        LastObjDesc->Common.NextObject = Node->Object;
    }

    Node->Type = (UINT8) ObjectType;
    Node->Object = ObjDesc;

    return_ACPI_STATUS (AE_OK);
}
コード例 #7
0
ファイル: dsmethod.c プロジェクト: looncraz/haiku
ACPI_STATUS
AcpiDsBeginMethodExecution (
    ACPI_NAMESPACE_NODE     *MethodNode,
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);


    if (!MethodNode)
    {
        return_ACPI_STATUS (AE_NULL_ENTRY);
    }

    AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState);

    /* Prevent wraparound of thread count */

    if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
    {
        ACPI_ERROR ((AE_INFO,
            "Method reached maximum reentrancy limit (255)"));
        return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
    }

    /*
     * If this method is serialized, we need to acquire the method mutex.
     */
    if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
    {
        /*
         * Create a mutex for the method if it is defined to be Serialized
         * and a mutex has not already been created. We defer the mutex creation
         * until a method is actually executed, to minimize the object count
         */
        if (!ObjDesc->Method.Mutex)
        {
            Status = AcpiDsCreateMethodMutex (ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
        }

        /*
         * The CurrentSyncLevel (per-thread) must be less than or equal to
         * the sync level of the method. This mechanism provides some
         * deadlock prevention.
         *
         * If the method was auto-serialized, we just ignore the sync level
         * mechanism, because auto-serialization of methods can interfere
         * with ASL code that actually uses sync levels.
         *
         * Top-level method invocation has no walk state at this point
         */
        if (WalkState &&
            (!(ObjDesc->Method.InfoFlags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) &&
            (WalkState->Thread->CurrentSyncLevel >
                ObjDesc->Method.Mutex->Mutex.SyncLevel))
        {
            ACPI_ERROR ((AE_INFO,
                "Cannot acquire Mutex for method [%4.4s]"
                ", current SyncLevel is too large (%u)",
                AcpiUtGetNodeName (MethodNode),
                WalkState->Thread->CurrentSyncLevel));

            return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
        }

        /*
         * Obtain the method mutex if necessary. Do not acquire mutex for a
         * recursive call.
         */
        if (!WalkState ||
            !ObjDesc->Method.Mutex->Mutex.ThreadId ||
            (WalkState->Thread->ThreadId !=
                ObjDesc->Method.Mutex->Mutex.ThreadId))
        {
            /*
             * Acquire the method mutex. This releases the interpreter if we
             * block (and reacquires it before it returns)
             */
            Status = AcpiExSystemWaitMutex (
                ObjDesc->Method.Mutex->Mutex.OsMutex, ACPI_WAIT_FOREVER);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }

            /* Update the mutex and walk info and save the original SyncLevel */

            if (WalkState)
            {
                ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
                    WalkState->Thread->CurrentSyncLevel;

                ObjDesc->Method.Mutex->Mutex.ThreadId =
                    WalkState->Thread->ThreadId;

                /*
                 * Update the current SyncLevel only if this is not an auto-
                 * serialized method. In the auto case, we have to ignore
                 * the sync level for the method mutex (created for the
                 * auto-serialization) because we have no idea of what the
                 * sync level should be. Therefore, just ignore it.
                 */
                if (!(ObjDesc->Method.InfoFlags &
                    ACPI_METHOD_IGNORE_SYNC_LEVEL))
                {
                    WalkState->Thread->CurrentSyncLevel =
                        ObjDesc->Method.SyncLevel;
                }
            }
            else
            {
                ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
                    ObjDesc->Method.Mutex->Mutex.SyncLevel;

                ObjDesc->Method.Mutex->Mutex.ThreadId =
                    AcpiOsGetThreadId ();
            }
        }

        /* Always increase acquisition depth */

        ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
    }

    /*
     * Allocate an Owner ID for this method, only if this is the first thread
     * to begin concurrent execution. We only need one OwnerId, even if the
     * method is invoked recursively.
     */
    if (!ObjDesc->Method.OwnerId)
    {
        Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }
    }

    /*
     * Increment the method parse tree thread count since it has been
     * reentered one more time (even if it is the same thread)
     */
    ObjDesc->Method.ThreadCount++;
    AcpiMethodCount++;
    return_ACPI_STATUS (Status);


Cleanup:
    /* On error, must release the method mutex (if present) */

    if (ObjDesc->Method.Mutex)
    {
        AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);
    }
    return_ACPI_STATUS (Status);
}
コード例 #8
0
ACPI_STATUS
AcpiUtEvaluateObject (
    ACPI_NAMESPACE_NODE     *PrefixNode,
    char                    *Path,
    UINT32                  ExpectedReturnBtypes,
    ACPI_OPERAND_OBJECT     **ReturnDesc)
{
    ACPI_EVALUATE_INFO      *Info;
    ACPI_STATUS             Status;
    UINT32                  ReturnBtype;


    ACPI_FUNCTION_TRACE (UtEvaluateObject);


    /* Allocate the evaluation information block */

    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Info->PrefixNode = PrefixNode;
    Info->Pathname = Path;

    /* Evaluate the object/method */

    Status = AcpiNsEvaluate (Info);
    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_FOUND)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
                AcpiUtGetNodeName (PrefixNode), Path));
        }
        else
        {
            ACPI_ERROR_METHOD ("Method execution failed",
                PrefixNode, Path, Status);
        }

        goto Cleanup;
    }

    /* Did we get a return object? */

    if (!Info->ReturnObject)
    {
        if (ExpectedReturnBtypes)
        {
            ACPI_ERROR_METHOD ("No object was returned from",
                PrefixNode, Path, AE_NOT_EXIST);

            Status = AE_NOT_EXIST;
        }

        goto Cleanup;
    }

    /* Map the return object type to the bitmapped type */

    switch ((Info->ReturnObject)->Common.Type)
    {
    case ACPI_TYPE_INTEGER:
        ReturnBtype = ACPI_BTYPE_INTEGER;
        break;

    case ACPI_TYPE_BUFFER:
        ReturnBtype = ACPI_BTYPE_BUFFER;
        break;

    case ACPI_TYPE_STRING:
        ReturnBtype = ACPI_BTYPE_STRING;
        break;

    case ACPI_TYPE_PACKAGE:
        ReturnBtype = ACPI_BTYPE_PACKAGE;
        break;

    default:
        ReturnBtype = 0;
        break;
    }

    if ((AcpiGbl_EnableInterpreterSlack) &&
        (!ExpectedReturnBtypes))
    {
        /*
         * We received a return object, but one was not expected.  This can
         * happen frequently if the "implicit return" feature is enabled.
         * Just delete the return object and return AE_OK.
         */
        AcpiUtRemoveReference (Info->ReturnObject);
        goto Cleanup;
    }

    /* Is the return object one of the expected types? */

    if (!(ExpectedReturnBtypes & ReturnBtype))
    {
        ACPI_ERROR_METHOD ("Return object type is incorrect",
            PrefixNode, Path, AE_TYPE);

        ACPI_ERROR ((AE_INFO,
            "Type returned from %s was incorrect: %s, expected Btypes: %X",
            Path, AcpiUtGetObjectTypeName (Info->ReturnObject),
            ExpectedReturnBtypes));

        /* On error exit, we must delete the return object */

        AcpiUtRemoveReference (Info->ReturnObject);
        Status = AE_TYPE;
        goto Cleanup;
    }

    /* Object type is OK, return it */

    *ReturnDesc = Info->ReturnObject;

Cleanup:
    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}
コード例 #9
0
ファイル: evgpe.c プロジェクト: DonCN/haiku
static void ACPI_SYSTEM_XFACE
AcpiEvAsynchExecuteGpeMethod (
    void                    *Context)
{
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    ACPI_STATUS             Status;
    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_GPE_NOTIFY_INFO    *Notify;


    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);


    /* Allocate a local GPE block */

    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
    if (!LocalGpeEventInfo)
    {
        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
            "while handling a GPE"));
        return_VOID;
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        return_VOID;
    }

    /* Must revalidate the GpeNumber/GpeBlock */

    if (!AcpiEvValidGpeEvent (GpeEventInfo))
    {
        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
        return_VOID;
    }

    /*
     * Take a snapshot of the GPE info for this level - we copy the info to
     * prevent a race condition with RemoveHandler/RemoveBlock.
     */
    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
        sizeof (ACPI_GPE_EVENT_INFO));

    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        return_VOID;
    }

    /* Do the correct dispatch - normal method or implicit notify */

    switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
    {
    case ACPI_GPE_DISPATCH_NOTIFY:
        /*
         * Implicit notify.
         * Dispatch a DEVICE_WAKE notify to the appropriate handler.
         * NOTE: the request is queued for execution after this method
         * completes. The notify handlers are NOT invoked synchronously
         * from this thread -- because handlers may in turn run other
         * control methods.
         *
         * June 2012: Expand implicit notify mechanism to support
         * notifies on multiple device objects.
         */
        Notify = LocalGpeEventInfo->Dispatch.NotifyList;
        while (ACPI_SUCCESS (Status) && Notify)
        {
            Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode,
                        ACPI_NOTIFY_DEVICE_WAKE);

            Notify = Notify->Next;
        }
        break;

    case ACPI_GPE_DISPATCH_METHOD:

        /* Allocate the evaluation information block */

        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
        if (!Info)
        {
            Status = AE_NO_MEMORY;
        }
        else
        {
            /*
             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
             * _Lxx/_Exx control method that corresponds to this GPE
             */
            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
            Info->Flags = ACPI_IGNORE_RETURN_VALUE;

            Status = AcpiNsEvaluate (Info);
            ACPI_FREE (Info);
        }

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "while evaluating GPE method [%4.4s]",
                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
        }
        break;

    default:

        return_VOID; /* Should never happen */
    }

    /* Defer enabling of GPE until all notify handlers are done */

    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (LocalGpeEventInfo);
    }
    return_VOID;
}
コード例 #10
0
ファイル: exmutex.c プロジェクト: andreiw/polaris
ACPI_STATUS
AcpiExAcquireMutex (
    ACPI_OPERAND_OBJECT     *TimeDesc,
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc);


    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Sanity check: we must have a valid thread ID */

    if (!WalkState->Thread)
    {
        ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex [%4.4s], null thread info",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_INTERNAL);
    }

    /*
     * Current Sync must be less than or equal to the sync level of the
     * mutex. This mechanism provides some deadlock prevention
     */
    if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%d)",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node),
            WalkState->Thread->CurrentSyncLevel));
        return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    }

    /* Support for multiple acquires by the owning thread */

    if (ObjDesc->Mutex.OwnerThread)
    {
        if (ObjDesc->Mutex.OwnerThread->ThreadId ==
            WalkState->Thread->ThreadId)
        {
            /*
             * The mutex is already owned by this thread, just increment the
             * acquisition depth
             */
            ObjDesc->Mutex.AcquisitionDepth++;
            return_ACPI_STATUS (AE_OK);
        }
    }

    /* Acquire the mutex, wait if necessary. Special case for Global Lock */

    if (ObjDesc->Mutex.OsMutex == AcpiGbl_GlobalLockMutex)
    {
        Status = AcpiEvAcquireGlobalLock ((UINT16) TimeDesc->Integer.Value);
    }
    else
    {
        Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex,
                    (UINT16) TimeDesc->Integer.Value);
    }

    if (ACPI_FAILURE (Status))
    {
        /* Includes failure from a timeout on TimeDesc */

        return_ACPI_STATUS (Status);
    }

    /* Have the mutex: update mutex and walk info and save the SyncLevel */

    ObjDesc->Mutex.OwnerThread = WalkState->Thread;
    ObjDesc->Mutex.AcquisitionDepth = 1;
    ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel;

    WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel;

    /* Link the mutex to the current thread for force-unlock at method exit */

    AcpiExLinkMutex (ObjDesc, WalkState->Thread);
    return_ACPI_STATUS (AE_OK);
}
コード例 #11
0
ファイル: exmutex.c プロジェクト: andreiw/polaris
ACPI_STATUS
AcpiExReleaseMutex (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (ExReleaseMutex);


    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* The mutex must have been previously acquired in order to release it */

    if (!ObjDesc->Mutex.OwnerThread)
    {
        ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], not acquired",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
    }

    /* Sanity check: we must have a valid thread ID */

    if (!WalkState->Thread)
    {
        ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], null thread info",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_INTERNAL);
    }

    /*
     * The Mutex is owned, but this thread must be the owner.
     * Special case for Global Lock, any thread can release
     */
    if ((ObjDesc->Mutex.OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
        (ObjDesc->Mutex.OsMutex != AcpiGbl_GlobalLockMutex))
    {
        ACPI_ERROR ((AE_INFO,
            "Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
            WalkState->Thread->ThreadId,
            AcpiUtGetNodeName (ObjDesc->Mutex.Node),
            ObjDesc->Mutex.OwnerThread->ThreadId));
        return_ACPI_STATUS (AE_AML_NOT_OWNER);
    }

    /*
     * The sync level of the mutex must be less than or equal to the current
     * sync level
     */
    if (ObjDesc->Mutex.SyncLevel > WalkState->Thread->CurrentSyncLevel)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot release Mutex [%4.4s], incorrect SyncLevel",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    }

    /* Match multiple Acquires with multiple Releases */

    ObjDesc->Mutex.AcquisitionDepth--;
    if (ObjDesc->Mutex.AcquisitionDepth != 0)
    {
        /* Just decrement the depth and return */

        return_ACPI_STATUS (AE_OK);
    }

    /* Unlink the mutex from the owner's list */

    AcpiExUnlinkMutex (ObjDesc);

    /* Release the mutex, special case for Global Lock */

    if (ObjDesc->Mutex.OsMutex == AcpiGbl_GlobalLockMutex)
    {
        Status = AcpiEvReleaseGlobalLock ();
    }
    else
    {
        AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex);
    }

    /* Update the mutex and restore SyncLevel */

    ObjDesc->Mutex.OwnerThread = NULL;
    WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel;

    return_ACPI_STATUS (Status);
}
コード例 #12
0
ファイル: nsalloc.c プロジェクト: 9elements/fwts
void
AcpiNsInstallNode (
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
    ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
    ACPI_OBJECT_TYPE        Type)
{
    ACPI_OWNER_ID           OwnerId = 0;
    ACPI_NAMESPACE_NODE     *ChildNode;


    ACPI_FUNCTION_TRACE (NsInstallNode);


    if (WalkState)
    {
        /*
         * Get the owner ID from the Walk state. The owner ID is used to
         * track table deletion and deletion of objects created by methods.
         */
        OwnerId = WalkState->OwnerId;

        if ((WalkState->MethodDesc) &&
            (ParentNode != WalkState->MethodNode))
        {
            /*
             * A method is creating a new node that is not a child of the
             * method (it is non-local). Mark the executing method as having
             * modified the namespace. This is used for cleanup when the
             * method exits.
             */
            WalkState->MethodDesc->Method.InfoFlags |=
                ACPI_METHOD_MODIFIED_NAMESPACE;
        }
    }

    /* Link the new entry into the parent and existing children */

    Node->Peer = NULL;
    Node->Parent = ParentNode;
    ChildNode = ParentNode->Child;

    if (!ChildNode)
    {
        ParentNode->Child = Node;
    }
    else
    {
        /* Add node to the end of the peer list */

        while (ChildNode->Peer)
        {
            ChildNode = ChildNode->Peer;
        }

        ChildNode->Peer = Node;
    }

    /* Init the new entry */

    Node->OwnerId = OwnerId;
    Node->Type = (UINT8) Type;

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
        "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
        AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
        AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
        ParentNode));

    return_VOID;
}
コード例 #13
0
ファイル: evmisc.c プロジェクト: cloudius-systems/acpica
ACPI_STATUS
AcpiEvQueueNotifyRequest (
    ACPI_NAMESPACE_NODE     *Node,
    UINT32                  NotifyValue)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerListHead = NULL;
    ACPI_GENERIC_STATE      *Info;
    UINT8                   HandlerListId = 0;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_NAME (EvQueueNotifyRequest);


    /* Are Notifies allowed on this object? */

    if (!AcpiEvIsNotifyObject (Node))
    {
        return (AE_TYPE);
    }

    /* Get the correct notify list type (System or Device) */

    if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
    {
        HandlerListId = ACPI_SYSTEM_HANDLER_LIST;
    }
    else
    {
        HandlerListId = ACPI_DEVICE_HANDLER_LIST;
    }

    /* Get the notify object attached to the namespace Node */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (ObjDesc)
    {
        /* We have an attached object, Get the correct handler list */

        HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId];
    }

    /*
     * If there is no notify handler (Global or Local)
     * for this object, just ignore the notify
     */
    if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
            AcpiUtGetNodeName (Node), NotifyValue, Node));

        return (AE_OK);
    }

    /* Setup notify info and schedule the notify dispatcher */

    Info = AcpiUtCreateGenericState ();
    if (!Info)
    {
        return (AE_NO_MEMORY);
    }

    Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY;

    Info->Notify.Node = Node;
    Info->Notify.Value = (UINT16) NotifyValue;
    Info->Notify.HandlerListId = HandlerListId;
    Info->Notify.HandlerListHead = HandlerListHead;
    Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId];

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
        AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type),
        NotifyValue, AcpiUtGetNotifyName (NotifyValue), Node));

    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch,
        Info);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtDeleteGenericState (Info);
    }

    return (Status);
}
コード例 #14
0
ファイル: aehandlers.c プロジェクト: zenny/DragonFlyBSD
static void
AeCommonNotifyHandler (
    ACPI_HANDLE             Device,
    UINT32                  Value,
    UINT32                  HandlerId)
{
    char                    *Type;


    Type = "Device";
    if (Value <= ACPI_MAX_SYS_NOTIFY)
    {
        Type = "System";
    }

    switch (Value)
    {
#if 0
    case 0:

        printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value);
        if (AcpiGbl_DebugFile)
        {
            AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n");
        }
        break;

    case 1:

        printf ("[AcpiExec] Method Error: Incorrect numeric result\n");
        if (AcpiGbl_DebugFile)
        {
            AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n");
        }
        break;

    case 2:

        printf ("[AcpiExec] Method Error: An operand was overwritten\n");
        if (AcpiGbl_DebugFile)
        {
            AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n");
        }
        break;

#endif

    default:

        printf ("[AcpiExec] Handler %u: Received a %s Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
            HandlerId, Type, AcpiUtGetNodeName (Device), Device, Value,
            AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY));
        if (AcpiGbl_DebugFile)
        {
            AcpiOsPrintf ("[AcpiExec] Handler %u: Received a %s notify, Value 0x%2.2X\n",
                HandlerId, Type, Value);
        }

        (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
        break;
    }
}
コード例 #15
0
static void ACPI_SYSTEM_XFACE
AcpiEvAsynchExecuteGpeMethod (
    void                    *Context)
{
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    ACPI_STATUS             Status = AE_OK;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_GPE_NOTIFY_INFO    *Notify;


    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);


    /* Do the correct dispatch - normal method or implicit notify */

    switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
    {
    case ACPI_GPE_DISPATCH_NOTIFY:
        /*
         * Implicit notify.
         * Dispatch a DEVICE_WAKE notify to the appropriate handler.
         * NOTE: the request is queued for execution after this method
         * completes. The notify handlers are NOT invoked synchronously
         * from this thread -- because handlers may in turn run other
         * control methods.
         *
         * June 2012: Expand implicit notify mechanism to support
         * notifies on multiple device objects.
         */
        Notify = GpeEventInfo->Dispatch.NotifyList;
        while (ACPI_SUCCESS (Status) && Notify)
        {
            Status = AcpiEvQueueNotifyRequest (
                Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);

            Notify = Notify->Next;
        }
        break;

    case ACPI_GPE_DISPATCH_METHOD:

        /* Allocate the evaluation information block */

        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
        if (!Info)
        {
            Status = AE_NO_MEMORY;
        }
        else
        {
            /*
             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
             * _Lxx/_Exx control method that corresponds to this GPE
             */
            Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
            Info->Flags = ACPI_IGNORE_RETURN_VALUE;

            Status = AcpiNsEvaluate (Info);
            ACPI_FREE (Info);
        }

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "while evaluating GPE method [%4.4s]",
                AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
        }
        break;

    default:

        goto ErrorExit; /* Should never happen */
    }

    /* Defer enabling of GPE until all notify handlers are done */

    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
        AcpiEvAsynchEnableGpe, GpeEventInfo);
    if (ACPI_SUCCESS (Status))
    {
        return_VOID;
    }

ErrorExit:
    AcpiEvAsynchEnableGpe (GpeEventInfo);
    return_VOID;
}
コード例 #16
0
ファイル: exprep.c プロジェクト: Strongc/reactos
ACPI_STATUS
AcpiExPrepFieldValue (
    ACPI_CREATE_FIELD_INFO  *Info)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *SecondDesc = NULL;
    ACPI_STATUS             Status;
    UINT32                  AccessByteWidth;
    UINT32                  Type;


    ACPI_FUNCTION_TRACE (ExPrepFieldValue);


    /* Parameter validation */

    if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD)
    {
        if (!Info->RegionNode)
        {
            ACPI_ERROR ((AE_INFO, "Null RegionNode"));
            return_ACPI_STATUS (AE_AML_NO_OPERAND);
        }

        Type = AcpiNsGetType (Info->RegionNode);
        if (Type != ACPI_TYPE_REGION)
        {
            ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
                Type, AcpiUtGetTypeName (Type)));

            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }
    }

    /* Allocate a new field object */

    ObjDesc = AcpiUtCreateInternalObject (Info->FieldType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Initialize areas of the object that are common to all fields */

    ObjDesc->CommonField.Node = Info->FieldNode;
    Status = AcpiExPrepCommonFieldObject (ObjDesc,
        Info->FieldFlags, Info->Attribute,
        Info->FieldBitPosition, Info->FieldBitLength);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtDeleteObjectDesc (ObjDesc);
        return_ACPI_STATUS (Status);
    }

    /* Initialize areas of the object that are specific to the field type */

    switch (Info->FieldType)
    {
    case ACPI_TYPE_LOCAL_REGION_FIELD:

        ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode);

        /* Fields specific to GenericSerialBus fields */

        ObjDesc->Field.AccessLength = Info->AccessLength;

        if (Info->ConnectionNode)
        {
            SecondDesc = Info->ConnectionNode->Object;
            if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID))
            {
                Status = AcpiDsGetBufferArguments (SecondDesc);
                if (ACPI_FAILURE (Status))
                {
                    AcpiUtDeleteObjectDesc (ObjDesc);
                    return_ACPI_STATUS (Status);
                }
            }

            ObjDesc->Field.ResourceBuffer =
                SecondDesc->Buffer.Pointer;
            ObjDesc->Field.ResourceLength =
                (UINT16) SecondDesc->Buffer.Length;
        }
        else if (Info->ResourceBuffer)
        {
            ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer;
            ObjDesc->Field.ResourceLength = Info->ResourceLength;
        }

        ObjDesc->Field.PinNumberIndex = Info->PinNumberIndex;

        /* Allow full data read from EC address space */

        if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
            (ObjDesc->CommonField.BitLength > 8))
        {
            AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES (
                ObjDesc->CommonField.BitLength);

            /* Maximum byte width supported is 255 */

            if (AccessByteWidth < 256)
            {
                ObjDesc->CommonField.AccessByteWidth =
                    (UINT8) AccessByteWidth;
            }
        }

        /* An additional reference for the container */

        AcpiUtAddReference (ObjDesc->Field.RegionObj);

        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
            "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
            ObjDesc->Field.StartFieldBitOffset,
            ObjDesc->Field.BaseByteOffset,
            ObjDesc->Field.AccessByteWidth,
            ObjDesc->Field.RegionObj));
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:

        ObjDesc->BankField.Value = Info->BankValue;
        ObjDesc->BankField.RegionObj =
            AcpiNsGetAttachedObject (Info->RegionNode);
        ObjDesc->BankField.BankObj =
            AcpiNsGetAttachedObject (Info->RegisterNode);

        /* An additional reference for the attached objects */

        AcpiUtAddReference (ObjDesc->BankField.RegionObj);
        AcpiUtAddReference (ObjDesc->BankField.BankObj);

        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
            "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
            ObjDesc->BankField.StartFieldBitOffset,
            ObjDesc->BankField.BaseByteOffset,
            ObjDesc->Field.AccessByteWidth,
            ObjDesc->BankField.RegionObj,
            ObjDesc->BankField.BankObj));

        /*
         * Remember location in AML stream of the field unit
         * opcode and operands -- since the BankValue
         * operands must be evaluated.
         */
        SecondDesc = ObjDesc->Common.NextObject;
        SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT,
            Info->DataRegisterNode)->Named.Data;
        SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT,
            Info->DataRegisterNode)->Named.Length;

        break;

    case ACPI_TYPE_LOCAL_INDEX_FIELD:

        /* Get the Index and Data registers */

        ObjDesc->IndexField.IndexObj =
            AcpiNsGetAttachedObject (Info->RegisterNode);
        ObjDesc->IndexField.DataObj =
            AcpiNsGetAttachedObject (Info->DataRegisterNode);

        if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj)
        {
            ACPI_ERROR ((AE_INFO, "Null Index Object during field prep"));
            AcpiUtDeleteObjectDesc (ObjDesc);
            return_ACPI_STATUS (AE_AML_INTERNAL);
        }

        /* An additional reference for the attached objects */

        AcpiUtAddReference (ObjDesc->IndexField.DataObj);
        AcpiUtAddReference (ObjDesc->IndexField.IndexObj);

        /*
         * April 2006: Changed to match MS behavior
         *
         * The value written to the Index register is the byte offset of the
         * target field in units of the granularity of the IndexField
         *
         * Previously, the value was calculated as an index in terms of the
         * width of the Data register, as below:
         *
         *      ObjDesc->IndexField.Value = (UINT32)
         *          (Info->FieldBitPosition / ACPI_MUL_8 (
         *              ObjDesc->Field.AccessByteWidth));
         *
         * February 2006: Tried value as a byte offset:
         *      ObjDesc->IndexField.Value = (UINT32)
         *          ACPI_DIV_8 (Info->FieldBitPosition);
         */
        ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN (
            ACPI_DIV_8 (Info->FieldBitPosition),
            ObjDesc->IndexField.AccessByteWidth);

        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
            "IndexField: BitOff %X, Off %X, Value %X, "
            "Gran %X, Index %p, Data %p\n",
            ObjDesc->IndexField.StartFieldBitOffset,
            ObjDesc->IndexField.BaseByteOffset,
            ObjDesc->IndexField.Value,
            ObjDesc->Field.AccessByteWidth,
            ObjDesc->IndexField.IndexObj,
            ObjDesc->IndexField.DataObj));
        break;

    default:

        /* No other types should get here */

        break;
    }

    /*
     * Store the constructed descriptor (ObjDesc) into the parent Node,
     * preserving the current type of that NamedObj.
     */
    Status = AcpiNsAttachObject (
        Info->FieldNode, ObjDesc, AcpiNsGetType (Info->FieldNode));

    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
        "Set NamedObj %p [%4.4s], ObjDesc %p\n",
        Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc));

    /* Remove local reference to the object */

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #17
0
ファイル: nsobject.c プロジェクト: 2asoft/freebsd
void
AcpiNsDetachObject (
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;


    ACPI_FUNCTION_TRACE (NsDetachObject);


    ObjDesc = Node->Object;

    if (!ObjDesc ||
        (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
    {
        return_VOID;
    }

    if (Node->Flags & ANOBJ_ALLOCATED_BUFFER)
    {
        /* Free the dynamic aml buffer */

        if (ObjDesc->Common.Type == ACPI_TYPE_METHOD)
        {
            ACPI_FREE (ObjDesc->Method.AmlStart);
        }
    }

    /* Clear the Node entry in all cases */

    Node->Object = NULL;
    if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND)
    {
        /* Unlink object from front of possible object list */

        Node->Object = ObjDesc->Common.NextObject;

        /* Handle possible 2-descriptor object */

        if (Node->Object &&
           (Node->Object->Common.Type != ACPI_TYPE_LOCAL_DATA))
        {
            Node->Object = Node->Object->Common.NextObject;
        }

        /*
         * Detach the object from any data objects (which are still held by
         * the namespace node)
         */
        if (ObjDesc->Common.NextObject &&
           ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA))
        {
           ObjDesc->Common.NextObject = NULL;
        }
    }

    /* Reset the node type to untyped */

    Node->Type = ACPI_TYPE_ANY;

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
        Node, AcpiUtGetNodeName (Node), ObjDesc));

    /* Remove one reference on the object (and all subobjects) */

    AcpiUtRemoveReference (ObjDesc);
    return_VOID;
}
コード例 #18
0
ファイル: dswscope.c プロジェクト: Alkzndr/freebsd
ACPI_STATUS
AcpiDsScopeStackPush (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_OBJECT_TYPE        Type,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_GENERIC_STATE      *ScopeInfo;
    ACPI_GENERIC_STATE      *OldScopeInfo;


    ACPI_FUNCTION_TRACE (DsScopeStackPush);


    if (!Node)
    {
        /* Invalid scope   */

        ACPI_ERROR ((AE_INFO, "Null scope parameter"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Make sure object type is valid */

    if (!AcpiUtValidObjectType (Type))
    {
        ACPI_WARNING ((AE_INFO,
            "Invalid object type: 0x%X", Type));
    }

    /* Allocate a new scope object */

    ScopeInfo = AcpiUtCreateGenericState ();
    if (!ScopeInfo)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Init new scope object */

    ScopeInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_WSCOPE;
    ScopeInfo->Scope.Node = Node;
    ScopeInfo->Common.Value = (UINT16) Type;

    WalkState->ScopeDepth++;

    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
        "[%.2d] Pushed scope ", (UINT32) WalkState->ScopeDepth));

    OldScopeInfo = WalkState->ScopeInfo;
    if (OldScopeInfo)
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
            "[%4.4s] (%s)",
            AcpiUtGetNodeName (OldScopeInfo->Scope.Node),
            AcpiUtGetTypeName (OldScopeInfo->Common.Value)));
    }
    else
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
            "[\\___] (%s)", "ROOT"));
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
        ", New scope -> [%4.4s] (%s)\n",
        AcpiUtGetNodeName (ScopeInfo->Scope.Node),
        AcpiUtGetTypeName (ScopeInfo->Common.Value)));

    /* Push new scope object onto stack */

    AcpiUtPushGenericState (&WalkState->ScopeInfo, ScopeInfo);
    return_ACPI_STATUS (AE_OK);
}
コード例 #19
0
ファイル: evregion.c プロジェクト: cloudius-systems/acpica
ACPI_STATUS
AcpiEvAddressSpaceDispatch (
    ACPI_OPERAND_OBJECT     *RegionObj,
    ACPI_OPERAND_OBJECT     *FieldObj,
    UINT32                  Function,
    UINT32                  RegionOffset,
    UINT32                  BitWidth,
    UINT64                  *Value)
{
    ACPI_STATUS             Status;
    ACPI_ADR_SPACE_HANDLER  Handler;
    ACPI_ADR_SPACE_SETUP    RegionSetup;
    ACPI_OPERAND_OBJECT     *HandlerDesc;
    ACPI_OPERAND_OBJECT     *RegionObj2;
    void                    *RegionContext = NULL;
    ACPI_CONNECTION_INFO    *Context;


    ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);


    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    if (!RegionObj2)
    {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /* Ensure that there is a handler associated with this region */

    HandlerDesc = RegionObj->Region.Handler;
    if (!HandlerDesc)
    {
        ACPI_ERROR ((AE_INFO,
            "No handler for Region [%4.4s] (%p) [%s]",
            AcpiUtGetNodeName (RegionObj->Region.Node),
            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    Context = HandlerDesc->AddressSpace.Context;

    /*
     * It may be the case that the region has never been initialized.
     * Some types of regions require special init code
     */
    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
    {
        /* This region has not been initialized yet, do it */

        RegionSetup = HandlerDesc->AddressSpace.Setup;
        if (!RegionSetup)
        {
            /* No initialization routine, exit with error */

            ACPI_ERROR ((AE_INFO,
                "No init routine for region(%p) [%s]",
                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (AE_NOT_EXIST);
        }

        /*
         * We must exit the interpreter because the region setup will
         * potentially execute control methods (for example, the _REG method
         * for this region)
         */
        AcpiExExitInterpreter ();

        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
                    Context, &RegionContext);

        /* Re-enter the interpreter */

        AcpiExEnterInterpreter ();

        /* Check for failure of the Region Setup */

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "During region initialization: [%s]",
                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (Status);
        }

        /* Region initialization may have been completed by RegionSetup */

        if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
        {
            RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;

            if (RegionObj2->Extra.RegionContext)
            {
                /* The handler for this region was already installed */

                ACPI_FREE (RegionContext);
            }
            else
            {
                /*
                 * Save the returned context for use in all accesses to
                 * this particular region
                 */
                RegionObj2->Extra.RegionContext = RegionContext;
            }
        }
    }

    /* We have everything we need, we can invoke the address space handler */

    Handler = HandlerDesc->AddressSpace.Handler;

    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
        &RegionObj->Region.Handler->AddressSpace, Handler,
        ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));


    /*
     * Special handling for GenericSerialBus and GeneralPurposeIo:
     * There are three extra parameters that must be passed to the
     * handler via the context:
     *   1) Connection buffer, a resource template from Connection() op.
     *   2) Length of the above buffer.
     *   3) Actual access length from the AccessAs() op.
     */
    if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) ||
            (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) &&
        Context &&
        FieldObj)
    {
        /* Get the Connection (ResourceTemplate) buffer */

        Context->Connection = FieldObj->Field.ResourceBuffer;
        Context->Length = FieldObj->Field.ResourceLength;
        Context->AccessLength = FieldObj->Field.AccessLength;
    }

    if (!(HandlerDesc->AddressSpace.HandlerFlags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * For handlers other than the default (supplied) handlers, we must
         * exit the interpreter because the handler *might* block -- we don't
         * know what it will do, so we can't hold the lock on the intepreter.
         */
        AcpiExExitInterpreter();
    }

    /* Call the handler */

    Status = Handler (Function,
        (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
        Context, RegionObj2->Extra.RegionContext);

    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
            AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    }

    if (!(HandlerDesc->AddressSpace.HandlerFlags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * We just returned from a non-default handler, we must re-enter the
         * interpreter
         */
       AcpiExEnterInterpreter ();
    }

    return_ACPI_STATUS (Status);
}
コード例 #20
0
ファイル: nsinit.c プロジェクト: BillTheBest/libuinet
static ACPI_STATUS
AcpiNsInitOneObject (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_OBJECT_TYPE        Type;
    ACPI_STATUS             Status = AE_OK;
    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ACPI_OPERAND_OBJECT     *ObjDesc;


    ACPI_FUNCTION_NAME (NsInitOneObject);


    Info->ObjectCount++;

    /* And even then, we are only interested in a few object types */

    Type = AcpiNsGetType (ObjHandle);
    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        return (AE_OK);
    }

    /* Increment counters for object types we are looking for */

    switch (Type)
    {
    case ACPI_TYPE_REGION:
        Info->OpRegionCount++;
        break;

    case ACPI_TYPE_BUFFER_FIELD:
        Info->FieldCount++;
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:
        Info->FieldCount++;
        break;

    case ACPI_TYPE_BUFFER:
        Info->BufferCount++;
        break;

    case ACPI_TYPE_PACKAGE:
        Info->PackageCount++;
        break;

    default:

        /* No init required, just exit now */
        return (AE_OK);
    }

    /* If the object is already initialized, nothing else to do */

    if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
    {
        return (AE_OK);
    }

    /* Must lock the interpreter before executing AML code */

    AcpiExEnterInterpreter ();

    /*
     * Each of these types can contain executable AML code within the
     * declaration.
     */
    switch (Type)
    {
    case ACPI_TYPE_REGION:

        Info->OpRegionInit++;
        Status = AcpiDsGetRegionArguments (ObjDesc);
        break;

    case ACPI_TYPE_BUFFER_FIELD:

        Info->FieldInit++;
        Status = AcpiDsGetBufferFieldArguments (ObjDesc);
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:

        Info->FieldInit++;
        Status = AcpiDsGetBankFieldArguments (ObjDesc);
        break;

    case ACPI_TYPE_BUFFER:

        Info->BufferInit++;
        Status = AcpiDsGetBufferArguments (ObjDesc);
        break;

    case ACPI_TYPE_PACKAGE:

        Info->PackageInit++;
        Status = AcpiDsGetPackageArguments (ObjDesc);
        break;

    default:
        /* No other types can get here */
        break;
    }

    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status,
            "Could not execute arguments for [%4.4s] (%s)",
            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
    }

    /*
     * Print a dot for each object unless we are going to print the entire
     * pathname
     */
    if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES))
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
    }

    /*
     * We ignore errors from above, and always return OK, since we don't want
     * to abort the walk on any single error.
     */
    AcpiExExitInterpreter ();
    return (AE_OK);
}
コード例 #21
0
ファイル: dsmethod.c プロジェクト: looncraz/haiku
ACPI_STATUS
AcpiDsRestartControlMethod (
    ACPI_WALK_STATE         *WalkState,
    ACPI_OPERAND_OBJECT     *ReturnDesc)
{
    ACPI_STATUS             Status;
    int                     SameAsImplicitReturn;


    ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);


    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
        AcpiUtGetNodeName (WalkState->MethodNode),
        WalkState->MethodCallOp, ReturnDesc));

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
        WalkState->ReturnUsed,
        WalkState->Results, WalkState));

    /* Did the called method return a value? */

    if (ReturnDesc)
    {
        /* Is the implicit return object the same as the return desc? */

        SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);

        /* Are we actually going to use the return value? */

        if (WalkState->ReturnUsed)
        {
            /* Save the return value from the previous method */

            Status = AcpiDsResultPush (ReturnDesc, WalkState);
            if (ACPI_FAILURE (Status))
            {
                AcpiUtRemoveReference (ReturnDesc);
                return_ACPI_STATUS (Status);
            }

            /*
             * Save as THIS method's return value in case it is returned
             * immediately to yet another method
             */
            WalkState->ReturnDesc = ReturnDesc;
        }

        /*
         * The following code is the optional support for the so-called
         * "implicit return". Some AML code assumes that the last value of the
         * method is "implicitly" returned to the caller, in the absence of an
         * explicit return value.
         *
         * Just save the last result of the method as the return value.
         *
         * NOTE: this is optional because the ASL language does not actually
         * support this behavior.
         */
        else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
                 SameAsImplicitReturn)
        {
            /*
             * Delete the return value if it will not be used by the
             * calling method or remove one reference if the explicit return
             * is the same as the implicit return value.
             */
            AcpiUtRemoveReference (ReturnDesc);
        }
    }

    return_ACPI_STATUS (AE_OK);
}
コード例 #22
0
void
AcpiDmDumpMethodInfo (
    ACPI_STATUS             Status,
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *Next;
    ACPI_THREAD_STATE       *Thread;
    ACPI_WALK_STATE         *NextWalkState;
    ACPI_NAMESPACE_NODE     *PreviousMethod = NULL;


    /* Ignore control codes, they are not errors */

    if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
    {
        return;
    }

    /* We may be executing a deferred opcode */

    if (WalkState->DeferredNode)
    {
        AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
        return;
    }

    /*
     * If there is no Thread, we are not actually executing a method.
     * This can happen when the iASL compiler calls the interpreter
     * to perform constant folding.
     */
    Thread = WalkState->Thread;
    if (!Thread)
    {
        return;
    }

    /* Display exception and method name */

    AcpiOsPrintf ("\n**** Exception %s during execution of method ",
        AcpiFormatException (Status));
    AcpiNsPrintNodePathname (WalkState->MethodNode, NULL);

    /* Display stack of executing methods */

    AcpiOsPrintf ("\n\nMethod Execution Stack:\n");
    NextWalkState = Thread->WalkStateList;

    /* Walk list of linked walk states */

    while (NextWalkState)
    {
        AcpiOsPrintf ("    Method [%4.4s] executing: ",
                AcpiUtGetNodeName (NextWalkState->MethodNode));

        /* First method is the currently executing method */

        if (NextWalkState == WalkState)
        {
            if (Op)
            {
                /* Display currently executing ASL statement */

                Next = Op->Common.Next;
                Op->Common.Next = NULL;

                AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX);
                Op->Common.Next = Next;
            }
        }
        else
        {
            /*
             * This method has called another method
             * NOTE: the method call parse subtree is already deleted at this
             * point, so we cannot disassemble the method invocation.
             */
            AcpiOsPrintf ("Call to method ");
            AcpiNsPrintNodePathname (PreviousMethod, NULL);
        }

        PreviousMethod = NextWalkState->MethodNode;
        NextWalkState = NextWalkState->Next;
        AcpiOsPrintf ("\n");
    }

    /* Display the method locals and arguments */

    AcpiOsPrintf ("\n");
    AcpiDmDisplayLocals (WalkState);
    AcpiOsPrintf ("\n");
    AcpiDmDisplayArguments (WalkState);
    AcpiOsPrintf ("\n");
}
コード例 #23
0
ファイル: nsaccess.c プロジェクト: Xeffyr/KolibriOS-Mod
ACPI_STATUS
AcpiNsLookup (
    ACPI_GENERIC_STATE      *ScopeInfo,
    char                    *Pathname,
    ACPI_OBJECT_TYPE        Type,
    ACPI_INTERPRETER_MODE   InterpreterMode,
    UINT32                  Flags,
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     **ReturnNode)
{
    ACPI_STATUS             Status;
    char                    *Path = Pathname;
    ACPI_NAMESPACE_NODE     *PrefixNode;
    ACPI_NAMESPACE_NODE     *CurrentNode = NULL;
    ACPI_NAMESPACE_NODE     *ThisNode = NULL;
    UINT32                  NumSegments;
    UINT32                  NumCarats;
    ACPI_NAME               SimpleName;
    ACPI_OBJECT_TYPE        TypeToCheckFor;
    ACPI_OBJECT_TYPE        ThisSearchType;
    UINT32                  SearchParentFlag = ACPI_NS_SEARCH_PARENT;
    UINT32                  LocalFlags;


    ACPI_FUNCTION_TRACE (NsLookup);


    if (!ReturnNode)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT);
    *ReturnNode = ACPI_ENTRY_NOT_FOUND;
    AcpiGbl_NsLookupCount++;

    if (!AcpiGbl_RootNode)
    {
        return_ACPI_STATUS (AE_NO_NAMESPACE);
    }

    /* Get the prefix scope. A null scope means use the root scope */

    if ((!ScopeInfo) ||
            (!ScopeInfo->Scope.Node))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                           "Null scope prefix, using root node (%p)\n",
                           AcpiGbl_RootNode));

        PrefixNode = AcpiGbl_RootNode;
    }
    else
    {
        PrefixNode = ScopeInfo->Scope.Node;
        if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED)
        {
            ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]",
                         PrefixNode, AcpiUtGetDescriptorName (PrefixNode)));
            return_ACPI_STATUS (AE_AML_INTERNAL);
        }

        if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE))
        {
            /*
             * This node might not be a actual "scope" node (such as a
             * Device/Method, etc.)  It could be a Package or other object
             * node. Backup up the tree to find the containing scope node.
             */
            while (!AcpiNsOpensScope (PrefixNode->Type) &&
                    PrefixNode->Type != ACPI_TYPE_ANY)
            {
                PrefixNode = PrefixNode->Parent;
            }
        }
    }

    /* Save type. TBD: may be no longer necessary */

    TypeToCheckFor = Type;

    /*
     * Begin examination of the actual pathname
     */
    if (!Pathname)
    {
        /* A Null NamePath is allowed and refers to the root */

        NumSegments = 0;
        ThisNode = AcpiGbl_RootNode;
        Path = "";

        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                           "Null Pathname (Zero segments), Flags=%X\n", Flags));
    }
    else
    {
        /*
         * Name pointer is valid (and must be in internal name format)
         *
         * Check for scope prefixes:
         *
         * As represented in the AML stream, a namepath consists of an
         * optional scope prefix followed by a name segment part.
         *
         * If present, the scope prefix is either a Root Prefix (in
         * which case the name is fully qualified), or one or more
         * Parent Prefixes (in which case the name's scope is relative
         * to the current scope).
         */
        if (*Path == (UINT8) AML_ROOT_PREFIX)
        {
            /* Pathname is fully qualified, start from the root */

            ThisNode = AcpiGbl_RootNode;
            SearchParentFlag = ACPI_NS_NO_UPSEARCH;

            /* Point to name segment part */

            Path++;

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                               "Path is absolute from root [%p]\n", ThisNode));
        }
        else
        {
            /* Pathname is relative to current scope, start there */

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                               "Searching relative to prefix scope [%4.4s] (%p)\n",
                               AcpiUtGetNodeName (PrefixNode), PrefixNode));

            /*
             * Handle multiple Parent Prefixes (carat) by just getting
             * the parent node for each prefix instance.
             */
            ThisNode = PrefixNode;
            NumCarats = 0;
            while (*Path == (UINT8) AML_PARENT_PREFIX)
            {
                /* Name is fully qualified, no search rules apply */

                SearchParentFlag = ACPI_NS_NO_UPSEARCH;

                /*
                 * Point past this prefix to the name segment
                 * part or the next Parent Prefix
                 */
                Path++;

                /* Backup to the parent node */

                NumCarats++;
                ThisNode = ThisNode->Parent;
                if (!ThisNode)
                {
                    /* Current scope has no parent scope */

                    ACPI_ERROR ((AE_INFO,
                                 "ACPI path has too many parent prefixes (^) "
                                 "- reached beyond root node"));
                    return_ACPI_STATUS (AE_NOT_FOUND);
                }
            }

            if (SearchParentFlag == ACPI_NS_NO_UPSEARCH)
            {
                ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                                   "Search scope is [%4.4s], path has %u carat(s)\n",
                                   AcpiUtGetNodeName (ThisNode), NumCarats));
            }
        }

        /*
         * Determine the number of ACPI name segments in this pathname.
         *
         * The segment part consists of either:
         *  - A Null name segment (0)
         *  - A DualNamePrefix followed by two 4-byte name segments
         *  - A MultiNamePrefix followed by a byte indicating the
         *      number of segments and the segments themselves.
         *  - A single 4-byte name segment
         *
         * Examine the name prefix opcode, if any, to determine the number of
         * segments.
         */
        switch (*Path)
        {
        case 0:
            /*
             * Null name after a root or parent prefixes. We already
             * have the correct target node and there are no name segments.
             */
            NumSegments  = 0;
            Type = ThisNode->Type;

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                               "Prefix-only Pathname (Zero name segments), Flags=%X\n",
                               Flags));
            break;

        case AML_DUAL_NAME_PREFIX:

            /* More than one NameSeg, search rules do not apply */

            SearchParentFlag = ACPI_NS_NO_UPSEARCH;

            /* Two segments, point to first name segment */

            NumSegments = 2;
            Path++;

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                               "Dual Pathname (2 segments, Flags=%X)\n", Flags));
            break;

        case AML_MULTI_NAME_PREFIX_OP:

            /* More than one NameSeg, search rules do not apply */

            SearchParentFlag = ACPI_NS_NO_UPSEARCH;

            /* Extract segment count, point to first name segment */

            Path++;
            NumSegments = (UINT32) (UINT8) *Path;
            Path++;

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                               "Multi Pathname (%u Segments, Flags=%X)\n",
                               NumSegments, Flags));
            break;

        default:
            /*
             * Not a Null name, no Dual or Multi prefix, hence there is
             * only one name segment and Pathname is already pointing to it.
             */
            NumSegments = 1;

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                               "Simple Pathname (1 segment, Flags=%X)\n", Flags));
            break;
        }

        ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path));
    }


    /*
     * Search namespace for each segment of the name. Loop through and
     * verify (or add to the namespace) each name segment.
     *
     * The object type is significant only at the last name
     * segment. (We don't care about the types along the path, only
     * the type of the final target object.)
     */
    ThisSearchType = ACPI_TYPE_ANY;
    CurrentNode = ThisNode;
    while (NumSegments && CurrentNode)
    {
        NumSegments--;
        if (!NumSegments)
        {
            /* This is the last segment, enable typechecking */

            ThisSearchType = Type;

            /*
             * Only allow automatic parent search (search rules) if the caller
             * requested it AND we have a single, non-fully-qualified NameSeg
             */
            if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) &&
                    (Flags & ACPI_NS_SEARCH_PARENT))
            {
                LocalFlags |= ACPI_NS_SEARCH_PARENT;
            }

            /* Set error flag according to caller */

            if (Flags & ACPI_NS_ERROR_IF_FOUND)
            {
                LocalFlags |= ACPI_NS_ERROR_IF_FOUND;
            }
        }

        /* Extract one ACPI name from the front of the pathname */

        ACPI_MOVE_32_TO_32 (&SimpleName, Path);

        /* Try to find the single (4 character) ACPI name */

        Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode,
                                       InterpreterMode, ThisSearchType, LocalFlags, &ThisNode);
        if (ACPI_FAILURE (Status))
        {
            if (Status == AE_NOT_FOUND)
            {
                /* Name not found in ACPI namespace */

                ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
                                   "Name [%4.4s] not found in scope [%4.4s] %p\n",
                                   (char *) &SimpleName, (char *) &CurrentNode->Name,
                                   CurrentNode));
            }

            *ReturnNode = ThisNode;
            return_ACPI_STATUS (Status);
        }

        /* More segments to follow? */

        if (NumSegments > 0)
        {
            /*
             * If we have an alias to an object that opens a scope (such as a
             * device or processor), we need to dereference the alias here so
             * that we can access any children of the original node (via the
             * remaining segments).
             */
            if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS)
            {
                if (!ThisNode->Object)
                {
                    return_ACPI_STATUS (AE_NOT_EXIST);
                }

                if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *)
                                       ThisNode->Object)->Type))
                {
                    ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object;
                }
            }
        }

        /* Special handling for the last segment (NumSegments == 0) */

        else
        {
            /*
             * Sanity typecheck of the target object:
             *
             * If 1) This is the last segment (NumSegments == 0)
             *    2) And we are looking for a specific type
             *       (Not checking for TYPE_ANY)
             *    3) Which is not an alias
             *    4) Which is not a local type (TYPE_SCOPE)
             *    5) And the type of target object is known (not TYPE_ANY)
             *    6) And target object does not match what we are looking for
             *
             * Then we have a type mismatch. Just warn and ignore it.
             */
            if ((TypeToCheckFor != ACPI_TYPE_ANY)                   &&
                    (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS)           &&
                    (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS)    &&
                    (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE)           &&
                    (ThisNode->Type != ACPI_TYPE_ANY)                   &&
                    (ThisNode->Type != TypeToCheckFor))
            {
                /* Complain about a type mismatch */

                ACPI_WARNING ((AE_INFO,
                               "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
                               ACPI_CAST_PTR (char, &SimpleName),
                               AcpiUtGetTypeName (ThisNode->Type),
                               AcpiUtGetTypeName (TypeToCheckFor)));
            }

            /*
             * If this is the last name segment and we are not looking for a
             * specific type, but the type of found object is known, use that
             * type to (later) see if it opens a scope.
             */
            if (Type == ACPI_TYPE_ANY)
            {
                Type = ThisNode->Type;
            }
        }

        /* Point to next name segment and make this node current */

        Path += ACPI_NAME_SIZE;
        CurrentNode = ThisNode;
    }
コード例 #24
0
ファイル: nsdump.c プロジェクト: 2asoft/freebsd
ACPI_STATUS
AcpiNsDumpOneObject (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_WALK_INFO          *Info = (ACPI_WALK_INFO *) Context;
    ACPI_NAMESPACE_NODE     *ThisNode;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_OBJECT_TYPE        ObjType;
    ACPI_OBJECT_TYPE        Type;
    UINT32                  BytesToDump;
    UINT32                  DbgLevel;
    UINT32                  i;


    ACPI_FUNCTION_NAME (NsDumpOneObject);


    /* Is output enabled? */

    if (!(AcpiDbgLevel & Info->DebugLevel))
    {
        return (AE_OK);
    }

    if (!ObjHandle)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n"));
        return (AE_OK);
    }

    ThisNode = AcpiNsValidateHandle (ObjHandle);
    if (!ThisNode)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Invalid object handle %p\n",
            ObjHandle));
        return (AE_OK);
    }

    Type = ThisNode->Type;

    /* Check if the owner matches */

    if ((Info->OwnerId != ACPI_OWNER_ID_MAX) &&
        (Info->OwnerId != ThisNode->OwnerId))
    {
        return (AE_OK);
    }

    if (!(Info->DisplayType & ACPI_DISPLAY_SHORT))
    {
        /* Indent the object according to the level */

        AcpiOsPrintf ("%2d%*s", (UINT32) Level - 1, (int) Level * 2, " ");

        /* Check the node type and name */

        if (Type > ACPI_TYPE_LOCAL_MAX)
        {
            ACPI_WARNING ((AE_INFO,
                "Invalid ACPI Object Type 0x%08X", Type));
        }

        AcpiOsPrintf ("%4.4s", AcpiUtGetNodeName (ThisNode));
    }

    /* Now we can print out the pertinent information */

    AcpiOsPrintf (" %-12s %p %2.2X ",
        AcpiUtGetTypeName (Type), ThisNode, ThisNode->OwnerId);

    DbgLevel = AcpiDbgLevel;
    AcpiDbgLevel = 0;
    ObjDesc = AcpiNsGetAttachedObject (ThisNode);
    AcpiDbgLevel = DbgLevel;

    /* Temp nodes are those nodes created by a control method */

    if (ThisNode->Flags & ANOBJ_TEMPORARY)
    {
        AcpiOsPrintf ("(T) ");
    }

    switch (Info->DisplayType & ACPI_DISPLAY_MASK)
    {
    case ACPI_DISPLAY_SUMMARY:

        if (!ObjDesc)
        {
            /* No attached object. Some types should always have an object */

            switch (Type)
            {
            case ACPI_TYPE_INTEGER:
            case ACPI_TYPE_PACKAGE:
            case ACPI_TYPE_BUFFER:
            case ACPI_TYPE_STRING:
            case ACPI_TYPE_METHOD:

                AcpiOsPrintf ("<No attached object>");
                break;

            default:

                break;
            }

            AcpiOsPrintf ("\n");
            return (AE_OK);
        }

        switch (Type)
        {
        case ACPI_TYPE_PROCESSOR:

            AcpiOsPrintf ("ID %02X Len %02X Addr %8.8X%8.8X\n",
                ObjDesc->Processor.ProcId, ObjDesc->Processor.Length,
                ACPI_FORMAT_UINT64 (ObjDesc->Processor.Address));
            break;

        case ACPI_TYPE_DEVICE:

            AcpiOsPrintf ("Notify Object: %p\n", ObjDesc);
            break;

        case ACPI_TYPE_METHOD:

            AcpiOsPrintf ("Args %X Len %.4X Aml %p\n",
                (UINT32) ObjDesc->Method.ParamCount,
                ObjDesc->Method.AmlLength, ObjDesc->Method.AmlStart);
            break;

        case ACPI_TYPE_INTEGER:

            AcpiOsPrintf ("= %8.8X%8.8X\n",
                ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
            break;

        case ACPI_TYPE_PACKAGE:

            if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
            {
                AcpiOsPrintf ("Elements %.2X\n",
                    ObjDesc->Package.Count);
            }
            else
            {
                AcpiOsPrintf ("[Length not yet evaluated]\n");
            }
            break;

        case ACPI_TYPE_BUFFER:

            if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
            {
                AcpiOsPrintf ("Len %.2X",
                    ObjDesc->Buffer.Length);

                /* Dump some of the buffer */

                if (ObjDesc->Buffer.Length > 0)
                {
                    AcpiOsPrintf (" =");
                    for (i = 0; (i < ObjDesc->Buffer.Length && i < 12); i++)
                    {
                        AcpiOsPrintf (" %.2hX", ObjDesc->Buffer.Pointer[i]);
                    }
                }
                AcpiOsPrintf ("\n");
            }
            else
            {
                AcpiOsPrintf ("[Length not yet evaluated]\n");
            }
            break;

        case ACPI_TYPE_STRING:

            AcpiOsPrintf ("Len %.2X ", ObjDesc->String.Length);
            AcpiUtPrintString (ObjDesc->String.Pointer, 80);
            AcpiOsPrintf ("\n");
            break;

        case ACPI_TYPE_REGION:

            AcpiOsPrintf ("[%s]",
                AcpiUtGetRegionName (ObjDesc->Region.SpaceId));
            if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID)
            {
                AcpiOsPrintf (" Addr %8.8X%8.8X Len %.4X\n",
                    ACPI_FORMAT_UINT64 (ObjDesc->Region.Address),
                    ObjDesc->Region.Length);
            }
            else
            {
                AcpiOsPrintf (" [Address/Length not yet evaluated]\n");
            }
            break;

        case ACPI_TYPE_LOCAL_REFERENCE:

            AcpiOsPrintf ("[%s]\n", AcpiUtGetReferenceName (ObjDesc));
            break;

        case ACPI_TYPE_BUFFER_FIELD:

            if (ObjDesc->BufferField.BufferObj &&
                ObjDesc->BufferField.BufferObj->Buffer.Node)
            {
                AcpiOsPrintf ("Buf [%4.4s]",
                    AcpiUtGetNodeName (
                        ObjDesc->BufferField.BufferObj->Buffer.Node));
            }
            break;

        case ACPI_TYPE_LOCAL_REGION_FIELD:

            AcpiOsPrintf ("Rgn [%4.4s]",
                AcpiUtGetNodeName (
                    ObjDesc->CommonField.RegionObj->Region.Node));
            break;

        case ACPI_TYPE_LOCAL_BANK_FIELD:

            AcpiOsPrintf ("Rgn [%4.4s] Bnk [%4.4s]",
                AcpiUtGetNodeName (
                    ObjDesc->CommonField.RegionObj->Region.Node),
                AcpiUtGetNodeName (
                    ObjDesc->BankField.BankObj->CommonField.Node));
            break;

        case ACPI_TYPE_LOCAL_INDEX_FIELD:

            AcpiOsPrintf ("Idx [%4.4s] Dat [%4.4s]",
                AcpiUtGetNodeName (
                    ObjDesc->IndexField.IndexObj->CommonField.Node),
                AcpiUtGetNodeName (
                    ObjDesc->IndexField.DataObj->CommonField.Node));
            break;

        case ACPI_TYPE_LOCAL_ALIAS:
        case ACPI_TYPE_LOCAL_METHOD_ALIAS:

            AcpiOsPrintf ("Target %4.4s (%p)\n",
                AcpiUtGetNodeName (ObjDesc), ObjDesc);
            break;

        default:

            AcpiOsPrintf ("Object %p\n", ObjDesc);
            break;
        }

        /* Common field handling */

        switch (Type)
        {
        case ACPI_TYPE_BUFFER_FIELD:
        case ACPI_TYPE_LOCAL_REGION_FIELD:
        case ACPI_TYPE_LOCAL_BANK_FIELD:
        case ACPI_TYPE_LOCAL_INDEX_FIELD:

            AcpiOsPrintf (" Off %.3X Len %.2X Acc %.2hd\n",
                (ObjDesc->CommonField.BaseByteOffset * 8)
                    + ObjDesc->CommonField.StartFieldBitOffset,
                ObjDesc->CommonField.BitLength,
                ObjDesc->CommonField.AccessByteWidth);
            break;

        default:

            break;
        }
        break;

    case ACPI_DISPLAY_OBJECTS:

        AcpiOsPrintf ("O:%p", ObjDesc);
        if (!ObjDesc)
        {
            /* No attached object, we are done */

            AcpiOsPrintf ("\n");
            return (AE_OK);
        }

        AcpiOsPrintf ("(R%u)", ObjDesc->Common.ReferenceCount);

        switch (Type)
        {
        case ACPI_TYPE_METHOD:

            /* Name is a Method and its AML offset/length are set */

            AcpiOsPrintf (" M:%p-%X\n", ObjDesc->Method.AmlStart,
                ObjDesc->Method.AmlLength);
            break;

        case ACPI_TYPE_INTEGER:

            AcpiOsPrintf (" I:%8.8X8.8%X\n",
                ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
            break;

        case ACPI_TYPE_STRING:

            AcpiOsPrintf (" S:%p-%X\n", ObjDesc->String.Pointer,
                ObjDesc->String.Length);
            break;

        case ACPI_TYPE_BUFFER:

            AcpiOsPrintf (" B:%p-%X\n", ObjDesc->Buffer.Pointer,
                ObjDesc->Buffer.Length);
            break;

        default:

            AcpiOsPrintf ("\n");
            break;
        }
        break;

    default:
        AcpiOsPrintf ("\n");
        break;
    }

    /* If debug turned off, done */

    if (!(AcpiDbgLevel & ACPI_LV_VALUES))
    {
        return (AE_OK);
    }

    /* If there is an attached object, display it */

    DbgLevel = AcpiDbgLevel;
    AcpiDbgLevel = 0;
    ObjDesc = AcpiNsGetAttachedObject (ThisNode);
    AcpiDbgLevel = DbgLevel;

    /* Dump attached objects */

    while (ObjDesc)
    {
        ObjType = ACPI_TYPE_INVALID;
        AcpiOsPrintf ("Attached Object %p: ", ObjDesc);

        /* Decode the type of attached object and dump the contents */

        switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
        {
        case ACPI_DESC_TYPE_NAMED:

            AcpiOsPrintf ("(Ptr to Node)\n");
            BytesToDump = sizeof (ACPI_NAMESPACE_NODE);
            ACPI_DUMP_BUFFER (ObjDesc, BytesToDump);
            break;

        case ACPI_DESC_TYPE_OPERAND:

            ObjType = ObjDesc->Common.Type;

            if (ObjType > ACPI_TYPE_LOCAL_MAX)
            {
                AcpiOsPrintf (
                    "(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
                    ObjType);

                BytesToDump = 32;
            }
            else
            {
                AcpiOsPrintf (
                    "(Pointer to ACPI Object type %.2X [%s])\n",
                    ObjType, AcpiUtGetTypeName (ObjType));

                BytesToDump = sizeof (ACPI_OPERAND_OBJECT);
            }

            ACPI_DUMP_BUFFER (ObjDesc, BytesToDump);
            break;

        default:

            break;
        }

        /* If value is NOT an internal object, we are done */

        if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND)
        {
            goto Cleanup;
        }

        /* Valid object, get the pointer to next level, if any */

        switch (ObjType)
        {
        case ACPI_TYPE_BUFFER:
        case ACPI_TYPE_STRING:
            /*
             * NOTE: takes advantage of common fields between string/buffer
             */
            BytesToDump = ObjDesc->String.Length;
            ObjDesc = (void *) ObjDesc->String.Pointer;

            AcpiOsPrintf ("(Buffer/String pointer %p length %X)\n",
                ObjDesc, BytesToDump);
            ACPI_DUMP_BUFFER (ObjDesc, BytesToDump);
            goto Cleanup;

        case ACPI_TYPE_BUFFER_FIELD:

            ObjDesc = (ACPI_OPERAND_OBJECT *) ObjDesc->BufferField.BufferObj;
            break;

        case ACPI_TYPE_PACKAGE:

            ObjDesc = (void *) ObjDesc->Package.Elements;
            break;

        case ACPI_TYPE_METHOD:

            ObjDesc = (void *) ObjDesc->Method.AmlStart;
            break;

        case ACPI_TYPE_LOCAL_REGION_FIELD:

            ObjDesc = (void *) ObjDesc->Field.RegionObj;
            break;

        case ACPI_TYPE_LOCAL_BANK_FIELD:

            ObjDesc = (void *) ObjDesc->BankField.RegionObj;
            break;

        case ACPI_TYPE_LOCAL_INDEX_FIELD:

            ObjDesc = (void *) ObjDesc->IndexField.IndexObj;
            break;

        default:

            goto Cleanup;
        }

        ObjType = ACPI_TYPE_INVALID;   /* Terminate loop after next pass */
    }

Cleanup:
    AcpiOsPrintf ("\n");
    return (AE_OK);
}
コード例 #25
0
ファイル: dsopcode.c プロジェクト: hoangduit/reactos
static ACPI_STATUS
AcpiDsInitBufferField (
    UINT16                  AmlOpcode,
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_OPERAND_OBJECT     *BufferDesc,
    ACPI_OPERAND_OBJECT     *OffsetDesc,
    ACPI_OPERAND_OBJECT     *LengthDesc,
    ACPI_OPERAND_OBJECT     *ResultDesc)
{
    UINT32                  Offset;
    UINT32                  BitOffset;
    UINT32                  BitCount;
    UINT8                   FieldFlags;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc);


    /* Host object must be a Buffer */

    if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER)
    {
        ACPI_ERROR ((AE_INFO,
            "Target of Create Field is not a Buffer object - %s",
            AcpiUtGetObjectTypeName (BufferDesc)));

        Status = AE_AML_OPERAND_TYPE;
        goto Cleanup;
    }

    /*
     * The last parameter to all of these opcodes (ResultDesc) started
     * out as a NameString, and should therefore now be a NS node
     * after resolution in AcpiExResolveOperands().
     */
    if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED)
    {
        ACPI_ERROR ((AE_INFO,
            "(%s) destination not a NS Node [%s]",
            AcpiPsGetOpcodeName (AmlOpcode),
            AcpiUtGetDescriptorName (ResultDesc)));

        Status = AE_AML_OPERAND_TYPE;
        goto Cleanup;
    }

    Offset = (UINT32) OffsetDesc->Integer.Value;

    /*
     * Setup the Bit offsets and counts, according to the opcode
     */
    switch (AmlOpcode)
    {
    case AML_CREATE_FIELD_OP:

        /* Offset is in bits, count is in bits */

        FieldFlags = AML_FIELD_ACCESS_BYTE;
        BitOffset  = Offset;
        BitCount   = (UINT32) LengthDesc->Integer.Value;

        /* Must have a valid (>0) bit count */

        if (BitCount == 0)
        {
            ACPI_ERROR ((AE_INFO,
                "Attempt to CreateField of length zero"));
            Status = AE_AML_OPERAND_VALUE;
            goto Cleanup;
        }
        break;

    case AML_CREATE_BIT_FIELD_OP:

        /* Offset is in bits, Field is one bit */

        BitOffset  = Offset;
        BitCount   = 1;
        FieldFlags = AML_FIELD_ACCESS_BYTE;
        break;

    case AML_CREATE_BYTE_FIELD_OP:

        /* Offset is in bytes, field is one byte */

        BitOffset  = 8 * Offset;
        BitCount   = 8;
        FieldFlags = AML_FIELD_ACCESS_BYTE;
        break;

    case AML_CREATE_WORD_FIELD_OP:

        /* Offset is in bytes, field is one word */

        BitOffset  = 8 * Offset;
        BitCount   = 16;
        FieldFlags = AML_FIELD_ACCESS_WORD;
        break;

    case AML_CREATE_DWORD_FIELD_OP:

        /* Offset is in bytes, field is one dword */

        BitOffset  = 8 * Offset;
        BitCount   = 32;
        FieldFlags = AML_FIELD_ACCESS_DWORD;
        break;

    case AML_CREATE_QWORD_FIELD_OP:

        /* Offset is in bytes, field is one qword */

        BitOffset  = 8 * Offset;
        BitCount   = 64;
        FieldFlags = AML_FIELD_ACCESS_QWORD;
        break;

    default:

        ACPI_ERROR ((AE_INFO,
            "Unknown field creation opcode 0x%02X",
            AmlOpcode));
        Status = AE_AML_BAD_OPCODE;
        goto Cleanup;
    }

    /* Entire field must fit within the current length of the buffer */

    if ((BitOffset + BitCount) >
        (8 * (UINT32) BufferDesc->Buffer.Length))
    {
        ACPI_ERROR ((AE_INFO,
            "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",
            AcpiUtGetNodeName (ResultDesc),
            BitOffset + BitCount,
            AcpiUtGetNodeName (BufferDesc->Buffer.Node),
            8 * (UINT32) BufferDesc->Buffer.Length));
        Status = AE_AML_BUFFER_LIMIT;
        goto Cleanup;
    }

    /*
     * Initialize areas of the field object that are common to all fields
     * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK),
     * UPDATE_RULE = 0 (UPDATE_PRESERVE)
     */
    Status = AcpiExPrepCommonFieldObject (ObjDesc, FieldFlags, 0,
                                            BitOffset, BitCount);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

    ObjDesc->BufferField.BufferObj = BufferDesc;

    /* Reference count for BufferDesc inherits ObjDesc count */

    BufferDesc->Common.ReferenceCount = (UINT16)
        (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount);


Cleanup:

    /* Always delete the operands */

    AcpiUtRemoveReference (OffsetDesc);
    AcpiUtRemoveReference (BufferDesc);

    if (AmlOpcode == AML_CREATE_FIELD_OP)
    {
        AcpiUtRemoveReference (LengthDesc);
    }

    /* On failure, delete the result descriptor */

    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ResultDesc);     /* Result descriptor */
    }
    else
    {
        /* Now the address and length are valid for this BufferField */

        ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID;
    }

    return_ACPI_STATUS (Status);
}
コード例 #26
0
ファイル: dsinit.c プロジェクト: BillTheBest/libuinet
static ACPI_STATUS
AcpiDsInitOneObject (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ACPI_OBJECT_TYPE        Type;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_ENTRY ();


    /*
     * We are only interested in NS nodes owned by the table that
     * was just loaded
     */
    if (Node->OwnerId != Info->OwnerId)
    {
        return (AE_OK);
    }

    Info->ObjectCount++;

    /* And even then, we are only interested in a few object types */

    Type = AcpiNsGetType (ObjHandle);

    switch (Type)
    {
    case ACPI_TYPE_REGION:

        Status = AcpiDsInitializeRegion (ObjHandle);
        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "During Region initialization %p [%4.4s]",
                ObjHandle, AcpiUtGetNodeName (ObjHandle)));
        }

        Info->OpRegionCount++;
        break;


    case ACPI_TYPE_METHOD:

        Info->MethodCount++;
        break;


    case ACPI_TYPE_DEVICE:

        Info->DeviceCount++;
        break;


    default:
        break;
    }

    /*
     * We ignore errors from above, and always return OK, since
     * we don't want to abort the walk on a single error.
     */
    return (AE_OK);
}
コード例 #27
0
ファイル: exfldio.c プロジェクト: CSRedRat/reactos
static ACPI_STATUS
AcpiExSetupRegion (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    UINT32                  FieldDatumByteOffset)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *RgnDesc;
    UINT8                   SpaceId;


    ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);


    RgnDesc = ObjDesc->CommonField.RegionObj;

    /* We must have a valid region */

    if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
    {
        ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
            RgnDesc->Common.Type,
            AcpiUtGetObjectTypeName (RgnDesc)));

        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    }

    SpaceId = RgnDesc->Region.SpaceId;

    /* Validate the Space ID */

    if (!AcpiIsValidSpaceId (SpaceId))
    {
        ACPI_ERROR ((AE_INFO,
            "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
        return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
    }

    /*
     * If the Region Address and Length have not been previously evaluated,
     * evaluate them now and save the results.
     */
    if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
    {
        Status = AcpiDsGetRegionArguments (RgnDesc);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
    }

    /*
     * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
     * address space and the request cannot be directly validated
     */
    if (SpaceId == ACPI_ADR_SPACE_SMBUS ||
        SpaceId == ACPI_ADR_SPACE_GSBUS ||
        SpaceId == ACPI_ADR_SPACE_IPMI)
    {
        /* SMBus or IPMI has a non-linear address space */

        return_ACPI_STATUS (AE_OK);
    }

#ifdef ACPI_UNDER_DEVELOPMENT
    /*
     * If the Field access is AnyAcc, we can now compute the optimal
     * access (because we know know the length of the parent region)
     */
    if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
    {
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
    }
#endif

    /*
     * Validate the request. The entire request from the byte offset for a
     * length of one field datum (access width) must fit within the region.
     * (Region length is specified in bytes)
     */
    if (RgnDesc->Region.Length <
        (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
        ObjDesc->CommonField.AccessByteWidth))
    {
        if (AcpiGbl_EnableInterpreterSlack)
        {
            /*
             * Slack mode only:  We will go ahead and allow access to this
             * field if it is within the region length rounded up to the next
             * access width boundary. ACPI_SIZE cast for 64-bit compile.
             */
            if (ACPI_ROUND_UP (RgnDesc->Region.Length,
                    ObjDesc->CommonField.AccessByteWidth) >=
                ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
                    ObjDesc->CommonField.AccessByteWidth +
                    FieldDatumByteOffset))
            {
                return_ACPI_STATUS (AE_OK);
            }
        }

        if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
        {
            /*
             * This is the case where the AccessType (AccWord, etc.) is wider
             * than the region itself. For example, a region of length one
             * byte, and a field with Dword access specified.
             */
            ACPI_ERROR ((AE_INFO,
                "Field [%4.4s] access width (%u bytes) "
                "too large for region [%4.4s] (length %u)",
                AcpiUtGetNodeName (ObjDesc->CommonField.Node),
                ObjDesc->CommonField.AccessByteWidth,
                AcpiUtGetNodeName (RgnDesc->Region.Node),
                RgnDesc->Region.Length));
        }

        /*
         * Offset rounded up to next multiple of field width
         * exceeds region length, indicate an error
         */
        ACPI_ERROR ((AE_INFO,
            "Field [%4.4s] Base+Offset+Width %u+%u+%u "
            "is beyond end of region [%4.4s] (length %u)",
            AcpiUtGetNodeName (ObjDesc->CommonField.Node),
            ObjDesc->CommonField.BaseByteOffset,
            FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
            AcpiUtGetNodeName (RgnDesc->Region.Node),
            RgnDesc->Region.Length));

        return_ACPI_STATUS (AE_AML_REGION_LIMIT);
    }

    return_ACPI_STATUS (AE_OK);
}
コード例 #28
0
ACPI_STATUS
AcpiEvInstallSpaceHandler (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_ADR_SPACE_TYPE     SpaceId,
    ACPI_ADR_SPACE_HANDLER  Handler,
    ACPI_ADR_SPACE_SETUP    Setup,
    void                    *Context)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        Type;
    UINT8                  Flags = 0;


    ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);


    /*
     * This registration is valid for only the types below and the root. This
     * is where the default handlers get placed.
     */
    if ((Node->Type != ACPI_TYPE_DEVICE)     &&
        (Node->Type != ACPI_TYPE_PROCESSOR)  &&
        (Node->Type != ACPI_TYPE_THERMAL)    &&
        (Node != AcpiGbl_RootNode))
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    if (Handler == ACPI_DEFAULT_HANDLER)
    {
        Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;

        switch (SpaceId)
        {
        case ACPI_ADR_SPACE_SYSTEM_MEMORY:

            Handler = AcpiExSystemMemorySpaceHandler;
            Setup   = AcpiEvSystemMemoryRegionSetup;
            break;

        case ACPI_ADR_SPACE_SYSTEM_IO:

            Handler = AcpiExSystemIoSpaceHandler;
            Setup   = AcpiEvIoSpaceRegionSetup;
            break;

        case ACPI_ADR_SPACE_PCI_CONFIG:

            Handler = AcpiExPciConfigSpaceHandler;
            Setup   = AcpiEvPciConfigRegionSetup;
            break;

        case ACPI_ADR_SPACE_CMOS:

            Handler = AcpiExCmosSpaceHandler;
            Setup   = AcpiEvCmosRegionSetup;
            break;

        case ACPI_ADR_SPACE_PCI_BAR_TARGET:

            Handler = AcpiExPciBarSpaceHandler;
            Setup   = AcpiEvPciBarRegionSetup;
            break;

        case ACPI_ADR_SPACE_DATA_TABLE:

            Handler = AcpiExDataTableSpaceHandler;
            Setup   = NULL;
            break;

        default:

            Status = AE_BAD_PARAMETER;
            goto UnlockAndExit;
        }
    }

    /* If the caller hasn't specified a setup routine, use the default */

    if (!Setup)
    {
        Setup = AcpiEvDefaultRegionSetup;
    }

    /* Check for an existing internal object */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (ObjDesc)
    {
        /*
         * The attached device object already exists. Make sure the handler
         * is not already installed.
         */
        HandlerObj = ObjDesc->Device.Handler;

        /* Walk the handler list for this device */

        while (HandlerObj)
        {
            /* Same SpaceId indicates a handler already installed */

            if (HandlerObj->AddressSpace.SpaceId == SpaceId)
            {
                if (HandlerObj->AddressSpace.Handler == Handler)
                {
                    /*
                     * It is (relatively) OK to attempt to install the SAME
                     * handler twice. This can easily happen with the
                     * PCI_Config space.
                     */
                    Status = AE_SAME_HANDLER;
                    goto UnlockAndExit;
                }
                else
                {
                    /* A handler is already installed */

                    Status = AE_ALREADY_EXISTS;
                }
                goto UnlockAndExit;
            }

            /* Walk the linked list of handlers */

            HandlerObj = HandlerObj->AddressSpace.Next;
        }
    }
    else
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
            "Creating object on Device %p while installing handler\n", Node));

        /* ObjDesc does not exist, create one */

        if (Node->Type == ACPI_TYPE_ANY)
        {
            Type = ACPI_TYPE_DEVICE;
        }
        else
        {
            Type = Node->Type;
        }

        ObjDesc = AcpiUtCreateInternalObject (Type);
        if (!ObjDesc)
        {
            Status = AE_NO_MEMORY;
            goto UnlockAndExit;
        }

        /* Init new descriptor */

        ObjDesc->Common.Type = (UINT8) Type;

        /* Attach the new object to the Node */

        Status = AcpiNsAttachObject (Node, ObjDesc, Type);

        /* Remove local reference to the object */

        AcpiUtRemoveReference (ObjDesc);

        if (ACPI_FAILURE (Status))
        {
            goto UnlockAndExit;
        }
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
        AcpiUtGetRegionName (SpaceId), SpaceId,
        AcpiUtGetNodeName (Node), Node, ObjDesc));

    /*
     * Install the handler
     *
     * At this point there is no existing handler. Just allocate the object
     * for the handler and link it into the list.
     */
    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
    if (!HandlerObj)
    {
        Status = AE_NO_MEMORY;
        goto UnlockAndExit;
    }

    /* Init handler obj */

    HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
    HandlerObj->AddressSpace.HandlerFlags = Flags;
    HandlerObj->AddressSpace.RegionList = NULL;
    HandlerObj->AddressSpace.Node = Node;
    HandlerObj->AddressSpace.Handler = Handler;
    HandlerObj->AddressSpace.Context = Context;
    HandlerObj->AddressSpace.Setup  = Setup;

    /* Install at head of Device.AddressSpace list */

    HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;

    /*
     * The Device object is the first reference on the HandlerObj.
     * Each region that uses the handler adds a reference.
     */
    ObjDesc->Device.Handler = HandlerObj;

    /*
     * Walk the namespace finding all of the regions this
     * handler will manage.
     *
     * Start at the device and search the branch toward
     * the leaf nodes until either the leaf is encountered or
     * a device is detected that has an address handler of the
     * same type.
     *
     * In either case, back up and search down the remainder
     * of the branch
     */
    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
                ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
                HandlerObj, NULL);

UnlockAndExit:
    return_ACPI_STATUS (Status);
}
コード例 #29
0
ACPI_STATUS
AcpiEvPciConfigRegionSetup (
    ACPI_HANDLE             Handle,
    UINT32                  Function,
    void                    *HandlerContext,
    void                    **RegionContext)
{
    ACPI_STATUS             Status = AE_OK;
    UINT64                  PciValue;
    ACPI_PCI_ID             *PciId = *RegionContext;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_NAMESPACE_NODE     *ParentNode;
    ACPI_NAMESPACE_NODE     *PciRootNode;
    ACPI_NAMESPACE_NODE     *PciDeviceNode;
    ACPI_OPERAND_OBJECT     *RegionObj = (ACPI_OPERAND_OBJECT  *) Handle;


    ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup);


    HandlerObj = RegionObj->Region.Handler;
    if (!HandlerObj)
    {
        /*
         * No installed handler. This shouldn't happen because the dispatch
         * routine checks before we get here, but we check again just in case.
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
            "Attempting to init a region %p, with no handler\n", RegionObj));
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    *RegionContext = NULL;
    if (Function == ACPI_REGION_DEACTIVATE)
    {
        if (PciId)
        {
            ACPI_FREE (PciId);
        }
        return_ACPI_STATUS (Status);
    }

    ParentNode = RegionObj->Region.Node->Parent;

    /*
     * Get the _SEG and _BBN values from the device upon which the handler
     * is installed.
     *
     * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
     * This is the device the handler has been registered to handle.
     */

    /*
     * If the AddressSpace.Node is still pointing to the root, we need
     * to scan upward for a PCI Root bridge and re-associate the OpRegion
     * handlers with that device.
     */
    if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode)
    {
        /* Start search from the parent object */

        PciRootNode = ParentNode;
        while (PciRootNode != AcpiGbl_RootNode)
        {
            /* Get the _HID/_CID in order to detect a RootBridge */

            if (AcpiEvIsPciRootBridge (PciRootNode))
            {
                /* Install a handler for this PCI root bridge */

                Status = AcpiInstallAddressSpaceHandler (
                            (ACPI_HANDLE) PciRootNode,
                            ACPI_ADR_SPACE_PCI_CONFIG,
                            ACPI_DEFAULT_HANDLER, NULL, NULL);
                if (ACPI_FAILURE (Status))
                {
                    if (Status == AE_SAME_HANDLER)
                    {
                        /*
                         * It is OK if the handler is already installed on the
                         * root bridge. Still need to return a context object
                         * for the new PCI_Config operation region, however.
                         */
                        Status = AE_OK;
                    }
                    else
                    {
                        ACPI_EXCEPTION ((AE_INFO, Status,
                            "Could not install PciConfig handler "
                            "for Root Bridge %4.4s",
                            AcpiUtGetNodeName (PciRootNode)));
                    }
                }
                break;
            }

            PciRootNode = PciRootNode->Parent;
        }

        /* PCI root bridge not found, use namespace root node */
    }
    else
    {
        PciRootNode = HandlerObj->AddressSpace.Node;
    }

    /*
     * If this region is now initialized, we are done.
     * (InstallAddressSpaceHandler could have initialized it)
     */
    if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Region is still not initialized. Create a new context */

    PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID));
    if (!PciId)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /*
     * For PCI_Config space access, we need the segment, bus, device and
     * function numbers. Acquire them here.
     *
     * Find the parent device object. (This allows the operation region to be
     * within a subscope under the device, such as a control method.)
     */
    PciDeviceNode = RegionObj->Region.Node;
    while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE))
    {
        PciDeviceNode = PciDeviceNode->Parent;
    }

    if (!PciDeviceNode)
    {
        ACPI_FREE (PciId);
        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    }

    /*
     * Get the PCI device and function numbers from the _ADR object
     * contained in the parent's scope.
     */
    Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR,
                PciDeviceNode, &PciValue);

    /*
     * The default is zero, and since the allocation above zeroed the data,
     * just do nothing on failure.
     */
    if (ACPI_SUCCESS (Status))
    {
        PciId->Device   = ACPI_HIWORD (ACPI_LODWORD (PciValue));
        PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue));
    }

    /* The PCI segment number comes from the _SEG method */

    Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG,
                PciRootNode, &PciValue);
    if (ACPI_SUCCESS (Status))
    {
        PciId->Segment = ACPI_LOWORD (PciValue);
    }

    /* The PCI bus number comes from the _BBN method */

    Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN,
                PciRootNode, &PciValue);
    if (ACPI_SUCCESS (Status))
    {
        PciId->Bus = ACPI_LOWORD (PciValue);
    }

    /* Complete/update the PCI ID for this device */

    Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (PciId);
        return_ACPI_STATUS (Status);
    }

    *RegionContext = PciId;
    return_ACPI_STATUS (AE_OK);
}
コード例 #30
0
ファイル: exmutex.c プロジェクト: Lxg1582/freebsd
ACPI_STATUS
AcpiExReleaseMutex (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    UINT8                   PreviousSyncLevel;
    ACPI_THREAD_STATE       *OwnerThread;


    ACPI_FUNCTION_TRACE (ExReleaseMutex);


    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    OwnerThread = ObjDesc->Mutex.OwnerThread;

    /* The mutex must have been previously acquired in order to release it */

    if (!OwnerThread)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot release Mutex [%4.4s], not acquired",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
    }

    /* Must have a valid thread ID */

    if (!WalkState->Thread)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot release Mutex [%4.4s], null thread info",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node)));
        return_ACPI_STATUS (AE_AML_INTERNAL);
    }

    /*
     * The Mutex is owned, but this thread must be the owner.
     * Special case for Global Lock, any thread can release
     */
    if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) &&
        (ObjDesc != AcpiGbl_GlobalLockMutex))
    {
        ACPI_ERROR ((AE_INFO,
            "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
            (UINT32) WalkState->Thread->ThreadId,
            AcpiUtGetNodeName (ObjDesc->Mutex.Node),
            (UINT32) OwnerThread->ThreadId));
        return_ACPI_STATUS (AE_AML_NOT_OWNER);
    }

    /*
     * The sync level of the mutex must be equal to the current sync level. In
     * other words, the current level means that at least one mutex at that
     * level is currently being held. Attempting to release a mutex of a
     * different level can only mean that the mutex ordering rule is being
     * violated. This behavior is clarified in ACPI 4.0 specification.
     */
    if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel)
    {
        ACPI_ERROR ((AE_INFO,
            "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
            AcpiUtGetNodeName (ObjDesc->Mutex.Node),
            ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel));
        return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
    }

    /*
     * Get the previous SyncLevel from the head of the acquired mutex list.
     * This handles the case where several mutexes at the same level have been
     * acquired, but are not released in reverse order.
     */
    PreviousSyncLevel =
        OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel;

    Status = AcpiExReleaseMutexObject (ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    if (ObjDesc->Mutex.AcquisitionDepth == 0)
    {
        /* Restore the previous SyncLevel */

        OwnerThread->CurrentSyncLevel = PreviousSyncLevel;
    }

    return_ACPI_STATUS (Status);
}