コード例 #1
0
ACPI_STATUS
AcpiUtEvaluateNumericObject (
    char                    *ObjectName,
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_INTEGER            *Address)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (UtEvaluateNumericObject);


    Status = AcpiUtEvaluateObject (DeviceNode, ObjectName,
                ACPI_BTYPE_INTEGER, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the returned Integer */

    *Address = ObjDesc->Integer.Value;

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #2
0
ACPI_STATUS
AcpiUtExecute_SUB (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_PNP_DEVICE_ID      **ReturnId)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PNP_DEVICE_ID      *Sub;
    UINT32                  Length;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (UtExecute_SUB);


    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__SUB,
                                   ACPI_BTYPE_STRING, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the size of the String to be returned, includes null terminator */

    Length = ObjDesc->String.Length + 1;

    /* Allocate a buffer for the SUB */

    Sub = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
    if (!Sub)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /* Area for the string starts after PNP_DEVICE_ID struct */

    Sub->String = ACPI_ADD_PTR (char, Sub, sizeof (ACPI_PNP_DEVICE_ID));

    /* Simply copy existing string */

    ACPI_STRCPY (Sub->String, ObjDesc->String.Pointer);
    Sub->Length = Length;
    *ReturnId = Sub;


Cleanup:

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #3
0
ACPI_STATUS
AcpiUtExecute_STA (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    UINT32                  *Flags)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (UtExecute_STA);


    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__STA,
                ACPI_BTYPE_INTEGER, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        if (AE_NOT_FOUND == Status)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
                "_STA on %4.4s was not found, assuming device is present\n",
                AcpiUtGetNodeName (DeviceNode)));

            *Flags = ACPI_UINT32_MAX;
            Status = AE_OK;
        }

        return_ACPI_STATUS (Status);
    }

    /* Extract the status flags */

    *Flags = (UINT32) ObjDesc->Integer.Value;

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #4
0
ACPI_STATUS
AcpiUtExecute_UID (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_DEVICE_ID          *Uid)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (UtExecute_UID);


    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID,
                ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        /* Convert the Numeric UID to string */

        AcpiExUnsignedIntegerToString (ObjDesc->Integer.Value, Uid->Value);
    }
    else
    {
        /* Copy the String UID from the returned object */

        AcpiUtCopyIdString (Uid->Value, ObjDesc->String.Pointer,
                sizeof (Uid->Value));
    }

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #5
0
ACPI_STATUS
AcpiUtExecute_HID (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_PNP_DEVICE_ID      **ReturnId)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PNP_DEVICE_ID      *Hid;
    UINT32                  Length;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (UtExecute_HID);


    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID,
                                   ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the size of the String to be returned, includes null terminator */

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        Length = ACPI_EISAID_STRING_SIZE;
    }
    else
    {
        Length = ObjDesc->String.Length + 1;
    }

    /* Allocate a buffer for the HID */

    Hid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
    if (!Hid)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /* Area for the string starts after PNP_DEVICE_ID struct */

    Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_PNP_DEVICE_ID));

    /* Convert EISAID to a string or simply copy existing string */

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value);
    }
    else
    {
        ACPI_STRCPY (Hid->String, ObjDesc->String.Pointer);
    }

    Hid->Length = Length;
    *ReturnId = Hid;


