xref: /titanic_50/usr/src/uts/intel/io/acpica/utilities/utids.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
157190917SDana Myers /******************************************************************************
257190917SDana Myers  *
3*385cc6b4SJerry Jelinek  * Module Name: utids - support for device IDs - HID, UID, CID, SUB, CLS
457190917SDana Myers  *
557190917SDana Myers  *****************************************************************************/
657190917SDana Myers 
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
957190917SDana Myers  * All rights reserved.
1057190917SDana Myers  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
2557190917SDana Myers  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
2957190917SDana Myers  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
4357190917SDana Myers 
4457190917SDana Myers #include "acpi.h"
4557190917SDana Myers #include "accommon.h"
4657190917SDana Myers #include "acinterp.h"
4757190917SDana Myers 
4857190917SDana Myers 
4957190917SDana Myers #define _COMPONENT          ACPI_UTILITIES
5057190917SDana Myers         ACPI_MODULE_NAME    ("utids")
5157190917SDana Myers 
5257190917SDana Myers 
5357190917SDana Myers /*******************************************************************************
5457190917SDana Myers  *
5557190917SDana Myers  * FUNCTION:    AcpiUtExecute_HID
5657190917SDana Myers  *
5757190917SDana Myers  * PARAMETERS:  DeviceNode          - Node for the device
5857190917SDana Myers  *              ReturnId            - Where the string HID is returned
5957190917SDana Myers  *
6057190917SDana Myers  * RETURN:      Status
6157190917SDana Myers  *
6257190917SDana Myers  * DESCRIPTION: Executes the _HID control method that returns the hardware
6357190917SDana Myers  *              ID of the device. The HID is either an 32-bit encoded EISAID
6457190917SDana Myers  *              Integer or a String. A string is always returned. An EISAID
6557190917SDana Myers  *              is converted to a string.
6657190917SDana Myers  *
6757190917SDana Myers  *              NOTE: Internal function, no parameter validation
6857190917SDana Myers  *
6957190917SDana Myers  ******************************************************************************/
7057190917SDana Myers 
7157190917SDana Myers ACPI_STATUS
AcpiUtExecute_HID(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID ** ReturnId)7257190917SDana Myers AcpiUtExecute_HID (
7357190917SDana Myers     ACPI_NAMESPACE_NODE     *DeviceNode,
74*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID      **ReturnId)
7557190917SDana Myers {
7657190917SDana Myers     ACPI_OPERAND_OBJECT     *ObjDesc;
77*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID      *Hid;
7857190917SDana Myers     UINT32                  Length;
7957190917SDana Myers     ACPI_STATUS             Status;
8057190917SDana Myers 
8157190917SDana Myers 
8257190917SDana Myers     ACPI_FUNCTION_TRACE (UtExecute_HID);
8357190917SDana Myers 
8457190917SDana Myers 
8557190917SDana Myers     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID,
8657190917SDana Myers         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
8757190917SDana Myers     if (ACPI_FAILURE (Status))
8857190917SDana Myers     {
8957190917SDana Myers         return_ACPI_STATUS (Status);
9057190917SDana Myers     }
9157190917SDana Myers 
9257190917SDana Myers     /* Get the size of the String to be returned, includes null terminator */
9357190917SDana Myers 
9457190917SDana Myers     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
9557190917SDana Myers     {
9657190917SDana Myers         Length = ACPI_EISAID_STRING_SIZE;
9757190917SDana Myers     }
9857190917SDana Myers     else
9957190917SDana Myers     {
10057190917SDana Myers         Length = ObjDesc->String.Length + 1;
10157190917SDana Myers     }
10257190917SDana Myers 
10357190917SDana Myers     /* Allocate a buffer for the HID */
10457190917SDana Myers 
105*385cc6b4SJerry Jelinek     Hid = ACPI_ALLOCATE_ZEROED (
106*385cc6b4SJerry Jelinek         sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
10757190917SDana Myers     if (!Hid)
10857190917SDana Myers     {
10957190917SDana Myers         Status = AE_NO_MEMORY;
11057190917SDana Myers         goto Cleanup;
11157190917SDana Myers     }
11257190917SDana Myers 
113*385cc6b4SJerry Jelinek     /* Area for the string starts after PNP_DEVICE_ID struct */
11457190917SDana Myers 
115*385cc6b4SJerry Jelinek     Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_PNP_DEVICE_ID));
11657190917SDana Myers 
11757190917SDana Myers     /* Convert EISAID to a string or simply copy existing string */
11857190917SDana Myers 
11957190917SDana Myers     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
12057190917SDana Myers     {
12157190917SDana Myers         AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value);
12257190917SDana Myers     }
12357190917SDana Myers     else
12457190917SDana Myers     {
125*385cc6b4SJerry Jelinek         strcpy (Hid->String, ObjDesc->String.Pointer);
12657190917SDana Myers     }
12757190917SDana Myers 
12857190917SDana Myers     Hid->Length = Length;
12957190917SDana Myers     *ReturnId = Hid;
13057190917SDana Myers 
13157190917SDana Myers 
13257190917SDana Myers Cleanup:
13357190917SDana Myers 
13457190917SDana Myers     /* On exit, we must delete the return object */
13557190917SDana Myers 
13657190917SDana Myers     AcpiUtRemoveReference (ObjDesc);
13757190917SDana Myers     return_ACPI_STATUS (Status);
13857190917SDana Myers }
13957190917SDana Myers 
14057190917SDana Myers 
14157190917SDana Myers /*******************************************************************************
14257190917SDana Myers  *
14357190917SDana Myers  * FUNCTION:    AcpiUtExecute_UID
14457190917SDana Myers  *
14557190917SDana Myers  * PARAMETERS:  DeviceNode          - Node for the device
14657190917SDana Myers  *              ReturnId            - Where the string UID is returned
14757190917SDana Myers  *
14857190917SDana Myers  * RETURN:      Status
14957190917SDana Myers  *
15057190917SDana Myers  * DESCRIPTION: Executes the _UID control method that returns the unique
15157190917SDana Myers  *              ID of the device. The UID is either a 64-bit Integer (NOT an
15257190917SDana Myers  *              EISAID) or a string. Always returns a string. A 64-bit integer
15357190917SDana Myers  *              is converted to a decimal string.
15457190917SDana Myers  *
15557190917SDana Myers  *              NOTE: Internal function, no parameter validation
15657190917SDana Myers  *
15757190917SDana Myers  ******************************************************************************/
15857190917SDana Myers 
15957190917SDana Myers ACPI_STATUS
AcpiUtExecute_UID(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID ** ReturnId)16057190917SDana Myers AcpiUtExecute_UID (
16157190917SDana Myers     ACPI_NAMESPACE_NODE     *DeviceNode,
162*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID      **ReturnId)
16357190917SDana Myers {
16457190917SDana Myers     ACPI_OPERAND_OBJECT     *ObjDesc;
165*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID      *Uid;
16657190917SDana Myers     UINT32                  Length;
16757190917SDana Myers     ACPI_STATUS             Status;
16857190917SDana Myers 
16957190917SDana Myers 
17057190917SDana Myers     ACPI_FUNCTION_TRACE (UtExecute_UID);
17157190917SDana Myers 
17257190917SDana Myers 
17357190917SDana Myers     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID,
17457190917SDana Myers         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
17557190917SDana Myers     if (ACPI_FAILURE (Status))
17657190917SDana Myers     {
17757190917SDana Myers         return_ACPI_STATUS (Status);
17857190917SDana Myers     }
17957190917SDana Myers 
18057190917SDana Myers     /* Get the size of the String to be returned, includes null terminator */
18157190917SDana Myers 
18257190917SDana Myers     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
18357190917SDana Myers     {
18457190917SDana Myers         Length = ACPI_MAX64_DECIMAL_DIGITS + 1;
18557190917SDana Myers     }
18657190917SDana Myers     else
18757190917SDana Myers     {
18857190917SDana Myers         Length = ObjDesc->String.Length + 1;
18957190917SDana Myers     }
19057190917SDana Myers 
19157190917SDana Myers     /* Allocate a buffer for the UID */
19257190917SDana Myers 
193*385cc6b4SJerry Jelinek     Uid = ACPI_ALLOCATE_ZEROED (
194*385cc6b4SJerry Jelinek         sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
19557190917SDana Myers     if (!Uid)
19657190917SDana Myers     {
19757190917SDana Myers         Status = AE_NO_MEMORY;
19857190917SDana Myers         goto Cleanup;
19957190917SDana Myers     }
20057190917SDana Myers 
201*385cc6b4SJerry Jelinek     /* Area for the string starts after PNP_DEVICE_ID struct */
20257190917SDana Myers 
203*385cc6b4SJerry Jelinek     Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_PNP_DEVICE_ID));
20457190917SDana Myers 
20557190917SDana Myers     /* Convert an Integer to string, or just copy an existing string */
20657190917SDana Myers 
20757190917SDana Myers     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
20857190917SDana Myers     {
20957190917SDana Myers         AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value);
21057190917SDana Myers     }
21157190917SDana Myers     else
21257190917SDana Myers     {
213*385cc6b4SJerry Jelinek         strcpy (Uid->String, ObjDesc->String.Pointer);
21457190917SDana Myers     }
21557190917SDana Myers 
21657190917SDana Myers     Uid->Length = Length;
21757190917SDana Myers     *ReturnId = Uid;
21857190917SDana Myers 
21957190917SDana Myers 
22057190917SDana Myers Cleanup:
22157190917SDana Myers 
22257190917SDana Myers     /* On exit, we must delete the return object */
22357190917SDana Myers 
22457190917SDana Myers     AcpiUtRemoveReference (ObjDesc);
22557190917SDana Myers     return_ACPI_STATUS (Status);
22657190917SDana Myers }
22757190917SDana Myers 
22857190917SDana Myers 
22957190917SDana Myers /*******************************************************************************
23057190917SDana Myers  *
23157190917SDana Myers  * FUNCTION:    AcpiUtExecute_CID
23257190917SDana Myers  *
23357190917SDana Myers  * PARAMETERS:  DeviceNode          - Node for the device
23457190917SDana Myers  *              ReturnCidList       - Where the CID list is returned
23557190917SDana Myers  *
23657190917SDana Myers  * RETURN:      Status, list of CID strings
23757190917SDana Myers  *
23857190917SDana Myers  * DESCRIPTION: Executes the _CID control method that returns one or more
23957190917SDana Myers  *              compatible hardware IDs for the device.
24057190917SDana Myers  *
24157190917SDana Myers  *              NOTE: Internal function, no parameter validation
24257190917SDana Myers  *
24357190917SDana Myers  * A _CID method can return either a single compatible ID or a package of
24457190917SDana Myers  * compatible IDs. Each compatible ID can be one of the following:
24557190917SDana Myers  * 1) Integer (32 bit compressed EISA ID) or
24657190917SDana Myers  * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
24757190917SDana Myers  *
24857190917SDana Myers  * The Integer CIDs are converted to string format by this function.
24957190917SDana Myers  *
25057190917SDana Myers  ******************************************************************************/
25157190917SDana Myers 
25257190917SDana Myers ACPI_STATUS
AcpiUtExecute_CID(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID_LIST ** ReturnCidList)25357190917SDana Myers AcpiUtExecute_CID (
25457190917SDana Myers     ACPI_NAMESPACE_NODE     *DeviceNode,
255*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID_LIST **ReturnCidList)
25657190917SDana Myers {
25757190917SDana Myers     ACPI_OPERAND_OBJECT     **CidObjects;
25857190917SDana Myers     ACPI_OPERAND_OBJECT     *ObjDesc;
259*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID_LIST *CidList;
26057190917SDana Myers     char                    *NextIdString;
26157190917SDana Myers     UINT32                  StringAreaSize;
26257190917SDana Myers     UINT32                  Length;
26357190917SDana Myers     UINT32                  CidListSize;
26457190917SDana Myers     ACPI_STATUS             Status;
26557190917SDana Myers     UINT32                  Count;
26657190917SDana Myers     UINT32                  i;
26757190917SDana Myers 
26857190917SDana Myers 
26957190917SDana Myers     ACPI_FUNCTION_TRACE (UtExecute_CID);
27057190917SDana Myers 
27157190917SDana Myers 
27257190917SDana Myers     /* Evaluate the _CID method for this device */
27357190917SDana Myers 
27457190917SDana Myers     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID,
27557190917SDana Myers         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
27657190917SDana Myers         &ObjDesc);
27757190917SDana Myers     if (ACPI_FAILURE (Status))
27857190917SDana Myers     {
27957190917SDana Myers         return_ACPI_STATUS (Status);
28057190917SDana Myers     }
28157190917SDana Myers 
28257190917SDana Myers     /*
28357190917SDana Myers      * Get the count and size of the returned _CIDs. _CID can return either
28457190917SDana Myers      * a Package of Integers/Strings or a single Integer or String.
28557190917SDana Myers      * Note: This section also validates that all CID elements are of the
28657190917SDana Myers      * correct type (Integer or String).
28757190917SDana Myers      */
28857190917SDana Myers     if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
28957190917SDana Myers     {
29057190917SDana Myers         Count = ObjDesc->Package.Count;
29157190917SDana Myers         CidObjects = ObjDesc->Package.Elements;
29257190917SDana Myers     }
29357190917SDana Myers     else /* Single Integer or String CID */
29457190917SDana Myers     {
29557190917SDana Myers         Count = 1;
29657190917SDana Myers         CidObjects = &ObjDesc;
29757190917SDana Myers     }
29857190917SDana Myers 
29957190917SDana Myers     StringAreaSize = 0;
30057190917SDana Myers     for (i = 0; i < Count; i++)
30157190917SDana Myers     {
30257190917SDana Myers         /* String lengths include null terminator */
30357190917SDana Myers 
30457190917SDana Myers         switch (CidObjects[i]->Common.Type)
30557190917SDana Myers         {
30657190917SDana Myers         case ACPI_TYPE_INTEGER:
307*385cc6b4SJerry Jelinek 
30857190917SDana Myers             StringAreaSize += ACPI_EISAID_STRING_SIZE;
30957190917SDana Myers             break;
31057190917SDana Myers 
31157190917SDana Myers         case ACPI_TYPE_STRING:
312*385cc6b4SJerry Jelinek 
31357190917SDana Myers             StringAreaSize += CidObjects[i]->String.Length + 1;
31457190917SDana Myers             break;
31557190917SDana Myers 
31657190917SDana Myers         default:
317*385cc6b4SJerry Jelinek 
31857190917SDana Myers             Status = AE_TYPE;
31957190917SDana Myers             goto Cleanup;
32057190917SDana Myers         }
32157190917SDana Myers     }
32257190917SDana Myers 
32357190917SDana Myers     /*
32457190917SDana Myers      * Now that we know the length of the CIDs, allocate return buffer:
32557190917SDana Myers      * 1) Size of the base structure +
326*385cc6b4SJerry Jelinek      * 2) Size of the CID PNP_DEVICE_ID array +
32757190917SDana Myers      * 3) Size of the actual CID strings
32857190917SDana Myers      */
329*385cc6b4SJerry Jelinek     CidListSize = sizeof (ACPI_PNP_DEVICE_ID_LIST) +
330*385cc6b4SJerry Jelinek         ((Count - 1) * sizeof (ACPI_PNP_DEVICE_ID)) +
33157190917SDana Myers         StringAreaSize;
33257190917SDana Myers 
33357190917SDana Myers     CidList = ACPI_ALLOCATE_ZEROED (CidListSize);
33457190917SDana Myers     if (!CidList)
33557190917SDana Myers     {
33657190917SDana Myers         Status = AE_NO_MEMORY;
33757190917SDana Myers         goto Cleanup;
33857190917SDana Myers     }
33957190917SDana Myers 
340*385cc6b4SJerry Jelinek     /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
34157190917SDana Myers 
34257190917SDana Myers     NextIdString = ACPI_CAST_PTR (char, CidList->Ids) +
343*385cc6b4SJerry Jelinek         ((ACPI_SIZE) Count * sizeof (ACPI_PNP_DEVICE_ID));
34457190917SDana Myers 
34557190917SDana Myers     /* Copy/convert the CIDs to the return buffer */
34657190917SDana Myers 
34757190917SDana Myers     for (i = 0; i < Count; i++)
34857190917SDana Myers     {
34957190917SDana Myers         if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER)
35057190917SDana Myers         {
35157190917SDana Myers             /* Convert the Integer (EISAID) CID to a string */
35257190917SDana Myers 
353*385cc6b4SJerry Jelinek             AcpiExEisaIdToString (
354*385cc6b4SJerry Jelinek                 NextIdString, CidObjects[i]->Integer.Value);
35557190917SDana Myers             Length = ACPI_EISAID_STRING_SIZE;
35657190917SDana Myers         }
35757190917SDana Myers         else /* ACPI_TYPE_STRING */
35857190917SDana Myers         {
35957190917SDana Myers             /* Copy the String CID from the returned object */
36057190917SDana Myers 
361*385cc6b4SJerry Jelinek             strcpy (NextIdString, CidObjects[i]->String.Pointer);
36257190917SDana Myers             Length = CidObjects[i]->String.Length + 1;
36357190917SDana Myers         }
36457190917SDana Myers 
36557190917SDana Myers         CidList->Ids[i].String = NextIdString;
36657190917SDana Myers         CidList->Ids[i].Length = Length;
36757190917SDana Myers         NextIdString += Length;
36857190917SDana Myers     }
36957190917SDana Myers 
37057190917SDana Myers     /* Finish the CID list */
37157190917SDana Myers 
37257190917SDana Myers     CidList->Count = Count;
37357190917SDana Myers     CidList->ListSize = CidListSize;
37457190917SDana Myers     *ReturnCidList = CidList;
37557190917SDana Myers 
37657190917SDana Myers 
37757190917SDana Myers Cleanup:
37857190917SDana Myers 
37957190917SDana Myers     /* On exit, we must delete the _CID return object */
38057190917SDana Myers 
38157190917SDana Myers     AcpiUtRemoveReference (ObjDesc);
38257190917SDana Myers     return_ACPI_STATUS (Status);
38357190917SDana Myers }
38457190917SDana Myers 
385*385cc6b4SJerry Jelinek 
386*385cc6b4SJerry Jelinek /*******************************************************************************
387*385cc6b4SJerry Jelinek  *
388*385cc6b4SJerry Jelinek  * FUNCTION:    AcpiUtExecute_CLS
389*385cc6b4SJerry Jelinek  *
390*385cc6b4SJerry Jelinek  * PARAMETERS:  DeviceNode          - Node for the device
391*385cc6b4SJerry Jelinek  *              ReturnId            - Where the _CLS is returned
392*385cc6b4SJerry Jelinek  *
393*385cc6b4SJerry Jelinek  * RETURN:      Status
394*385cc6b4SJerry Jelinek  *
395*385cc6b4SJerry Jelinek  * DESCRIPTION: Executes the _CLS control method that returns PCI-defined
396*385cc6b4SJerry Jelinek  *              class code of the device. The _CLS value is always a package
397*385cc6b4SJerry Jelinek  *              containing PCI class information as a list of integers.
398*385cc6b4SJerry Jelinek  *              The returned string has format "BBSSPP", where:
399*385cc6b4SJerry Jelinek  *                BB = Base-class code
400*385cc6b4SJerry Jelinek  *                SS = Sub-class code
401*385cc6b4SJerry Jelinek  *                PP = Programming Interface code
402*385cc6b4SJerry Jelinek  *
403*385cc6b4SJerry Jelinek  ******************************************************************************/
404*385cc6b4SJerry Jelinek 
405*385cc6b4SJerry Jelinek ACPI_STATUS
AcpiUtExecute_CLS(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID ** ReturnId)406*385cc6b4SJerry Jelinek AcpiUtExecute_CLS (
407*385cc6b4SJerry Jelinek     ACPI_NAMESPACE_NODE     *DeviceNode,
408*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID      **ReturnId)
409*385cc6b4SJerry Jelinek {
410*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     *ObjDesc;
411*385cc6b4SJerry Jelinek     ACPI_OPERAND_OBJECT     **ClsObjects;
412*385cc6b4SJerry Jelinek     UINT32                  Count;
413*385cc6b4SJerry Jelinek     ACPI_PNP_DEVICE_ID      *Cls;
414*385cc6b4SJerry Jelinek     UINT32                  Length;
415*385cc6b4SJerry Jelinek     ACPI_STATUS             Status;
416*385cc6b4SJerry Jelinek     UINT8                   ClassCode[3] = {0, 0, 0};
417*385cc6b4SJerry Jelinek 
418*385cc6b4SJerry Jelinek 
419*385cc6b4SJerry Jelinek     ACPI_FUNCTION_TRACE (UtExecute_CLS);
420*385cc6b4SJerry Jelinek 
421*385cc6b4SJerry Jelinek 
422*385cc6b4SJerry Jelinek     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CLS,
423*385cc6b4SJerry Jelinek         ACPI_BTYPE_PACKAGE, &ObjDesc);
424*385cc6b4SJerry Jelinek     if (ACPI_FAILURE (Status))
425*385cc6b4SJerry Jelinek     {
426*385cc6b4SJerry Jelinek         return_ACPI_STATUS (Status);
427*385cc6b4SJerry Jelinek     }
428*385cc6b4SJerry Jelinek 
429*385cc6b4SJerry Jelinek     /* Get the size of the String to be returned, includes null terminator */
430*385cc6b4SJerry Jelinek 
431*385cc6b4SJerry Jelinek     Length = ACPI_PCICLS_STRING_SIZE;
432*385cc6b4SJerry Jelinek     ClsObjects = ObjDesc->Package.Elements;
433*385cc6b4SJerry Jelinek     Count = ObjDesc->Package.Count;
434*385cc6b4SJerry Jelinek 
435*385cc6b4SJerry Jelinek     if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
436*385cc6b4SJerry Jelinek     {
437*385cc6b4SJerry Jelinek         if (Count > 0 && ClsObjects[0]->Common.Type == ACPI_TYPE_INTEGER)
438*385cc6b4SJerry Jelinek         {
439*385cc6b4SJerry Jelinek             ClassCode[0] = (UINT8) ClsObjects[0]->Integer.Value;
440*385cc6b4SJerry Jelinek         }
441*385cc6b4SJerry Jelinek         if (Count > 1 && ClsObjects[1]->Common.Type == ACPI_TYPE_INTEGER)
442*385cc6b4SJerry Jelinek         {
443*385cc6b4SJerry Jelinek             ClassCode[1] = (UINT8) ClsObjects[1]->Integer.Value;
444*385cc6b4SJerry Jelinek         }
445*385cc6b4SJerry Jelinek         if (Count > 2 && ClsObjects[2]->Common.Type == ACPI_TYPE_INTEGER)
446*385cc6b4SJerry Jelinek         {
447*385cc6b4SJerry Jelinek             ClassCode[2] = (UINT8) ClsObjects[2]->Integer.Value;
448*385cc6b4SJerry Jelinek         }
449*385cc6b4SJerry Jelinek     }
450*385cc6b4SJerry Jelinek 
451*385cc6b4SJerry Jelinek     /* Allocate a buffer for the CLS */
452*385cc6b4SJerry Jelinek 
453*385cc6b4SJerry Jelinek     Cls = ACPI_ALLOCATE_ZEROED (
454*385cc6b4SJerry Jelinek         sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
455*385cc6b4SJerry Jelinek     if (!Cls)
456*385cc6b4SJerry Jelinek     {
457*385cc6b4SJerry Jelinek         Status = AE_NO_MEMORY;
458*385cc6b4SJerry Jelinek         goto Cleanup;
459*385cc6b4SJerry Jelinek     }
460*385cc6b4SJerry Jelinek 
461*385cc6b4SJerry Jelinek     /* Area for the string starts after PNP_DEVICE_ID struct */
462*385cc6b4SJerry Jelinek 
463*385cc6b4SJerry Jelinek     Cls->String = ACPI_ADD_PTR (char, Cls, sizeof (ACPI_PNP_DEVICE_ID));
464*385cc6b4SJerry Jelinek 
465*385cc6b4SJerry Jelinek     /* Simply copy existing string */
466*385cc6b4SJerry Jelinek 
467*385cc6b4SJerry Jelinek     AcpiExPciClsToString (Cls->String, ClassCode);
468*385cc6b4SJerry Jelinek     Cls->Length = Length;
469*385cc6b4SJerry Jelinek     *ReturnId = Cls;
470*385cc6b4SJerry Jelinek 
471*385cc6b4SJerry Jelinek 
472*385cc6b4SJerry Jelinek Cleanup:
473*385cc6b4SJerry Jelinek 
474*385cc6b4SJerry Jelinek     /* On exit, we must delete the return object */
475*385cc6b4SJerry Jelinek 
476*385cc6b4SJerry Jelinek     AcpiUtRemoveReference (ObjDesc);
477*385cc6b4SJerry Jelinek     return_ACPI_STATUS (Status);
478*385cc6b4SJerry Jelinek }
479