Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, Intel Corp.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions, and the following disclaimer,
  16.  *    without modification.
  17.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18.  *    substantially similar to the "NO WARRANTY" disclaimer below
  19.  *    ("Disclaimer") and any redistribution must be conditioned upon
  20.  *    including a substantially similar Disclaimer requirement for further
  21.  *    binary redistribution.
  22.  * 3. Neither the names of the above-listed copyright holders nor the names
  23.  *    of any contributors may be used to endorse or promote products derived
  24.  *    from this software without specific prior written permission.
  25.  *
  26.  * Alternatively, this software may be distributed under the terms of the
  27.  * GNU General Public License ("GPL") version 2 as published by the Free
  28.  * Software Foundation.
  29.  *
  30.  * NO WARRANTY
  31.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41.  * POSSIBILITY OF SUCH DAMAGES.
  42.  */
  43.  
  44. #include <acpi/acpi.h>
  45. #include "accommon.h"
  46. #include "acinterp.h"
  47.  
  48. #define _COMPONENT          ACPI_UTILITIES
  49. ACPI_MODULE_NAME("utids")
  50.  
  51. /*******************************************************************************
  52.  *
  53.  * FUNCTION:    acpi_ut_execute_HID
  54.  *
  55.  * PARAMETERS:  device_node         - Node for the device
  56.  *              return_id           - Where the string HID is returned
  57.  *
  58.  * RETURN:      Status
  59.  *
  60.  * DESCRIPTION: Executes the _HID control method that returns the hardware
  61.  *              ID of the device. The HID is either an 32-bit encoded EISAID
  62.  *              Integer or a String. A string is always returned. An EISAID
  63.  *              is converted to a string.
  64.  *
  65.  *              NOTE: Internal function, no parameter validation
  66.  *
  67.  ******************************************************************************/
  68. acpi_status
  69. acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
  70.                     struct acpi_pnp_device_id **return_id)
  71. {
  72.         union acpi_operand_object *obj_desc;
  73.         struct acpi_pnp_device_id *hid;
  74.         u32 length;
  75.         acpi_status status;
  76.  
  77.         ACPI_FUNCTION_TRACE(ut_execute_HID);
  78.  
  79.         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
  80.                                          ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
  81.                                          &obj_desc);
  82.         if (ACPI_FAILURE(status)) {
  83.                 return_ACPI_STATUS(status);
  84.         }
  85.  
  86.         /* Get the size of the String to be returned, includes null terminator */
  87.  
  88.         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
  89.                 length = ACPI_EISAID_STRING_SIZE;
  90.         } else {
  91.                 length = obj_desc->string.length + 1;
  92.         }
  93.  
  94.         /* Allocate a buffer for the HID */
  95.  
  96.         hid =
  97.             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
  98.                                  (acpi_size) length);
  99.         if (!hid) {
  100.                 status = AE_NO_MEMORY;
  101.                 goto cleanup;
  102.         }
  103.  
  104.         /* Area for the string starts after PNP_DEVICE_ID struct */
  105.  
  106.         hid->string =
  107.             ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
  108.  
  109.         /* Convert EISAID to a string or simply copy existing string */
  110.  
  111.         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
  112.                 acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
  113.         } else {
  114.                 strcpy(hid->string, obj_desc->string.pointer);
  115.         }
  116.  
  117.         hid->length = length;
  118.         *return_id = hid;
  119.  
  120. cleanup:
  121.  
  122.         /* On exit, we must delete the return object */
  123.  
  124.         acpi_ut_remove_reference(obj_desc);
  125.         return_ACPI_STATUS(status);
  126. }
  127.  
  128. /*******************************************************************************
  129.  *
  130.  * FUNCTION:    acpi_ut_execute_SUB
  131.  *
  132.  * PARAMETERS:  device_node         - Node for the device
  133.  *              return_id           - Where the _SUB is returned
  134.  *
  135.  * RETURN:      Status
  136.  *
  137.  * DESCRIPTION: Executes the _SUB control method that returns the subsystem
  138.  *              ID of the device. The _SUB value is always a string containing
  139.  *              either a valid PNP or ACPI ID.
  140.  *
  141.  *              NOTE: Internal function, no parameter validation
  142.  *
  143.  ******************************************************************************/
  144.  
  145. acpi_status
  146. acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
  147.                     struct acpi_pnp_device_id **return_id)
  148. {
  149.         union acpi_operand_object *obj_desc;
  150.         struct acpi_pnp_device_id *sub;
  151.         u32 length;
  152.         acpi_status status;
  153.  
  154.         ACPI_FUNCTION_TRACE(ut_execute_SUB);
  155.  
  156.         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
  157.                                          ACPI_BTYPE_STRING, &obj_desc);
  158.         if (ACPI_FAILURE(status)) {
  159.                 return_ACPI_STATUS(status);
  160.         }
  161.  
  162.         /* Get the size of the String to be returned, includes null terminator */
  163.  
  164.         length = obj_desc->string.length + 1;
  165.  
  166.         /* Allocate a buffer for the SUB */
  167.  
  168.         sub =
  169.             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
  170.                                  (acpi_size) length);
  171.         if (!sub) {
  172.                 status = AE_NO_MEMORY;
  173.                 goto cleanup;
  174.         }
  175.  
  176.         /* Area for the string starts after PNP_DEVICE_ID struct */
  177.  
  178.         sub->string =
  179.             ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
  180.  
  181.         /* Simply copy existing string */
  182.  
  183.         strcpy(sub->string, obj_desc->string.pointer);
  184.         sub->length = length;
  185.         *return_id = sub;
  186.  
  187. cleanup:
  188.  
  189.         /* On exit, we must delete the return object */
  190.  
  191.         acpi_ut_remove_reference(obj_desc);
  192.         return_ACPI_STATUS(status);
  193. }
  194.  
  195. /*******************************************************************************
  196.  *
  197.  * FUNCTION:    acpi_ut_execute_UID
  198.  *
  199.  * PARAMETERS:  device_node         - Node for the device
  200.  *              return_id           - Where the string UID is returned
  201.  *
  202.  * RETURN:      Status
  203.  *
  204.  * DESCRIPTION: Executes the _UID control method that returns the unique
  205.  *              ID of the device. The UID is either a 64-bit Integer (NOT an
  206.  *              EISAID) or a string. Always returns a string. A 64-bit integer
  207.  *              is converted to a decimal string.
  208.  *
  209.  *              NOTE: Internal function, no parameter validation
  210.  *
  211.  ******************************************************************************/
  212.  
  213. acpi_status
  214. acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
  215.                     struct acpi_pnp_device_id **return_id)
  216. {
  217.         union acpi_operand_object *obj_desc;
  218.         struct acpi_pnp_device_id *uid;
  219.         u32 length;
  220.         acpi_status status;
  221.  
  222.         ACPI_FUNCTION_TRACE(ut_execute_UID);
  223.  
  224.         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
  225.                                          ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
  226.                                          &obj_desc);
  227.         if (ACPI_FAILURE(status)) {
  228.                 return_ACPI_STATUS(status);
  229.         }
  230.  
  231.         /* Get the size of the String to be returned, includes null terminator */
  232.  
  233.         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
  234.                 length = ACPI_MAX64_DECIMAL_DIGITS + 1;
  235.         } else {
  236.                 length = obj_desc->string.length + 1;
  237.         }
  238.  
  239.         /* Allocate a buffer for the UID */
  240.  
  241.         uid =
  242.             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
  243.                                  (acpi_size) length);
  244.         if (!uid) {
  245.                 status = AE_NO_MEMORY;
  246.                 goto cleanup;
  247.         }
  248.  
  249.         /* Area for the string starts after PNP_DEVICE_ID struct */
  250.  
  251.         uid->string =
  252.             ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
  253.  
  254.         /* Convert an Integer to string, or just copy an existing string */
  255.  
  256.         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
  257.                 acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
  258.         } else {
  259.                 strcpy(uid->string, obj_desc->string.pointer);
  260.         }
  261.  
  262.         uid->length = length;
  263.         *return_id = uid;
  264.  
  265. cleanup:
  266.  
  267.         /* On exit, we must delete the return object */
  268.  
  269.         acpi_ut_remove_reference(obj_desc);
  270.         return_ACPI_STATUS(status);
  271. }
  272.  
  273. /*******************************************************************************
  274.  *
  275.  * FUNCTION:    acpi_ut_execute_CID
  276.  *
  277.  * PARAMETERS:  device_node         - Node for the device
  278.  *              return_cid_list     - Where the CID list is returned
  279.  *
  280.  * RETURN:      Status, list of CID strings
  281.  *
  282.  * DESCRIPTION: Executes the _CID control method that returns one or more
  283.  *              compatible hardware IDs for the device.
  284.  *
  285.  *              NOTE: Internal function, no parameter validation
  286.  *
  287.  * A _CID method can return either a single compatible ID or a package of
  288.  * compatible IDs. Each compatible ID can be one of the following:
  289.  * 1) Integer (32 bit compressed EISA ID) or
  290.  * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
  291.  *
  292.  * The Integer CIDs are converted to string format by this function.
  293.  *
  294.  ******************************************************************************/
  295.  
  296. acpi_status
  297. acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
  298.                     struct acpi_pnp_device_id_list **return_cid_list)
  299. {
  300.         union acpi_operand_object **cid_objects;
  301.         union acpi_operand_object *obj_desc;
  302.         struct acpi_pnp_device_id_list *cid_list;
  303.         char *next_id_string;
  304.         u32 string_area_size;
  305.         u32 length;
  306.         u32 cid_list_size;
  307.         acpi_status status;
  308.         u32 count;
  309.         u32 i;
  310.  
  311.         ACPI_FUNCTION_TRACE(ut_execute_CID);
  312.  
  313.         /* Evaluate the _CID method for this device */
  314.  
  315.         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
  316.                                          ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
  317.                                          | ACPI_BTYPE_PACKAGE, &obj_desc);
  318.         if (ACPI_FAILURE(status)) {
  319.                 return_ACPI_STATUS(status);
  320.         }
  321.  
  322.         /*
  323.          * Get the count and size of the returned _CIDs. _CID can return either
  324.          * a Package of Integers/Strings or a single Integer or String.
  325.          * Note: This section also validates that all CID elements are of the
  326.          * correct type (Integer or String).
  327.          */
  328.         if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
  329.                 count = obj_desc->package.count;
  330.                 cid_objects = obj_desc->package.elements;
  331.         } else {                /* Single Integer or String CID */
  332.  
  333.                 count = 1;
  334.                 cid_objects = &obj_desc;
  335.         }
  336.  
  337.         string_area_size = 0;
  338.         for (i = 0; i < count; i++) {
  339.  
  340.                 /* String lengths include null terminator */
  341.  
  342.                 switch (cid_objects[i]->common.type) {
  343.                 case ACPI_TYPE_INTEGER:
  344.  
  345.                         string_area_size += ACPI_EISAID_STRING_SIZE;
  346.                         break;
  347.  
  348.                 case ACPI_TYPE_STRING:
  349.  
  350.                         string_area_size += cid_objects[i]->string.length + 1;
  351.                         break;
  352.  
  353.                 default:
  354.  
  355.                         status = AE_TYPE;
  356.                         goto cleanup;
  357.                 }
  358.         }
  359.  
  360.         /*
  361.          * Now that we know the length of the CIDs, allocate return buffer:
  362.          * 1) Size of the base structure +
  363.          * 2) Size of the CID PNP_DEVICE_ID array +
  364.          * 3) Size of the actual CID strings
  365.          */
  366.         cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
  367.             ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
  368.             string_area_size;
  369.  
  370.         cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
  371.         if (!cid_list) {
  372.                 status = AE_NO_MEMORY;
  373.                 goto cleanup;
  374.         }
  375.  
  376.         /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
  377.  
  378.         next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
  379.             ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
  380.  
  381.         /* Copy/convert the CIDs to the return buffer */
  382.  
  383.         for (i = 0; i < count; i++) {
  384.                 if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) {
  385.  
  386.                         /* Convert the Integer (EISAID) CID to a string */
  387.  
  388.                         acpi_ex_eisa_id_to_string(next_id_string,
  389.                                                   cid_objects[i]->integer.
  390.                                                   value);
  391.                         length = ACPI_EISAID_STRING_SIZE;
  392.                 } else {        /* ACPI_TYPE_STRING */
  393.  
  394.                         /* Copy the String CID from the returned object */
  395.  
  396.                         strcpy(next_id_string, cid_objects[i]->string.pointer);
  397.                         length = cid_objects[i]->string.length + 1;
  398.                 }
  399.  
  400.                 cid_list->ids[i].string = next_id_string;
  401.                 cid_list->ids[i].length = length;
  402.                 next_id_string += length;
  403.         }
  404.  
  405.         /* Finish the CID list */
  406.  
  407.         cid_list->count = count;
  408.         cid_list->list_size = cid_list_size;
  409.         *return_cid_list = cid_list;
  410.  
  411. cleanup:
  412.  
  413.         /* On exit, we must delete the _CID return object */
  414.  
  415.         acpi_ut_remove_reference(obj_desc);
  416.         return_ACPI_STATUS(status);
  417. }
  418.  
  419. /*******************************************************************************
  420.  *
  421.  * FUNCTION:    acpi_ut_execute_CLS
  422.  *
  423.  * PARAMETERS:  device_node         - Node for the device
  424.  *              return_id           - Where the _CLS is returned
  425.  *
  426.  * RETURN:      Status
  427.  *
  428.  * DESCRIPTION: Executes the _CLS control method that returns PCI-defined
  429.  *              class code of the device. The _CLS value is always a package
  430.  *              containing PCI class information as a list of integers.
  431.  *              The returned string has format "BBSSPP", where:
  432.  *                BB = Base-class code
  433.  *                SS = Sub-class code
  434.  *                PP = Programming Interface code
  435.  *
  436.  ******************************************************************************/
  437.  
  438. acpi_status
  439. acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
  440.                     struct acpi_pnp_device_id **return_id)
  441. {
  442.         union acpi_operand_object *obj_desc;
  443.         union acpi_operand_object **cls_objects;
  444.         u32 count;
  445.         struct acpi_pnp_device_id *cls;
  446.         u32 length;
  447.         acpi_status status;
  448.         u8 class_code[3] = { 0, 0, 0 };
  449.  
  450.         ACPI_FUNCTION_TRACE(ut_execute_CLS);
  451.  
  452.         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS,
  453.                                          ACPI_BTYPE_PACKAGE, &obj_desc);
  454.         if (ACPI_FAILURE(status)) {
  455.                 return_ACPI_STATUS(status);
  456.         }
  457.  
  458.         /* Get the size of the String to be returned, includes null terminator */
  459.  
  460.         length = ACPI_PCICLS_STRING_SIZE;
  461.         cls_objects = obj_desc->package.elements;
  462.         count = obj_desc->package.count;
  463.  
  464.         if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
  465.                 if (count > 0
  466.                     && cls_objects[0]->common.type == ACPI_TYPE_INTEGER) {
  467.                         class_code[0] = (u8)cls_objects[0]->integer.value;
  468.                 }
  469.                 if (count > 1
  470.                     && cls_objects[1]->common.type == ACPI_TYPE_INTEGER) {
  471.                         class_code[1] = (u8)cls_objects[1]->integer.value;
  472.                 }
  473.                 if (count > 2
  474.                     && cls_objects[2]->common.type == ACPI_TYPE_INTEGER) {
  475.                         class_code[2] = (u8)cls_objects[2]->integer.value;
  476.                 }
  477.         }
  478.  
  479.         /* Allocate a buffer for the CLS */
  480.  
  481.         cls =
  482.             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
  483.                                  (acpi_size) length);
  484.         if (!cls) {
  485.                 status = AE_NO_MEMORY;
  486.                 goto cleanup;
  487.         }
  488.  
  489.         /* Area for the string starts after PNP_DEVICE_ID struct */
  490.  
  491.         cls->string =
  492.             ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id));
  493.  
  494.         /* Simply copy existing string */
  495.  
  496.         acpi_ex_pci_cls_to_string(cls->string, class_code);
  497.         cls->length = length;
  498.         *return_id = cls;
  499.  
  500. cleanup:
  501.  
  502.         /* On exit, we must delete the return object */
  503.  
  504.         acpi_ut_remove_reference(obj_desc);
  505.         return_ACPI_STATUS(status);
  506. }
  507.