Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exfldio - Aml Field I/O
  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. #include "amlcode.h"
  48. #include "acevents.h"
  49. #include "acdispat.h"
  50.  
  51. #define _COMPONENT          ACPI_EXECUTER
  52. ACPI_MODULE_NAME("exfldio")
  53.  
  54. /* Local prototypes */
  55. static acpi_status
  56. acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
  57.                        u32 field_datum_byte_offset, u64 *value, u32 read_write);
  58.  
  59. static u8
  60. acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
  61.  
  62. static acpi_status
  63. acpi_ex_setup_region(union acpi_operand_object *obj_desc,
  64.                      u32 field_datum_byte_offset);
  65.  
  66. /*******************************************************************************
  67.  *
  68.  * FUNCTION:    acpi_ex_setup_region
  69.  *
  70.  * PARAMETERS:  obj_desc                - Field to be read or written
  71.  *              field_datum_byte_offset - Byte offset of this datum within the
  72.  *                                        parent field
  73.  *
  74.  * RETURN:      Status
  75.  *
  76.  * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
  77.  *              acpi_ex_insert_into_field. Initialize the Region if necessary and
  78.  *              validate the request.
  79.  *
  80.  ******************************************************************************/
  81.  
  82. static acpi_status
  83. acpi_ex_setup_region(union acpi_operand_object *obj_desc,
  84.                      u32 field_datum_byte_offset)
  85. {
  86.         acpi_status status = AE_OK;
  87.         union acpi_operand_object *rgn_desc;
  88.         u8 space_id;
  89.  
  90.         ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
  91.  
  92.         rgn_desc = obj_desc->common_field.region_obj;
  93.  
  94.         /* We must have a valid region */
  95.  
  96.         if (rgn_desc->common.type != ACPI_TYPE_REGION) {
  97.                 ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)",
  98.                             rgn_desc->common.type,
  99.                             acpi_ut_get_object_type_name(rgn_desc)));
  100.  
  101.                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
  102.         }
  103.  
  104.         space_id = rgn_desc->region.space_id;
  105.  
  106.         /* Validate the Space ID */
  107.  
  108.         if (!acpi_is_valid_space_id(space_id)) {
  109.                 ACPI_ERROR((AE_INFO,
  110.                             "Invalid/unknown Address Space ID: 0x%2.2X",
  111.                             space_id));
  112.                 return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
  113.         }
  114.  
  115.         /*
  116.          * If the Region Address and Length have not been previously evaluated,
  117.          * evaluate them now and save the results.
  118.          */
  119.         if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
  120.                 status = acpi_ds_get_region_arguments(rgn_desc);
  121.                 if (ACPI_FAILURE(status)) {
  122.                         return_ACPI_STATUS(status);
  123.                 }
  124.         }
  125.  
  126.         /*
  127.          * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
  128.          * address space and the request cannot be directly validated
  129.          */
  130.         if (space_id == ACPI_ADR_SPACE_SMBUS ||
  131.             space_id == ACPI_ADR_SPACE_GSBUS ||
  132.             space_id == ACPI_ADR_SPACE_IPMI) {
  133.  
  134.                 /* SMBus or IPMI has a non-linear address space */
  135.  
  136.                 return_ACPI_STATUS(AE_OK);
  137.         }
  138. #ifdef ACPI_UNDER_DEVELOPMENT
  139.         /*
  140.          * If the Field access is any_acc, we can now compute the optimal
  141.          * access (because we know know the length of the parent region)
  142.          */
  143.         if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
  144.                 if (ACPI_FAILURE(status)) {
  145.                         return_ACPI_STATUS(status);
  146.                 }
  147.         }
  148. #endif
  149.  
  150.         /*
  151.          * Validate the request. The entire request from the byte offset for a
  152.          * length of one field datum (access width) must fit within the region.
  153.          * (Region length is specified in bytes)
  154.          */
  155.         if (rgn_desc->region.length <
  156.             (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
  157.              obj_desc->common_field.access_byte_width)) {
  158.                 if (acpi_gbl_enable_interpreter_slack) {
  159.                         /*
  160.                          * Slack mode only:  We will go ahead and allow access to this
  161.                          * field if it is within the region length rounded up to the next
  162.                          * access width boundary. acpi_size cast for 64-bit compile.
  163.                          */
  164.                         if (ACPI_ROUND_UP(rgn_desc->region.length,
  165.                                           obj_desc->common_field.
  166.                                           access_byte_width) >=
  167.                             ((acpi_size) obj_desc->common_field.
  168.                              base_byte_offset +
  169.                              obj_desc->common_field.access_byte_width +
  170.                              field_datum_byte_offset)) {
  171.                                 return_ACPI_STATUS(AE_OK);
  172.                         }
  173.                 }
  174.  
  175.                 if (rgn_desc->region.length <
  176.                     obj_desc->common_field.access_byte_width) {
  177.                         /*
  178.                          * This is the case where the access_type (acc_word, etc.) is wider
  179.                          * than the region itself. For example, a region of length one
  180.                          * byte, and a field with Dword access specified.
  181.                          */
  182.                         ACPI_ERROR((AE_INFO,
  183.                                     "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
  184.                                     acpi_ut_get_node_name(obj_desc->
  185.                                                           common_field.node),
  186.                                     obj_desc->common_field.access_byte_width,
  187.                                     acpi_ut_get_node_name(rgn_desc->region.
  188.                                                           node),
  189.                                     rgn_desc->region.length));
  190.                 }
  191.  
  192.                 /*
  193.                  * Offset rounded up to next multiple of field width
  194.                  * exceeds region length, indicate an error
  195.                  */
  196.                 ACPI_ERROR((AE_INFO,
  197.                             "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
  198.                             acpi_ut_get_node_name(obj_desc->common_field.node),
  199.                             obj_desc->common_field.base_byte_offset,
  200.                             field_datum_byte_offset,
  201.                             obj_desc->common_field.access_byte_width,
  202.                             acpi_ut_get_node_name(rgn_desc->region.node),
  203.                             rgn_desc->region.length));
  204.  
  205.                 return_ACPI_STATUS(AE_AML_REGION_LIMIT);
  206.         }
  207.  
  208.         return_ACPI_STATUS(AE_OK);
  209. }
  210.  
  211. /*******************************************************************************
  212.  *
  213.  * FUNCTION:    acpi_ex_access_region
  214.  *
  215.  * PARAMETERS:  obj_desc                - Field to be read
  216.  *              field_datum_byte_offset - Byte offset of this datum within the
  217.  *                                        parent field
  218.  *              value                   - Where to store value (must at least
  219.  *                                        64 bits)
  220.  *              function                - Read or Write flag plus other region-
  221.  *                                        dependent flags
  222.  *
  223.  * RETURN:      Status
  224.  *
  225.  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
  226.  *
  227.  ******************************************************************************/
  228.  
  229. acpi_status
  230. acpi_ex_access_region(union acpi_operand_object *obj_desc,
  231.                       u32 field_datum_byte_offset, u64 *value, u32 function)
  232. {
  233.         acpi_status status;
  234.         union acpi_operand_object *rgn_desc;
  235.         u32 region_offset;
  236.  
  237.         ACPI_FUNCTION_TRACE(ex_access_region);
  238.  
  239.         /*
  240.          * Ensure that the region operands are fully evaluated and verify
  241.          * the validity of the request
  242.          */
  243.         status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
  244.         if (ACPI_FAILURE(status)) {
  245.                 return_ACPI_STATUS(status);
  246.         }
  247.  
  248.         /*
  249.          * The physical address of this field datum is:
  250.          *
  251.          * 1) The base of the region, plus
  252.          * 2) The base offset of the field, plus
  253.          * 3) The current offset into the field
  254.          */
  255.         rgn_desc = obj_desc->common_field.region_obj;
  256.         region_offset =
  257.             obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
  258.  
  259.         if ((function & ACPI_IO_MASK) == ACPI_READ) {
  260.                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
  261.         } else {
  262.                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
  263.         }
  264.  
  265.         ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
  266.                               " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
  267.                               acpi_ut_get_region_name(rgn_desc->region.
  268.                                                       space_id),
  269.                               rgn_desc->region.space_id,
  270.                               obj_desc->common_field.access_byte_width,
  271.                               obj_desc->common_field.base_byte_offset,
  272.                               field_datum_byte_offset,
  273.                               ACPI_FORMAT_UINT64(rgn_desc->region.address +
  274.                                                  region_offset)));
  275.  
  276.         /* Invoke the appropriate address_space/op_region handler */
  277.  
  278.         status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
  279.                                                 function, region_offset,
  280.                                                 ACPI_MUL_8(obj_desc->
  281.                                                            common_field.
  282.                                                            access_byte_width),
  283.                                                 value);
  284.  
  285.         if (ACPI_FAILURE(status)) {
  286.                 if (status == AE_NOT_IMPLEMENTED) {
  287.                         ACPI_ERROR((AE_INFO,
  288.                                     "Region %s (ID=%u) not implemented",
  289.                                     acpi_ut_get_region_name(rgn_desc->region.
  290.                                                             space_id),
  291.                                     rgn_desc->region.space_id));
  292.                 } else if (status == AE_NOT_EXIST) {
  293.                         ACPI_ERROR((AE_INFO,
  294.                                     "Region %s (ID=%u) has no handler",
  295.                                     acpi_ut_get_region_name(rgn_desc->region.
  296.                                                             space_id),
  297.                                     rgn_desc->region.space_id));
  298.                 }
  299.         }
  300.  
  301.         return_ACPI_STATUS(status);
  302. }
  303.  
  304. /*******************************************************************************
  305.  *
  306.  * FUNCTION:    acpi_ex_register_overflow
  307.  *
  308.  * PARAMETERS:  obj_desc                - Register(Field) to be written
  309.  *              value                   - Value to be stored
  310.  *
  311.  * RETURN:      TRUE if value overflows the field, FALSE otherwise
  312.  *
  313.  * DESCRIPTION: Check if a value is out of range of the field being written.
  314.  *              Used to check if the values written to Index and Bank registers
  315.  *              are out of range. Normally, the value is simply truncated
  316.  *              to fit the field, but this case is most likely a serious
  317.  *              coding error in the ASL.
  318.  *
  319.  ******************************************************************************/
  320.  
  321. static u8
  322. acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
  323. {
  324.  
  325.         if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
  326.                 /*
  327.                  * The field is large enough to hold the maximum integer, so we can
  328.                  * never overflow it.
  329.                  */
  330.                 return (FALSE);
  331.         }
  332.  
  333.         if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) {
  334.                 /*
  335.                  * The Value is larger than the maximum value that can fit into
  336.                  * the register.
  337.                  */
  338.                 ACPI_ERROR((AE_INFO,
  339.                             "Index value 0x%8.8X%8.8X overflows field width 0x%X",
  340.                             ACPI_FORMAT_UINT64(value),
  341.                             obj_desc->common_field.bit_length));
  342.  
  343.                 return (TRUE);
  344.         }
  345.  
  346.         /* The Value will fit into the field with no truncation */
  347.  
  348.         return (FALSE);
  349. }
  350.  
  351. /*******************************************************************************
  352.  *
  353.  * FUNCTION:    acpi_ex_field_datum_io
  354.  *
  355.  * PARAMETERS:  obj_desc                - Field to be read
  356.  *              field_datum_byte_offset - Byte offset of this datum within the
  357.  *                                        parent field
  358.  *              value                   - Where to store value (must be 64 bits)
  359.  *              read_write              - Read or Write flag
  360.  *
  361.  * RETURN:      Status
  362.  *
  363.  * DESCRIPTION: Read or Write a single datum of a field. The field_type is
  364.  *              demultiplexed here to handle the different types of fields
  365.  *              (buffer_field, region_field, index_field, bank_field)
  366.  *
  367.  ******************************************************************************/
  368.  
  369. static acpi_status
  370. acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
  371.                        u32 field_datum_byte_offset, u64 *value, u32 read_write)
  372. {
  373.         acpi_status status;
  374.         u64 local_value;
  375.  
  376.         ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
  377.  
  378.         if (read_write == ACPI_READ) {
  379.                 if (!value) {
  380.                         local_value = 0;
  381.  
  382.                         /* To support reads without saving return value */
  383.                         value = &local_value;
  384.                 }
  385.  
  386.                 /* Clear the entire return buffer first, [Very Important!] */
  387.  
  388.                 *value = 0;
  389.         }
  390.  
  391.         /*
  392.          * The four types of fields are:
  393.          *
  394.          * buffer_field - Read/write from/to a Buffer
  395.          * region_field - Read/write from/to a Operation Region.
  396.          * bank_field  - Write to a Bank Register, then read/write from/to an
  397.          *               operation_region
  398.          * index_field - Write to an Index Register, then read/write from/to a
  399.          *               Data Register
  400.          */
  401.         switch (obj_desc->common.type) {
  402.         case ACPI_TYPE_BUFFER_FIELD:
  403.                 /*
  404.                  * If the buffer_field arguments have not been previously evaluated,
  405.                  * evaluate them now and save the results.
  406.                  */
  407.                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
  408.                         status = acpi_ds_get_buffer_field_arguments(obj_desc);
  409.                         if (ACPI_FAILURE(status)) {
  410.                                 return_ACPI_STATUS(status);
  411.                         }
  412.                 }
  413.  
  414.                 if (read_write == ACPI_READ) {
  415.                         /*
  416.                          * Copy the data from the source buffer.
  417.                          * Length is the field width in bytes.
  418.                          */
  419.                         memcpy(value,
  420.                                (obj_desc->buffer_field.buffer_obj)->buffer.
  421.                                pointer +
  422.                                obj_desc->buffer_field.base_byte_offset +
  423.                                field_datum_byte_offset,
  424.                                obj_desc->common_field.access_byte_width);
  425.                 } else {
  426.                         /*
  427.                          * Copy the data to the target buffer.
  428.                          * Length is the field width in bytes.
  429.                          */
  430.                         memcpy((obj_desc->buffer_field.buffer_obj)->buffer.
  431.                                pointer +
  432.                                obj_desc->buffer_field.base_byte_offset +
  433.                                field_datum_byte_offset, value,
  434.                                obj_desc->common_field.access_byte_width);
  435.                 }
  436.  
  437.                 status = AE_OK;
  438.                 break;
  439.  
  440.         case ACPI_TYPE_LOCAL_BANK_FIELD:
  441.                 /*
  442.                  * Ensure that the bank_value is not beyond the capacity of
  443.                  * the register
  444.                  */
  445.                 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
  446.                                               (u64) obj_desc->bank_field.
  447.                                               value)) {
  448.                         return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
  449.                 }
  450.  
  451.                 /*
  452.                  * For bank_fields, we must write the bank_value to the bank_register
  453.                  * (itself a region_field) before we can access the data.
  454.                  */
  455.                 status =
  456.                     acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
  457.                                               &obj_desc->bank_field.value,
  458.                                               sizeof(obj_desc->bank_field.
  459.                                                      value));
  460.                 if (ACPI_FAILURE(status)) {
  461.                         return_ACPI_STATUS(status);
  462.                 }
  463.  
  464.                 /*
  465.                  * Now that the Bank has been selected, fall through to the
  466.                  * region_field case and write the datum to the Operation Region
  467.                  */
  468.  
  469.                 /*lint -fallthrough */
  470.  
  471.         case ACPI_TYPE_LOCAL_REGION_FIELD:
  472.                 /*
  473.                  * For simple region_fields, we just directly access the owning
  474.                  * Operation Region.
  475.                  */
  476.                 status =
  477.                     acpi_ex_access_region(obj_desc, field_datum_byte_offset,
  478.                                           value, read_write);
  479.                 break;
  480.  
  481.         case ACPI_TYPE_LOCAL_INDEX_FIELD:
  482.                 /*
  483.                  * Ensure that the index_value is not beyond the capacity of
  484.                  * the register
  485.                  */
  486.                 if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
  487.                                               (u64) obj_desc->index_field.
  488.                                               value)) {
  489.                         return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
  490.                 }
  491.  
  492.                 /* Write the index value to the index_register (itself a region_field) */
  493.  
  494.                 field_datum_byte_offset += obj_desc->index_field.value;
  495.  
  496.                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  497.                                   "Write to Index Register: Value %8.8X\n",
  498.                                   field_datum_byte_offset));
  499.  
  500.                 status =
  501.                     acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
  502.                                               &field_datum_byte_offset,
  503.                                               sizeof(field_datum_byte_offset));
  504.                 if (ACPI_FAILURE(status)) {
  505.                         return_ACPI_STATUS(status);
  506.                 }
  507.  
  508.                 if (read_write == ACPI_READ) {
  509.  
  510.                         /* Read the datum from the data_register */
  511.  
  512.                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  513.                                           "Read from Data Register\n"));
  514.  
  515.                         status =
  516.                             acpi_ex_extract_from_field(obj_desc->index_field.
  517.                                                        data_obj, value,
  518.                                                        sizeof(u64));
  519.                 } else {
  520.                         /* Write the datum to the data_register */
  521.  
  522.                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  523.                                           "Write to Data Register: Value %8.8X%8.8X\n",
  524.                                           ACPI_FORMAT_UINT64(*value)));
  525.  
  526.                         status =
  527.                             acpi_ex_insert_into_field(obj_desc->index_field.
  528.                                                       data_obj, value,
  529.                                                       sizeof(u64));
  530.                 }
  531.                 break;
  532.  
  533.         default:
  534.  
  535.                 ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u",
  536.                             obj_desc->common.type));
  537.                 status = AE_AML_INTERNAL;
  538.                 break;
  539.         }
  540.  
  541.         if (ACPI_SUCCESS(status)) {
  542.                 if (read_write == ACPI_READ) {
  543.                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  544.                                           "Value Read %8.8X%8.8X, Width %u\n",
  545.                                           ACPI_FORMAT_UINT64(*value),
  546.                                           obj_desc->common_field.
  547.                                           access_byte_width));
  548.                 } else {
  549.                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  550.                                           "Value Written %8.8X%8.8X, Width %u\n",
  551.                                           ACPI_FORMAT_UINT64(*value),
  552.                                           obj_desc->common_field.
  553.                                           access_byte_width));
  554.                 }
  555.         }
  556.  
  557.         return_ACPI_STATUS(status);
  558. }
  559.  
  560. /*******************************************************************************
  561.  *
  562.  * FUNCTION:    acpi_ex_write_with_update_rule
  563.  *
  564.  * PARAMETERS:  obj_desc                - Field to be written
  565.  *              mask                    - bitmask within field datum
  566.  *              field_value             - Value to write
  567.  *              field_datum_byte_offset - Offset of datum within field
  568.  *
  569.  * RETURN:      Status
  570.  *
  571.  * DESCRIPTION: Apply the field update rule to a field write
  572.  *
  573.  ******************************************************************************/
  574.  
  575. acpi_status
  576. acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
  577.                                u64 mask,
  578.                                u64 field_value, u32 field_datum_byte_offset)
  579. {
  580.         acpi_status status = AE_OK;
  581.         u64 merged_value;
  582.         u64 current_value;
  583.  
  584.         ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
  585.  
  586.         /* Start with the new bits  */
  587.  
  588.         merged_value = field_value;
  589.  
  590.         /* If the mask is all ones, we don't need to worry about the update rule */
  591.  
  592.         if (mask != ACPI_UINT64_MAX) {
  593.  
  594.                 /* Decode the update rule */
  595.  
  596.                 switch (obj_desc->common_field.
  597.                         field_flags & AML_FIELD_UPDATE_RULE_MASK) {
  598.                 case AML_FIELD_UPDATE_PRESERVE:
  599.                         /*
  600.                          * Check if update rule needs to be applied (not if mask is all
  601.                          * ones)  The left shift drops the bits we want to ignore.
  602.                          */
  603.                         if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
  604.                                        ACPI_MUL_8(obj_desc->common_field.
  605.                                                   access_byte_width))) != 0) {
  606.                                 /*
  607.                                  * Read the current contents of the byte/word/dword containing
  608.                                  * the field, and merge with the new field value.
  609.                                  */
  610.                                 status =
  611.                                     acpi_ex_field_datum_io(obj_desc,
  612.                                                            field_datum_byte_offset,
  613.                                                            &current_value,
  614.                                                            ACPI_READ);
  615.                                 if (ACPI_FAILURE(status)) {
  616.                                         return_ACPI_STATUS(status);
  617.                                 }
  618.  
  619.                                 merged_value |= (current_value & ~mask);
  620.                         }
  621.                         break;
  622.  
  623.                 case AML_FIELD_UPDATE_WRITE_AS_ONES:
  624.  
  625.                         /* Set positions outside the field to all ones */
  626.  
  627.                         merged_value |= ~mask;
  628.                         break;
  629.  
  630.                 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
  631.  
  632.                         /* Set positions outside the field to all zeros */
  633.  
  634.                         merged_value &= mask;
  635.                         break;
  636.  
  637.                 default:
  638.  
  639.                         ACPI_ERROR((AE_INFO,
  640.                                     "Unknown UpdateRule value: 0x%X",
  641.                                     (obj_desc->common_field.
  642.                                      field_flags &
  643.                                      AML_FIELD_UPDATE_RULE_MASK)));
  644.                         return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
  645.                 }
  646.         }
  647.  
  648.         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
  649.                           "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
  650.                           ACPI_FORMAT_UINT64(mask),
  651.                           field_datum_byte_offset,
  652.                           obj_desc->common_field.access_byte_width,
  653.                           ACPI_FORMAT_UINT64(field_value),
  654.                           ACPI_FORMAT_UINT64(merged_value)));
  655.  
  656.         /* Write the merged value */
  657.  
  658.         status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
  659.                                         &merged_value, ACPI_WRITE);
  660.  
  661.         return_ACPI_STATUS(status);
  662. }
  663.  
  664. /*******************************************************************************
  665.  *
  666.  * FUNCTION:    acpi_ex_extract_from_field
  667.  *
  668.  * PARAMETERS:  obj_desc            - Field to be read
  669.  *              buffer              - Where to store the field data
  670.  *              buffer_length       - Length of Buffer
  671.  *
  672.  * RETURN:      Status
  673.  *
  674.  * DESCRIPTION: Retrieve the current value of the given field
  675.  *
  676.  ******************************************************************************/
  677.  
  678. acpi_status
  679. acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
  680.                            void *buffer, u32 buffer_length)
  681. {
  682.         acpi_status status;
  683.         u64 raw_datum;
  684.         u64 merged_datum;
  685.         u32 field_offset = 0;
  686.         u32 buffer_offset = 0;
  687.         u32 buffer_tail_bits;
  688.         u32 datum_count;
  689.         u32 field_datum_count;
  690.         u32 access_bit_width;
  691.         u32 i;
  692.  
  693.         ACPI_FUNCTION_TRACE(ex_extract_from_field);
  694.  
  695.         /* Validate target buffer and clear it */
  696.  
  697.         if (buffer_length <
  698.             ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
  699.                 ACPI_ERROR((AE_INFO,
  700.                             "Field size %u (bits) is too large for buffer (%u)",
  701.                             obj_desc->common_field.bit_length, buffer_length));
  702.  
  703.                 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
  704.         }
  705.  
  706.         memset(buffer, 0, buffer_length);
  707.         access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
  708.  
  709.         /* Handle the simple case here */
  710.  
  711.         if ((obj_desc->common_field.start_field_bit_offset == 0) &&
  712.             (obj_desc->common_field.bit_length == access_bit_width)) {
  713.                 if (buffer_length >= sizeof(u64)) {
  714.                         status =
  715.                             acpi_ex_field_datum_io(obj_desc, 0, buffer,
  716.                                                    ACPI_READ);
  717.                 } else {
  718.                         /* Use raw_datum (u64) to handle buffers < 64 bits */
  719.  
  720.                         status =
  721.                             acpi_ex_field_datum_io(obj_desc, 0, &raw_datum,
  722.                                                    ACPI_READ);
  723.                         memcpy(buffer, &raw_datum, buffer_length);
  724.                 }
  725.  
  726.                 return_ACPI_STATUS(status);
  727.         }
  728.  
  729. /* TBD: Move to common setup code */
  730.  
  731.         /* Field algorithm is limited to sizeof(u64), truncate if needed */
  732.  
  733.         if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
  734.                 obj_desc->common_field.access_byte_width = sizeof(u64);
  735.                 access_bit_width = sizeof(u64) * 8;
  736.         }
  737.  
  738.         /* Compute the number of datums (access width data items) */
  739.  
  740.         datum_count =
  741.             ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
  742.                              access_bit_width);
  743.  
  744.         field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
  745.                                              obj_desc->common_field.
  746.                                              start_field_bit_offset,
  747.                                              access_bit_width);
  748.  
  749.         /* Priming read from the field */
  750.  
  751.         status =
  752.             acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
  753.                                    ACPI_READ);
  754.         if (ACPI_FAILURE(status)) {
  755.                 return_ACPI_STATUS(status);
  756.         }
  757.         merged_datum =
  758.             raw_datum >> obj_desc->common_field.start_field_bit_offset;
  759.  
  760.         /* Read the rest of the field */
  761.  
  762.         for (i = 1; i < field_datum_count; i++) {
  763.  
  764.                 /* Get next input datum from the field */
  765.  
  766.                 field_offset += obj_desc->common_field.access_byte_width;
  767.                 status = acpi_ex_field_datum_io(obj_desc, field_offset,
  768.                                                 &raw_datum, ACPI_READ);
  769.                 if (ACPI_FAILURE(status)) {
  770.                         return_ACPI_STATUS(status);
  771.                 }
  772.  
  773.                 /*
  774.                  * Merge with previous datum if necessary.
  775.                  *
  776.                  * Note: Before the shift, check if the shift value will be larger than
  777.                  * the integer size. If so, there is no need to perform the operation.
  778.                  * This avoids the differences in behavior between different compilers
  779.                  * concerning shift values larger than the target data width.
  780.                  */
  781.                 if (access_bit_width -
  782.                     obj_desc->common_field.start_field_bit_offset <
  783.                     ACPI_INTEGER_BIT_SIZE) {
  784.                         merged_datum |=
  785.                             raw_datum << (access_bit_width -
  786.                                           obj_desc->common_field.
  787.                                           start_field_bit_offset);
  788.                 }
  789.  
  790.                 if (i == datum_count) {
  791.                         break;
  792.                 }
  793.  
  794.                 /* Write merged datum to target buffer */
  795.  
  796.                 memcpy(((char *)buffer) + buffer_offset, &merged_datum,
  797.                        ACPI_MIN(obj_desc->common_field.access_byte_width,
  798.                                 buffer_length - buffer_offset));
  799.  
  800.                 buffer_offset += obj_desc->common_field.access_byte_width;
  801.                 merged_datum =
  802.                     raw_datum >> obj_desc->common_field.start_field_bit_offset;
  803.         }
  804.  
  805.         /* Mask off any extra bits in the last datum */
  806.  
  807.         buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
  808.         if (buffer_tail_bits) {
  809.                 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
  810.         }
  811.  
  812.         /* Write the last datum to the buffer */
  813.  
  814.         memcpy(((char *)buffer) + buffer_offset, &merged_datum,
  815.                ACPI_MIN(obj_desc->common_field.access_byte_width,
  816.                         buffer_length - buffer_offset));
  817.  
  818.         return_ACPI_STATUS(AE_OK);
  819. }
  820.  
  821. /*******************************************************************************
  822.  *
  823.  * FUNCTION:    acpi_ex_insert_into_field
  824.  *
  825.  * PARAMETERS:  obj_desc            - Field to be written
  826.  *              buffer              - Data to be written
  827.  *              buffer_length       - Length of Buffer
  828.  *
  829.  * RETURN:      Status
  830.  *
  831.  * DESCRIPTION: Store the Buffer contents into the given field
  832.  *
  833.  ******************************************************************************/
  834.  
  835. acpi_status
  836. acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
  837.                           void *buffer, u32 buffer_length)
  838. {
  839.         void *new_buffer;
  840.         acpi_status status;
  841.         u64 mask;
  842.         u64 width_mask;
  843.         u64 merged_datum;
  844.         u64 raw_datum = 0;
  845.         u32 field_offset = 0;
  846.         u32 buffer_offset = 0;
  847.         u32 buffer_tail_bits;
  848.         u32 datum_count;
  849.         u32 field_datum_count;
  850.         u32 access_bit_width;
  851.         u32 required_length;
  852.         u32 i;
  853.  
  854.         ACPI_FUNCTION_TRACE(ex_insert_into_field);
  855.  
  856.         /* Validate input buffer */
  857.  
  858.         new_buffer = NULL;
  859.         required_length =
  860.             ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
  861.         /*
  862.          * We must have a buffer that is at least as long as the field
  863.          * we are writing to. This is because individual fields are
  864.          * indivisible and partial writes are not supported -- as per
  865.          * the ACPI specification.
  866.          */
  867.         if (buffer_length < required_length) {
  868.  
  869.                 /* We need to create a new buffer */
  870.  
  871.                 new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
  872.                 if (!new_buffer) {
  873.                         return_ACPI_STATUS(AE_NO_MEMORY);
  874.                 }
  875.  
  876.                 /*
  877.                  * Copy the original data to the new buffer, starting
  878.                  * at Byte zero. All unused (upper) bytes of the
  879.                  * buffer will be 0.
  880.                  */
  881.                 memcpy((char *)new_buffer, (char *)buffer, buffer_length);
  882.                 buffer = new_buffer;
  883.                 buffer_length = required_length;
  884.         }
  885.  
  886. /* TBD: Move to common setup code */
  887.  
  888.         /* Algo is limited to sizeof(u64), so cut the access_byte_width */
  889.         if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
  890.                 obj_desc->common_field.access_byte_width = sizeof(u64);
  891.         }
  892.  
  893.         access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
  894.  
  895.         /*
  896.          * Create the bitmasks used for bit insertion.
  897.          * Note: This if/else is used to bypass compiler differences with the
  898.          * shift operator
  899.          */
  900.         if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
  901.                 width_mask = ACPI_UINT64_MAX;
  902.         } else {
  903.                 width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
  904.         }
  905.  
  906.         mask = width_mask &
  907.             ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
  908.  
  909.         /* Compute the number of datums (access width data items) */
  910.  
  911.         datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
  912.                                        access_bit_width);
  913.  
  914.         field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
  915.                                              obj_desc->common_field.
  916.                                              start_field_bit_offset,
  917.                                              access_bit_width);
  918.  
  919.         /* Get initial Datum from the input buffer */
  920.  
  921.         memcpy(&raw_datum, buffer,
  922.                ACPI_MIN(obj_desc->common_field.access_byte_width,
  923.                         buffer_length - buffer_offset));
  924.  
  925.         merged_datum =
  926.             raw_datum << obj_desc->common_field.start_field_bit_offset;
  927.  
  928.         /* Write the entire field */
  929.  
  930.         for (i = 1; i < field_datum_count; i++) {
  931.  
  932.                 /* Write merged datum to the target field */
  933.  
  934.                 merged_datum &= mask;
  935.                 status = acpi_ex_write_with_update_rule(obj_desc, mask,
  936.                                                         merged_datum,
  937.                                                         field_offset);
  938.                 if (ACPI_FAILURE(status)) {
  939.                         goto exit;
  940.                 }
  941.  
  942.                 field_offset += obj_desc->common_field.access_byte_width;
  943.  
  944.                 /*
  945.                  * Start new output datum by merging with previous input datum
  946.                  * if necessary.
  947.                  *
  948.                  * Note: Before the shift, check if the shift value will be larger than
  949.                  * the integer size. If so, there is no need to perform the operation.
  950.                  * This avoids the differences in behavior between different compilers
  951.                  * concerning shift values larger than the target data width.
  952.                  */
  953.                 if ((access_bit_width -
  954.                      obj_desc->common_field.start_field_bit_offset) <
  955.                     ACPI_INTEGER_BIT_SIZE) {
  956.                         merged_datum =
  957.                             raw_datum >> (access_bit_width -
  958.                                           obj_desc->common_field.
  959.                                           start_field_bit_offset);
  960.                 } else {
  961.                         merged_datum = 0;
  962.                 }
  963.  
  964.                 mask = width_mask;
  965.  
  966.                 if (i == datum_count) {
  967.                         break;
  968.                 }
  969.  
  970.                 /* Get the next input datum from the buffer */
  971.  
  972.                 buffer_offset += obj_desc->common_field.access_byte_width;
  973.                 memcpy(&raw_datum, ((char *)buffer) + buffer_offset,
  974.                        ACPI_MIN(obj_desc->common_field.access_byte_width,
  975.                                 buffer_length - buffer_offset));
  976.  
  977.                 merged_datum |=
  978.                     raw_datum << obj_desc->common_field.start_field_bit_offset;
  979.         }
  980.  
  981.         /* Mask off any extra bits in the last datum */
  982.  
  983.         buffer_tail_bits = (obj_desc->common_field.bit_length +
  984.                             obj_desc->common_field.start_field_bit_offset) %
  985.             access_bit_width;
  986.         if (buffer_tail_bits) {
  987.                 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
  988.         }
  989.  
  990.         /* Write the last datum to the field */
  991.  
  992.         merged_datum &= mask;
  993.         status = acpi_ex_write_with_update_rule(obj_desc,
  994.                                                 mask, merged_datum,
  995.                                                 field_offset);
  996.  
  997. exit:
  998.         /* Free temporary buffer if we used one */
  999.  
  1000.         if (new_buffer) {
  1001.                 ACPI_FREE(new_buffer);
  1002.         }
  1003.         return_ACPI_STATUS(status);
  1004. }
  1005.