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