Cleanup:

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #6
0
ACPI_STATUS
AcpiUtExecute_CID (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_PNP_DEVICE_ID_LIST **ReturnCidList)
{
    ACPI_OPERAND_OBJECT     **CidObjects;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PNP_DEVICE_ID_LIST *CidList;
    char                    *NextIdString;
    UINT32                  StringAreaSize;
    UINT32                  Length;
    UINT32                  CidListSize;
    ACPI_STATUS             Status;
    UINT32                  Count;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (UtExecute_CID);


    /* Evaluate the _CID method for this device */

    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID,
                                   ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
                                   &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Get the count and size of the returned _CIDs. _CID can return either
     * a Package of Integers/Strings or a single Integer or String.
     * Note: This section also validates that all CID elements are of the
     * correct type (Integer or String).
     */
    if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        Count = ObjDesc->Package.Count;
        CidObjects = ObjDesc->Package.Elements;
    }
    else /* Single Integer or String CID */
    {
        Count = 1;
        CidObjects = &ObjDesc;
    }

    StringAreaSize = 0;
    for (i = 0; i < Count; i++)
    {
        /* String lengths include null terminator */

        switch (CidObjects[i]->Common.Type)
        {
        case ACPI_TYPE_INTEGER:

            StringAreaSize += ACPI_EISAID_STRING_SIZE;
            break;

        case ACPI_TYPE_STRING:

            StringAreaSize += CidObjects[i]->String.Length + 1;
            break;

        default:

            Status = AE_TYPE;
            goto Cleanup;
        }
    }

    /*
     * Now that we know the length of the CIDs, allocate return buffer:
     * 1) Size of the base structure +
     * 2) Size of the CID PNP_DEVICE_ID array +
     * 3) Size of the actual CID strings
     */
    CidListSize = sizeof (ACPI_PNP_DEVICE_ID_LIST) +
                  ((Count - 1) * sizeof (ACPI_PNP_DEVICE_ID)) +
                  StringAreaSize;

    CidList = ACPI_ALLOCATE_ZEROED (CidListSize);
    if (!CidList)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /* Area for CID strings starts after the CID PNP_DEVICE_ID array */

    NextIdString = ACPI_CAST_PTR (char, CidList->Ids) +
                   ((ACPI_SIZE) Count * sizeof (ACPI_PNP_DEVICE_ID));

    /* Copy/convert the CIDs to the return buffer */

    for (i = 0; i < Count; i++)
    {
        if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER)
        {
            /* Convert the Integer (EISAID) CID to a string */

            AcpiExEisaIdToString (NextIdString, CidObjects[i]->Integer.Value);
            Length = ACPI_EISAID_STRING_SIZE;
        }
        else /* ACPI_TYPE_STRING */
        {
            /* Copy the String CID from the returned object */

            ACPI_STRCPY (NextIdString, CidObjects[i]->String.Pointer);
            Length = CidObjects[i]->String.Length + 1;
        }

        CidList->Ids[i].String = NextIdString;
        CidList->Ids[i].Length = Length;
        NextIdString += Length;
    }

    /* Finish the CID list */

    CidList->Count = Count;
    CidList->ListSize = CidListSize;
    *ReturnCidList = CidList;


Cleanup:

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #7
0
ファイル: evgpeinit.c プロジェクト: 0xffea/MINIX3
ACPI_STATUS
AcpiEvMatchPrwAndGpe (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
    ACPI_NAMESPACE_NODE     *GpeDevice;
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
    ACPI_NAMESPACE_NODE     *TargetGpeDevice;
    ACPI_NAMESPACE_NODE     *PrwNode;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_OPERAND_OBJECT     *PkgDesc;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    UINT32                  GpeNumber;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);


    /* Check for a _PRW method under this device */

    Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW,
                ACPI_NS_NO_UPSEARCH, &PrwNode);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Check if requested OwnerId matches this OwnerId */

    if ((WalkInfo->ExecuteByOwnerId) &&
        (PrwNode->OwnerId != WalkInfo->OwnerId))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Execute the _PRW */

    Status = AcpiUtEvaluateObject (PrwNode, NULL,
                ACPI_BTYPE_PACKAGE, &PkgDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* The returned _PRW package must have at least two elements */

    if (PkgDesc->Package.Count < 2)
    {
        goto Cleanup;
    }

    /* Extract pointers from the input context */

    GpeDevice = WalkInfo->GpeDevice;
    GpeBlock = WalkInfo->GpeBlock;

    /*
     * The _PRW object must return a package, we are only interested
     * in the first element
     */
    ObjDesc = PkgDesc->Package.Elements[0];

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        /* Use FADT-defined GPE device (from definition of _PRW) */

        TargetGpeDevice = NULL;
        if (GpeDevice)
        {
            TargetGpeDevice = AcpiGbl_FadtGpeDevice;
        }

        /* Integer is the GPE number in the FADT described GPE blocks */

        GpeNumber = (UINT32) ObjDesc->Integer.Value;
    }
    else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        /* Package contains a GPE reference and GPE number within a GPE block */

        if ((ObjDesc->Package.Count < 2) ||
            ((ObjDesc->Package.Elements[0])->Common.Type !=
                ACPI_TYPE_LOCAL_REFERENCE) ||
            ((ObjDesc->Package.Elements[1])->Common.Type !=
                ACPI_TYPE_INTEGER))
        {
            goto Cleanup;
        }

        /* Get GPE block reference and decode */

        TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
        GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
    }
    else
    {
        /* Unknown type, just ignore it */

        goto Cleanup;
    }

    /* Get the GpeEventInfo for this GPE */

    if (GpeDevice)
    {
        /*
         * Is this GPE within this block?
         *
         * TRUE if and only if these conditions are true:
         *     1) The GPE devices match.
         *     2) The GPE index(number) is within the range of the Gpe Block
         *          associated with the GPE device.
         */
        if (GpeDevice != TargetGpeDevice)
        {
            goto Cleanup;
        }

        GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock);
    }
    else
    {
        /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */

        GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber);
    }

    if (GpeEventInfo)
    {
        if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
        {
            /* This GPE can wake the system */

            GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
            WalkInfo->Count++;
        }
    }

