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