1 /******************************************************************************
 
   3  * Module Name: exfldio - Aml Field I/O
 
   5  *****************************************************************************/
 
   8  * Copyright (C) 2000 - 2008, Intel Corp.
 
  11  * Redistribution and use in source and binary forms, with or without
 
  12  * modification, are permitted provided that the following conditions
 
  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.
 
  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.
 
  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.
 
  44 #include <acpi/acpi.h>
 
  45 #include <acpi/acinterp.h>
 
  46 #include <acpi/amlcode.h>
 
  47 #include <acpi/acevents.h>
 
  48 #include <acpi/acdispat.h>
 
  50 #define _COMPONENT          ACPI_EXECUTER
 
  51 ACPI_MODULE_NAME("exfldio")
 
  53 /* Local prototypes */
 
  55 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
 
  56                        u32 field_datum_byte_offset,
 
  57                        acpi_integer * value, u32 read_write);
 
  60 acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
 
  64 acpi_ex_setup_region(union acpi_operand_object *obj_desc,
 
  65                      u32 field_datum_byte_offset);
 
  67 /*******************************************************************************
 
  69  * FUNCTION:    acpi_ex_setup_region
 
  71  * PARAMETERS:  obj_desc                - Field to be read or written
 
  72  *              field_datum_byte_offset - Byte offset of this datum within the
 
  77  * DESCRIPTION: Common processing for acpi_ex_extract_from_field and
 
  78  *              acpi_ex_insert_into_field. Initialize the Region if necessary and
 
  79  *              validate the request.
 
  81  ******************************************************************************/
 
  84 acpi_ex_setup_region(union acpi_operand_object *obj_desc,
 
  85                      u32 field_datum_byte_offset)
 
  87         acpi_status status = AE_OK;
 
  88         union acpi_operand_object *rgn_desc;
 
  90         ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
 
  92         rgn_desc = obj_desc->common_field.region_obj;
 
  94         /* We must have a valid region */
 
  96         if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) {
 
  97                 ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)",
 
  98                             ACPI_GET_OBJECT_TYPE(rgn_desc),
 
  99                             acpi_ut_get_object_type_name(rgn_desc)));
 
 101                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 
 105          * If the Region Address and Length have not been previously evaluated,
 
 106          * evaluate them now and save the results.
 
 108         if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
 
 109                 status = acpi_ds_get_region_arguments(rgn_desc);
 
 110                 if (ACPI_FAILURE(status)) {
 
 111                         return_ACPI_STATUS(status);
 
 115         /* Exit if Address/Length have been disallowed by the host OS */
 
 117         if (rgn_desc->common.flags & AOPOBJ_INVALID) {
 
 118                 return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
 
 122          * Exit now for SMBus address space, it has a non-linear address space
 
 123          * and the request cannot be directly validated
 
 125         if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
 
 127                 /* SMBus has a non-linear address space */
 
 129                 return_ACPI_STATUS(AE_OK);
 
 131 #ifdef ACPI_UNDER_DEVELOPMENT
 
 133          * If the Field access is any_acc, we can now compute the optimal
 
 134          * access (because we know know the length of the parent region)
 
 136         if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
 
 137                 if (ACPI_FAILURE(status)) {
 
 138                         return_ACPI_STATUS(status);
 
 144          * Validate the request.  The entire request from the byte offset for a
 
 145          * length of one field datum (access width) must fit within the region.
 
 146          * (Region length is specified in bytes)
 
 148         if (rgn_desc->region.length <
 
 149             (obj_desc->common_field.base_byte_offset +
 
 150              field_datum_byte_offset +
 
 151              obj_desc->common_field.access_byte_width)) {
 
 152                 if (acpi_gbl_enable_interpreter_slack) {
 
 154                          * Slack mode only:  We will go ahead and allow access to this
 
 155                          * field if it is within the region length rounded up to the next
 
 156                          * access width boundary.
 
 158                         if (ACPI_ROUND_UP(rgn_desc->region.length,
 
 159                                           obj_desc->common_field.
 
 160                                           access_byte_width) >=
 
 161                             (obj_desc->common_field.base_byte_offset +
 
 162                              (acpi_native_uint) obj_desc->common_field.
 
 163                              access_byte_width + field_datum_byte_offset)) {
 
 164                                 return_ACPI_STATUS(AE_OK);
 
 168                 if (rgn_desc->region.length <
 
 169                     obj_desc->common_field.access_byte_width) {
 
 171                          * This is the case where the access_type (acc_word, etc.) is wider
 
 172                          * than the region itself.  For example, a region of length one
 
 173                          * byte, and a field with Dword access specified.
 
 176                                     "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)",
 
 177                                     acpi_ut_get_node_name(obj_desc->
 
 179                                     obj_desc->common_field.access_byte_width,
 
 180                                     acpi_ut_get_node_name(rgn_desc->region.
 
 182                                     rgn_desc->region.length));
 
 186                  * Offset rounded up to next multiple of field width
 
 187                  * exceeds region length, indicate an error
 
 190                             "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)",
 
 191                             acpi_ut_get_node_name(obj_desc->common_field.node),
 
 192                             obj_desc->common_field.base_byte_offset,
 
 193                             field_datum_byte_offset,
 
 194                             obj_desc->common_field.access_byte_width,
 
 195                             acpi_ut_get_node_name(rgn_desc->region.node),
 
 196                             rgn_desc->region.length));
 
 198                 return_ACPI_STATUS(AE_AML_REGION_LIMIT);
 
 201         return_ACPI_STATUS(AE_OK);
 
 204 /*******************************************************************************
 
 206  * FUNCTION:    acpi_ex_access_region
 
 208  * PARAMETERS:  obj_desc                - Field to be read
 
 209  *              field_datum_byte_offset - Byte offset of this datum within the
 
 211  *              Value                   - Where to store value (must at least
 
 212  *                                        the size of acpi_integer)
 
 213  *              Function                - Read or Write flag plus other region-
 
 218  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
 
 220  ******************************************************************************/
 
 223 acpi_ex_access_region(union acpi_operand_object *obj_desc,
 
 224                       u32 field_datum_byte_offset,
 
 225                       acpi_integer * value, u32 function)
 
 228         union acpi_operand_object *rgn_desc;
 
 229         acpi_physical_address address;
 
 231         ACPI_FUNCTION_TRACE(ex_access_region);
 
 234          * Ensure that the region operands are fully evaluated and verify
 
 235          * the validity of the request
 
 237         status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
 
 238         if (ACPI_FAILURE(status)) {
 
 239                 return_ACPI_STATUS(status);
 
 243          * The physical address of this field datum is:
 
 245          * 1) The base of the region, plus
 
 246          * 2) The base offset of the field, plus
 
 247          * 3) The current offset into the field
 
 249         rgn_desc = obj_desc->common_field.region_obj;
 
 250         address = rgn_desc->region.address +
 
 251             obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
 
 253         if ((function & ACPI_IO_MASK) == ACPI_READ) {
 
 254                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
 
 256                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
 
 259         ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
 
 260                               " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
 
 261                               acpi_ut_get_region_name(rgn_desc->region.
 
 263                               rgn_desc->region.space_id,
 
 264                               obj_desc->common_field.access_byte_width,
 
 265                               obj_desc->common_field.base_byte_offset,
 
 266                               field_datum_byte_offset, ACPI_CAST_PTR(void,
 
 269         /* Invoke the appropriate address_space/op_region handler */
 
 271         status = acpi_ev_address_space_dispatch(rgn_desc, function,
 
 273                                                 ACPI_MUL_8(obj_desc->
 
 278         if (ACPI_FAILURE(status)) {
 
 279                 if (status == AE_NOT_IMPLEMENTED) {
 
 281                                     "Region %s(%X) not implemented",
 
 282                                     acpi_ut_get_region_name(rgn_desc->region.
 
 284                                     rgn_desc->region.space_id));
 
 285                 } else if (status == AE_NOT_EXIST) {
 
 287                                     "Region %s(%X) has no handler",
 
 288                                     acpi_ut_get_region_name(rgn_desc->region.
 
 290                                     rgn_desc->region.space_id));
 
 294         return_ACPI_STATUS(status);
 
 297 /*******************************************************************************
 
 299  * FUNCTION:    acpi_ex_register_overflow
 
 301  * PARAMETERS:  obj_desc                - Register(Field) to be written
 
 302  *              Value                   - Value to be stored
 
 304  * RETURN:      TRUE if value overflows the field, FALSE otherwise
 
 306  * DESCRIPTION: Check if a value is out of range of the field being written.
 
 307  *              Used to check if the values written to Index and Bank registers
 
 308  *              are out of range.  Normally, the value is simply truncated
 
 309  *              to fit the field, but this case is most likely a serious
 
 310  *              coding error in the ASL.
 
 312  ******************************************************************************/
 
 315 acpi_ex_register_overflow(union acpi_operand_object *obj_desc,
 
 319         if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
 
 321                  * The field is large enough to hold the maximum integer, so we can
 
 327         if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) {
 
 329                  * The Value is larger than the maximum value that can fit into
 
 335         /* The Value will fit into the field with no truncation */
 
 340 /*******************************************************************************
 
 342  * FUNCTION:    acpi_ex_field_datum_io
 
 344  * PARAMETERS:  obj_desc                - Field to be read
 
 345  *              field_datum_byte_offset - Byte offset of this datum within the
 
 347  *              Value                   - Where to store value (must be 64 bits)
 
 348  *              read_write              - Read or Write flag
 
 352  * DESCRIPTION: Read or Write a single datum of a field.  The field_type is
 
 353  *              demultiplexed here to handle the different types of fields
 
 354  *              (buffer_field, region_field, index_field, bank_field)
 
 356  ******************************************************************************/
 
 359 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
 
 360                        u32 field_datum_byte_offset,
 
 361                        acpi_integer * value, u32 read_write)
 
 364         acpi_integer local_value;
 
 366         ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
 
 368         if (read_write == ACPI_READ) {
 
 372                         /* To support reads without saving return value */
 
 373                         value = &local_value;
 
 376                 /* Clear the entire return buffer first, [Very Important!] */
 
 382          * The four types of fields are:
 
 384          * buffer_field - Read/write from/to a Buffer
 
 385          * region_field - Read/write from/to a Operation Region.
 
 386          * bank_field  - Write to a Bank Register, then read/write from/to an
 
 388          * index_field - Write to an Index Register, then read/write from/to a
 
 391         switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
 
 392         case ACPI_TYPE_BUFFER_FIELD:
 
 394                  * If the buffer_field arguments have not been previously evaluated,
 
 395                  * evaluate them now and save the results.
 
 397                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
 
 398                         status = acpi_ds_get_buffer_field_arguments(obj_desc);
 
 399                         if (ACPI_FAILURE(status)) {
 
 400                                 return_ACPI_STATUS(status);
 
 404                 if (read_write == ACPI_READ) {
 
 406                          * Copy the data from the source buffer.
 
 407                          * Length is the field width in bytes.
 
 410                                     (obj_desc->buffer_field.buffer_obj)->buffer.
 
 412                                     obj_desc->buffer_field.base_byte_offset +
 
 413                                     field_datum_byte_offset,
 
 414                                     obj_desc->common_field.access_byte_width);
 
 417                          * Copy the data to the target buffer.
 
 418                          * Length is the field width in bytes.
 
 420                         ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
 
 422                                     obj_desc->buffer_field.base_byte_offset +
 
 423                                     field_datum_byte_offset, value,
 
 424                                     obj_desc->common_field.access_byte_width);
 
 430         case ACPI_TYPE_LOCAL_BANK_FIELD:
 
 433                  * Ensure that the bank_value is not beyond the capacity of
 
 436                 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
 
 437                                               (acpi_integer) obj_desc->
 
 439                         return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
 
 443                  * For bank_fields, we must write the bank_value to the bank_register
 
 444                  * (itself a region_field) before we can access the data.
 
 447                     acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
 
 448                                               &obj_desc->bank_field.value,
 
 449                                               sizeof(obj_desc->bank_field.
 
 451                 if (ACPI_FAILURE(status)) {
 
 452                         return_ACPI_STATUS(status);
 
 456                  * Now that the Bank has been selected, fall through to the
 
 457                  * region_field case and write the datum to the Operation Region
 
 460                 /*lint -fallthrough */
 
 462         case ACPI_TYPE_LOCAL_REGION_FIELD:
 
 464                  * For simple region_fields, we just directly access the owning
 
 468                     acpi_ex_access_region(obj_desc, field_datum_byte_offset,
 
 472         case ACPI_TYPE_LOCAL_INDEX_FIELD:
 
 475                  * Ensure that the index_value is not beyond the capacity of
 
 478                 if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
 
 479                                               (acpi_integer) obj_desc->
 
 480                                               index_field.value)) {
 
 481                         return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
 
 484                 /* Write the index value to the index_register (itself a region_field) */
 
 486                 field_datum_byte_offset += obj_desc->index_field.value;
 
 488                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 
 489                                   "Write to Index Register: Value %8.8X\n",
 
 490                                   field_datum_byte_offset));
 
 493                     acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
 
 494                                               &field_datum_byte_offset,
 
 495                                               sizeof(field_datum_byte_offset));
 
 496                 if (ACPI_FAILURE(status)) {
 
 497                         return_ACPI_STATUS(status);
 
 500                 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 
 501                                   "I/O to Data Register: ValuePtr %p\n",
 
 504                 if (read_write == ACPI_READ) {
 
 506                         /* Read the datum from the data_register */
 
 509                             acpi_ex_extract_from_field(obj_desc->index_field.
 
 511                                                        sizeof(acpi_integer));
 
 513                         /* Write the datum to the data_register */
 
 516                             acpi_ex_insert_into_field(obj_desc->index_field.
 
 518                                                       sizeof(acpi_integer));
 
 524                 ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X",
 
 525                             ACPI_GET_OBJECT_TYPE(obj_desc)));
 
 526                 status = AE_AML_INTERNAL;
 
 530         if (ACPI_SUCCESS(status)) {
 
 531                 if (read_write == ACPI_READ) {
 
 532                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 
 533                                           "Value Read %8.8X%8.8X, Width %d\n",
 
 534                                           ACPI_FORMAT_UINT64(*value),
 
 535                                           obj_desc->common_field.
 
 538                         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 
 539                                           "Value Written %8.8X%8.8X, Width %d\n",
 
 540                                           ACPI_FORMAT_UINT64(*value),
 
 541                                           obj_desc->common_field.
 
 546         return_ACPI_STATUS(status);
 
 549 /*******************************************************************************
 
 551  * FUNCTION:    acpi_ex_write_with_update_rule
 
 553  * PARAMETERS:  obj_desc                - Field to be written
 
 554  *              Mask                    - bitmask within field datum
 
 555  *              field_value             - Value to write
 
 556  *              field_datum_byte_offset - Offset of datum within field
 
 560  * DESCRIPTION: Apply the field update rule to a field write
 
 562  ******************************************************************************/
 
 565 acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
 
 567                                acpi_integer field_value,
 
 568                                u32 field_datum_byte_offset)
 
 570         acpi_status status = AE_OK;
 
 571         acpi_integer merged_value;
 
 572         acpi_integer current_value;
 
 574         ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
 
 576         /* Start with the new bits  */
 
 578         merged_value = field_value;
 
 580         /* If the mask is all ones, we don't need to worry about the update rule */
 
 582         if (mask != ACPI_INTEGER_MAX) {
 
 584                 /* Decode the update rule */
 
 586                 switch (obj_desc->common_field.
 
 587                         field_flags & AML_FIELD_UPDATE_RULE_MASK) {
 
 588                 case AML_FIELD_UPDATE_PRESERVE:
 
 590                          * Check if update rule needs to be applied (not if mask is all
 
 591                          * ones)  The left shift drops the bits we want to ignore.
 
 593                         if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
 
 594                                        ACPI_MUL_8(obj_desc->common_field.
 
 595                                                   access_byte_width))) != 0) {
 
 597                                  * Read the current contents of the byte/word/dword containing
 
 598                                  * the field, and merge with the new field value.
 
 601                                     acpi_ex_field_datum_io(obj_desc,
 
 602                                                            field_datum_byte_offset,
 
 605                                 if (ACPI_FAILURE(status)) {
 
 606                                         return_ACPI_STATUS(status);
 
 609                                 merged_value |= (current_value & ~mask);
 
 613                 case AML_FIELD_UPDATE_WRITE_AS_ONES:
 
 615                         /* Set positions outside the field to all ones */
 
 617                         merged_value |= ~mask;
 
 620                 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
 
 622                         /* Set positions outside the field to all zeros */
 
 624                         merged_value &= mask;
 
 630                                     "Unknown UpdateRule value: %X",
 
 631                                     (obj_desc->common_field.
 
 633                                      AML_FIELD_UPDATE_RULE_MASK)));
 
 634                         return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 
 638         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 
 639                           "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
 
 640                           ACPI_FORMAT_UINT64(mask),
 
 641                           field_datum_byte_offset,
 
 642                           obj_desc->common_field.access_byte_width,
 
 643                           ACPI_FORMAT_UINT64(field_value),
 
 644                           ACPI_FORMAT_UINT64(merged_value)));
 
 646         /* Write the merged value */
 
 648         status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
 
 649                                         &merged_value, ACPI_WRITE);
 
 651         return_ACPI_STATUS(status);
 
 654 /*******************************************************************************
 
 656  * FUNCTION:    acpi_ex_extract_from_field
 
 658  * PARAMETERS:  obj_desc            - Field to be read
 
 659  *              Buffer              - Where to store the field data
 
 660  *              buffer_length       - Length of Buffer
 
 664  * DESCRIPTION: Retrieve the current value of the given field
 
 666  ******************************************************************************/
 
 669 acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
 
 670                            void *buffer, u32 buffer_length)
 
 673         acpi_integer raw_datum;
 
 674         acpi_integer merged_datum;
 
 675         u32 field_offset = 0;
 
 676         u32 buffer_offset = 0;
 
 677         u32 buffer_tail_bits;
 
 679         u32 field_datum_count;
 
 682         ACPI_FUNCTION_TRACE(ex_extract_from_field);
 
 684         /* Validate target buffer and clear it */
 
 687             ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
 
 689                             "Field size %X (bits) is too large for buffer (%X)",
 
 690                             obj_desc->common_field.bit_length, buffer_length));
 
 692                 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
 
 694         ACPI_MEMSET(buffer, 0, buffer_length);
 
 696         /* Compute the number of datums (access width data items) */
 
 698         datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
 
 699                                        obj_desc->common_field.access_bit_width);
 
 700         field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 
 701                                              obj_desc->common_field.
 
 702                                              start_field_bit_offset,
 
 703                                              obj_desc->common_field.
 
 706         /* Priming read from the field */
 
 709             acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
 
 711         if (ACPI_FAILURE(status)) {
 
 712                 return_ACPI_STATUS(status);
 
 715             raw_datum >> obj_desc->common_field.start_field_bit_offset;
 
 717         /* Read the rest of the field */
 
 719         for (i = 1; i < field_datum_count; i++) {
 
 721                 /* Get next input datum from the field */
 
 723                 field_offset += obj_desc->common_field.access_byte_width;
 
 724                 status = acpi_ex_field_datum_io(obj_desc, field_offset,
 
 725                                                 &raw_datum, ACPI_READ);
 
 726                 if (ACPI_FAILURE(status)) {
 
 727                         return_ACPI_STATUS(status);
 
 731                  * Merge with previous datum if necessary.
 
 733                  * Note: Before the shift, check if the shift value will be larger than
 
 734                  * the integer size. If so, there is no need to perform the operation.
 
 735                  * This avoids the differences in behavior between different compilers
 
 736                  * concerning shift values larger than the target data width.
 
 738                 if ((obj_desc->common_field.access_bit_width -
 
 739                      obj_desc->common_field.start_field_bit_offset) <
 
 740                     ACPI_INTEGER_BIT_SIZE) {
 
 742                             raw_datum << (obj_desc->common_field.
 
 744                                           obj_desc->common_field.
 
 745                                           start_field_bit_offset);
 
 748                 if (i == datum_count) {
 
 752                 /* Write merged datum to target buffer */
 
 754                 ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
 
 755                             ACPI_MIN(obj_desc->common_field.access_byte_width,
 
 756                                      buffer_length - buffer_offset));
 
 758                 buffer_offset += obj_desc->common_field.access_byte_width;
 
 760                     raw_datum >> obj_desc->common_field.start_field_bit_offset;
 
 763         /* Mask off any extra bits in the last datum */
 
 765         buffer_tail_bits = obj_desc->common_field.bit_length %
 
 766             obj_desc->common_field.access_bit_width;
 
 767         if (buffer_tail_bits) {
 
 768                 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 
 771         /* Write the last datum to the buffer */
 
 773         ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
 
 774                     ACPI_MIN(obj_desc->common_field.access_byte_width,
 
 775                              buffer_length - buffer_offset));
 
 777         return_ACPI_STATUS(AE_OK);
 
 780 /*******************************************************************************
 
 782  * FUNCTION:    acpi_ex_insert_into_field
 
 784  * PARAMETERS:  obj_desc            - Field to be written
 
 785  *              Buffer              - Data to be written
 
 786  *              buffer_length       - Length of Buffer
 
 790  * DESCRIPTION: Store the Buffer contents into the given field
 
 792  ******************************************************************************/
 
 795 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 
 796                           void *buffer, u32 buffer_length)
 
 800         acpi_integer width_mask;
 
 801         acpi_integer merged_datum;
 
 802         acpi_integer raw_datum = 0;
 
 803         u32 field_offset = 0;
 
 804         u32 buffer_offset = 0;
 
 805         u32 buffer_tail_bits;
 
 807         u32 field_datum_count;
 
 812         ACPI_FUNCTION_TRACE(ex_insert_into_field);
 
 814         /* Validate input buffer */
 
 818             ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
 
 820          * We must have a buffer that is at least as long as the field
 
 821          * we are writing to.  This is because individual fields are
 
 822          * indivisible and partial writes are not supported -- as per
 
 823          * the ACPI specification.
 
 825         if (buffer_length < required_length) {
 
 827                 /* We need to create a new buffer */
 
 829                 new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
 
 831                         return_ACPI_STATUS(AE_NO_MEMORY);
 
 835                  * Copy the original data to the new buffer, starting
 
 836                  * at Byte zero.  All unused (upper) bytes of the
 
 839                 ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
 
 841                 buffer_length = required_length;
 
 845          * Create the bitmasks used for bit insertion.
 
 846          * Note: This if/else is used to bypass compiler differences with the
 
 849         if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
 
 850                 width_mask = ACPI_INTEGER_MAX;
 
 853                     ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
 
 858             ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
 
 860         /* Compute the number of datums (access width data items) */
 
 862         datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
 
 863                                        obj_desc->common_field.access_bit_width);
 
 865         field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 
 866                                              obj_desc->common_field.
 
 867                                              start_field_bit_offset,
 
 868                                              obj_desc->common_field.
 
 871         /* Get initial Datum from the input buffer */
 
 873         ACPI_MEMCPY(&raw_datum, buffer,
 
 874                     ACPI_MIN(obj_desc->common_field.access_byte_width,
 
 875                              buffer_length - buffer_offset));
 
 878             raw_datum << obj_desc->common_field.start_field_bit_offset;
 
 880         /* Write the entire field */
 
 882         for (i = 1; i < field_datum_count; i++) {
 
 884                 /* Write merged datum to the target field */
 
 886                 merged_datum &= mask;
 
 887                 status = acpi_ex_write_with_update_rule(obj_desc, mask,
 
 890                 if (ACPI_FAILURE(status)) {
 
 894                 field_offset += obj_desc->common_field.access_byte_width;
 
 897                  * Start new output datum by merging with previous input datum
 
 900                  * Note: Before the shift, check if the shift value will be larger than
 
 901                  * the integer size. If so, there is no need to perform the operation.
 
 902                  * This avoids the differences in behavior between different compilers
 
 903                  * concerning shift values larger than the target data width.
 
 905                 if ((obj_desc->common_field.access_bit_width -
 
 906                      obj_desc->common_field.start_field_bit_offset) <
 
 907                     ACPI_INTEGER_BIT_SIZE) {
 
 909                             raw_datum >> (obj_desc->common_field.
 
 911                                           obj_desc->common_field.
 
 912                                           start_field_bit_offset);
 
 919                 if (i == datum_count) {
 
 923                 /* Get the next input datum from the buffer */
 
 925                 buffer_offset += obj_desc->common_field.access_byte_width;
 
 926                 ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
 
 927                             ACPI_MIN(obj_desc->common_field.access_byte_width,
 
 928                                      buffer_length - buffer_offset));
 
 930                     raw_datum << obj_desc->common_field.start_field_bit_offset;
 
 933         /* Mask off any extra bits in the last datum */
 
 935         buffer_tail_bits = (obj_desc->common_field.bit_length +
 
 936                             obj_desc->common_field.start_field_bit_offset) %
 
 937             obj_desc->common_field.access_bit_width;
 
 938         if (buffer_tail_bits) {
 
 939                 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 
 942         /* Write the last datum to the field */
 
 944         merged_datum &= mask;
 
 945         status = acpi_ex_write_with_update_rule(obj_desc,
 
 950         /* Free temporary buffer if we used one */
 
 953                 ACPI_FREE(new_buffer);
 
 955         return_ACPI_STATUS(status);