Cleanup:
    AcpiUtRemoveReference (PkgDesc);
    return_ACPI_STATUS (AE_OK);
}
コード例 #8
0
ACPI_STATUS
AcpiUtExecute_UID (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_DEVICE_ID          **ReturnId)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_DEVICE_ID          *Uid;
    UINT32                  Length;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (UtExecute_UID);


    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID,
                ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the size of the String to be returned, includes null terminator */

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        Length = ACPI_MAX64_DECIMAL_DIGITS + 1;
    }
    else
    {
        Length = ObjDesc->String.Length + 1;
    }

    /* Allocate a buffer for the UID */

    Uid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length);
    if (!Uid)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /* Area for the string starts after DEVICE_ID struct */

    Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_DEVICE_ID));

    /* Convert an Integer to string, or just copy an existing string */

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value);
    }
    else
    {
        AcpiUtCopyIdString (Uid->String, ObjDesc->String.Pointer);
    }

    Uid->Length = Length;
    *ReturnId = Uid;


Cleanup:

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #9
0
ファイル: utids.c プロジェクト: derekmarcotte/freebsd
ACPI_STATUS
AcpiUtExecute_CLS (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_PNP_DEVICE_ID      **ReturnId)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     **ClsObjects;
    UINT32                  Count;
    ACPI_PNP_DEVICE_ID      *Cls;
    UINT32                  Length;
    ACPI_STATUS             Status;
    UINT8                   ClassCode[3] = {0, 0, 0};


    ACPI_FUNCTION_TRACE (UtExecute_CLS);


    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CLS,
        ACPI_BTYPE_PACKAGE, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the size of the String to be returned, includes null terminator */

    Length = ACPI_PCICLS_STRING_SIZE;
    ClsObjects = ObjDesc->Package.Elements;
    Count = ObjDesc->Package.Count;

    if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        if (Count > 0 && ClsObjects[0]->Common.Type == ACPI_TYPE_INTEGER)
        {
            ClassCode[0] = (UINT8) ClsObjects[0]->Integer.Value;
        }
        if (Count > 1 && ClsObjects[1]->Common.Type == ACPI_TYPE_INTEGER)
        {
            ClassCode[1] = (UINT8) ClsObjects[1]->Integer.Value;
        }
        if (Count > 2 && ClsObjects[2]->Common.Type == ACPI_TYPE_INTEGER)
        {
            ClassCode[2] = (UINT8) ClsObjects[2]->Integer.Value;
        }
    }

    /* Allocate a buffer for the CLS */

    Cls = ACPI_ALLOCATE_ZEROED (
        sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
    if (!Cls)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /* Area for the string starts after PNP_DEVICE_ID struct */

    Cls->String = ACPI_ADD_PTR (char, Cls, sizeof (ACPI_PNP_DEVICE_ID));

    /* Simply copy existing string */

    AcpiExPciClsToString (Cls->String, ClassCode);
    Cls->Length = Length;
    *ReturnId = Cls;


Cleanup:

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
コード例 #10
0
ファイル: evgpeblk.c プロジェクト: mmanley/Antares
static ACPI_STATUS
AcpiEvMatchPrwAndGpe (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Info,
    void                    **ReturnValue)
{
    ACPI_GPE_WALK_INFO      *GpeInfo = (void *) Info;
    ACPI_NAMESPACE_NODE     *GpeDevice;
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
    ACPI_NAMESPACE_NODE     *TargetGpeDevice;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_OPERAND_OBJECT     *PkgDesc;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    UINT32                  GpeNumber;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);


    /* Check for a _PRW method under this device */

    Status = AcpiUtEvaluateObject (ObjHandle, METHOD_NAME__PRW,
                ACPI_BTYPE_PACKAGE, &PkgDesc);
    if (ACPI_FAILURE (Status))
    {
        /* Ignore all errors from _PRW, we don't want to abort the subsystem */

        return_ACPI_STATUS (AE_OK);
    }

    /* The returned _PRW package must have at least two elements */

    if (PkgDesc->Package.Count < 2)
    {
        goto Cleanup;
    }

    /* Extract pointers from the input context */

    GpeDevice = GpeInfo->GpeDevice;
    GpeBlock = GpeInfo->GpeBlock;

    /*
     * The _PRW object must return a package, we are only interested in the
     * first element
     */
    ObjDesc = PkgDesc->Package.Elements[0];

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        /* Use FADT-defined GPE device (from definition of _PRW) */

        TargetGpeDevice = AcpiGbl_FadtGpeDevice;

        /* Integer is the GPE number in the FADT described GPE blocks */

        GpeNumber = (UINT32) ObjDesc->Integer.Value;
    }
    else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        /* Package contains a GPE reference and GPE number within a GPE block */

        if ((ObjDesc->Package.Count < 2) ||
            ((ObjDesc->Package.Elements[0])->Common.Type !=
                ACPI_TYPE_LOCAL_REFERENCE) ||
            ((ObjDesc->Package.Elements[1])->Common.Type !=
                ACPI_TYPE_INTEGER))
        {
            goto Cleanup;
        }

        /* Get GPE block reference and decode */

        TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
        GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
    }
    else
    {
        /* Unknown type, just ignore it */

        goto Cleanup;
    }

    /*
     * Is this GPE within this block?
     *
     * TRUE if and only if these conditions are true:
     *     1) The GPE devices match.
     *     2) The GPE index(number) is within the range of the Gpe Block
     *          associated with the GPE device.
     */
    if ((GpeDevice == TargetGpeDevice) &&
        (GpeNumber >= GpeBlock->BlockBaseNumber) &&
        (GpeNumber < GpeBlock->BlockBaseNumber +
            (GpeBlock->RegisterCount * 8)))
    {
        GpeEventInfo = &GpeBlock->EventInfo[GpeNumber -
            GpeBlock->BlockBaseNumber];

        /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */

        GpeEventInfo->Flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);

        Status = AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE);
    }

Cleanup:
    AcpiUtRemoveReference (PkgDesc);
    return_ACPI_STATUS (AE_OK);
}
コード例 #11
0
ACPI_STATUS
AcpiUtExecute_CID (
    ACPI_NAMESPACE_NODE     *DeviceNode,
    ACPI_COMPATIBLE_ID_LIST **ReturnCidList)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;
    UINT32                  Count;
    UINT32                  Size;
    ACPI_COMPATIBLE_ID_LIST *CidList;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (UtExecute_CID);


    /* Evaluate the _CID method for this device */

    Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID,
                ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
                &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the number of _CIDs returned */

    Count = 1;
    if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        Count = ObjDesc->Package.Count;
    }

    /* Allocate a worst-case buffer for the _CIDs */

    Size = (((Count - 1) * sizeof (ACPI_COMPATIBLE_ID)) +
                           sizeof (ACPI_COMPATIBLE_ID_LIST));

    CidList = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Size);
    if (!CidList)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Init CID list */

    CidList->Count = Count;
    CidList->Size  = Size;

    /*
     *  A _CID can return either a single compatible ID or a package of
     *  compatible IDs.  Each compatible ID can be one of the following:
     *  1) Integer (32 bit compressed EISA ID) or
     *  2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
     */

    /* The _CID object can be either a single CID or a package (list) of CIDs */

    if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        /* Translate each package element */

        for (i = 0; i < Count; i++)
        {
            Status = AcpiUtTranslateOneCid (ObjDesc->Package.Elements[i],
                            &CidList->Id[i]);
            if (ACPI_FAILURE (Status))
            {
                break;
            }
        }
    }
    else
    {
        /* Only one CID, translate to a string */

        Status = AcpiUtTranslateOneCid (ObjDesc, CidList->Id);
    }

    /* Cleanup on error */

    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (CidList);
    }
    else
    {
        *ReturnCidList = CidList;
    }

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

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}