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 - 2013, 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, u64 *value, u32 read_write);
  58
  59static u8
  60acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
  61
  62static acpi_status
  63acpi_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
  82static acpi_status
  83acpi_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
 229acpi_status
 230acpi_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 %p\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, ACPI_CAST_PTR(void,
 273                                                                     (rgn_desc->
 274                                                                      region.
 275                                                                      address +
 276                                                                      region_offset))));
 277
 278        /* Invoke the appropriate address_space/op_region handler */
 279
 280        status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
 281                                                function, region_offset,
 282                                                ACPI_MUL_8(obj_desc->
 283                                                           common_field.
 284                                                           access_byte_width),
 285                                                value);
 286
 287        if (ACPI_FAILURE(status)) {
 288                if (status == AE_NOT_IMPLEMENTED) {
 289                        ACPI_ERROR((AE_INFO,
 290                                    "Region %s (ID=%u) not implemented",
 291                                    acpi_ut_get_region_name(rgn_desc->region.
 292                                                            space_id),
 293                                    rgn_desc->region.space_id));
 294                } else if (status == AE_NOT_EXIST) {
 295                        ACPI_ERROR((AE_INFO,
 296                                    "Region %s (ID=%u) has no handler",
 297                                    acpi_ut_get_region_name(rgn_desc->region.
 298                                                            space_id),
 299                                    rgn_desc->region.space_id));
 300                }
 301        }
 302
 303        return_ACPI_STATUS(status);
 304}
 305
 306/*******************************************************************************
 307 *
 308 * FUNCTION:    acpi_ex_register_overflow
 309 *
 310 * PARAMETERS:  obj_desc                - Register(Field) to be written
 311 *              value                   - Value to be stored
 312 *
 313 * RETURN:      TRUE if value overflows the field, FALSE otherwise
 314 *
 315 * DESCRIPTION: Check if a value is out of range of the field being written.
 316 *              Used to check if the values written to Index and Bank registers
 317 *              are out of range. Normally, the value is simply truncated
 318 *              to fit the field, but this case is most likely a serious
 319 *              coding error in the ASL.
 320 *
 321 ******************************************************************************/
 322
 323static u8
 324acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
 325{
 326
 327        if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
 328                /*
 329                 * The field is large enough to hold the maximum integer, so we can
 330                 * never overflow it.
 331                 */
 332                return (FALSE);
 333        }
 334
 335        if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) {
 336                /*
 337                 * The Value is larger than the maximum value that can fit into
 338                 * the register.
 339                 */
 340                ACPI_ERROR((AE_INFO,
 341                            "Index value 0x%8.8X%8.8X overflows field width 0x%X",
 342                            ACPI_FORMAT_UINT64(value),
 343                            obj_desc->common_field.bit_length));
 344
 345                return (TRUE);
 346        }
 347
 348        /* The Value will fit into the field with no truncation */
 349
 350        return (FALSE);
 351}
 352
 353/*******************************************************************************
 354 *
 355 * FUNCTION:    acpi_ex_field_datum_io
 356 *
 357 * PARAMETERS:  obj_desc                - Field to be read
 358 *              field_datum_byte_offset - Byte offset of this datum within the
 359 *                                        parent field
 360 *              value                   - Where to store value (must be 64 bits)
 361 *              read_write              - Read or Write flag
 362 *
 363 * RETURN:      Status
 364 *
 365 * DESCRIPTION: Read or Write a single datum of a field. The field_type is
 366 *              demultiplexed here to handle the different types of fields
 367 *              (buffer_field, region_field, index_field, bank_field)
 368 *
 369 ******************************************************************************/
 370
 371static acpi_status
 372acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
 373                       u32 field_datum_byte_offset, u64 *value, u32 read_write)
 374{
 375        acpi_status status;
 376        u64 local_value;
 377
 378        ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
 379
 380        if (read_write == ACPI_READ) {
 381                if (!value) {
 382                        local_value = 0;
 383
 384                        /* To support reads without saving return value */
 385                        value = &local_value;
 386                }
 387
 388                /* Clear the entire return buffer first, [Very Important!] */
 389
 390                *value = 0;
 391        }
 392
 393        /*
 394         * The four types of fields are:
 395         *
 396         * buffer_field - Read/write from/to a Buffer
 397         * region_field - Read/write from/to a Operation Region.
 398         * bank_field  - Write to a Bank Register, then read/write from/to an
 399         *               operation_region
 400         * index_field - Write to an Index Register, then read/write from/to a
 401         *               Data Register
 402         */
 403        switch (obj_desc->common.type) {
 404        case ACPI_TYPE_BUFFER_FIELD:
 405                /*
 406                 * If the buffer_field arguments have not been previously evaluated,
 407                 * evaluate them now and save the results.
 408                 */
 409                if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
 410                        status = acpi_ds_get_buffer_field_arguments(obj_desc);
 411                        if (ACPI_FAILURE(status)) {
 412                                return_ACPI_STATUS(status);
 413                        }
 414                }
 415
 416                if (read_write == ACPI_READ) {
 417                        /*
 418                         * Copy the data from the source buffer.
 419                         * Length is the field width in bytes.
 420                         */
 421                        ACPI_MEMCPY(value,
 422                                    (obj_desc->buffer_field.buffer_obj)->buffer.
 423                                    pointer +
 424                                    obj_desc->buffer_field.base_byte_offset +
 425                                    field_datum_byte_offset,
 426                                    obj_desc->common_field.access_byte_width);
 427                } else {
 428                        /*
 429                         * Copy the data to the target buffer.
 430                         * Length is the field width in bytes.
 431                         */
 432                        ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
 433                                    pointer +
 434                                    obj_desc->buffer_field.base_byte_offset +
 435                                    field_datum_byte_offset, value,
 436                                    obj_desc->common_field.access_byte_width);
 437                }
 438
 439                status = AE_OK;
 440                break;
 441
 442        case ACPI_TYPE_LOCAL_BANK_FIELD:
 443                /*
 444                 * Ensure that the bank_value is not beyond the capacity of
 445                 * the register
 446                 */
 447                if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
 448                                              (u64) obj_desc->bank_field.
 449                                              value)) {
 450                        return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
 451                }
 452
 453                /*
 454                 * For bank_fields, we must write the bank_value to the bank_register
 455                 * (itself a region_field) before we can access the data.
 456                 */
 457                status =
 458                    acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
 459                                              &obj_desc->bank_field.value,
 460                                              sizeof(obj_desc->bank_field.
 461                                                     value));
 462                if (ACPI_FAILURE(status)) {
 463                        return_ACPI_STATUS(status);
 464                }
 465
 466                /*
 467                 * Now that the Bank has been selected, fall through to the
 468                 * region_field case and write the datum to the Operation Region
 469                 */
 470
 471                /*lint -fallthrough */
 472
 473        case ACPI_TYPE_LOCAL_REGION_FIELD:
 474                /*
 475                 * For simple region_fields, we just directly access the owning
 476                 * Operation Region.
 477                 */
 478                status =
 479                    acpi_ex_access_region(obj_desc, field_datum_byte_offset,
 480                                          value, read_write);
 481                break;
 482
 483        case ACPI_TYPE_LOCAL_INDEX_FIELD:
 484                /*
 485                 * Ensure that the index_value is not beyond the capacity of
 486                 * the register
 487                 */
 488                if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
 489                                              (u64) obj_desc->index_field.
 490                                              value)) {
 491                        return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
 492                }
 493
 494                /* Write the index value to the index_register (itself a region_field) */
 495
 496                field_datum_byte_offset += obj_desc->index_field.value;
 497
 498                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 499                                  "Write to Index Register: Value %8.8X\n",
 500                                  field_datum_byte_offset));
 501
 502                status =
 503                    acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
 504                                              &field_datum_byte_offset,
 505                                              sizeof(field_datum_byte_offset));
 506                if (ACPI_FAILURE(status)) {
 507                        return_ACPI_STATUS(status);
 508                }
 509
 510                if (read_write == ACPI_READ) {
 511
 512                        /* Read the datum from the data_register */
 513
 514                        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 515                                          "Read from Data Register\n"));
 516
 517                        status =
 518                            acpi_ex_extract_from_field(obj_desc->index_field.
 519                                                       data_obj, value,
 520                                                       sizeof(u64));
 521                } else {
 522                        /* Write the datum to the data_register */
 523
 524                        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 525                                          "Write to Data Register: Value %8.8X%8.8X\n",
 526                                          ACPI_FORMAT_UINT64(*value)));
 527
 528                        status =
 529                            acpi_ex_insert_into_field(obj_desc->index_field.
 530                                                      data_obj, value,
 531                                                      sizeof(u64));
 532                }
 533                break;
 534
 535        default:
 536
 537                ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u",
 538                            obj_desc->common.type));
 539                status = AE_AML_INTERNAL;
 540                break;
 541        }
 542
 543        if (ACPI_SUCCESS(status)) {
 544                if (read_write == ACPI_READ) {
 545                        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 546                                          "Value Read %8.8X%8.8X, Width %u\n",
 547                                          ACPI_FORMAT_UINT64(*value),
 548                                          obj_desc->common_field.
 549                                          access_byte_width));
 550                } else {
 551                        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 552                                          "Value Written %8.8X%8.8X, Width %u\n",
 553                                          ACPI_FORMAT_UINT64(*value),
 554                                          obj_desc->common_field.
 555                                          access_byte_width));
 556                }
 557        }
 558
 559        return_ACPI_STATUS(status);
 560}
 561
 562/*******************************************************************************
 563 *
 564 * FUNCTION:    acpi_ex_write_with_update_rule
 565 *
 566 * PARAMETERS:  obj_desc                - Field to be written
 567 *              mask                    - bitmask within field datum
 568 *              field_value             - Value to write
 569 *              field_datum_byte_offset - Offset of datum within field
 570 *
 571 * RETURN:      Status
 572 *
 573 * DESCRIPTION: Apply the field update rule to a field write
 574 *
 575 ******************************************************************************/
 576
 577acpi_status
 578acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
 579                               u64 mask,
 580                               u64 field_value, u32 field_datum_byte_offset)
 581{
 582        acpi_status status = AE_OK;
 583        u64 merged_value;
 584        u64 current_value;
 585
 586        ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
 587
 588        /* Start with the new bits  */
 589
 590        merged_value = field_value;
 591
 592        /* If the mask is all ones, we don't need to worry about the update rule */
 593
 594        if (mask != ACPI_UINT64_MAX) {
 595
 596                /* Decode the update rule */
 597
 598                switch (obj_desc->common_field.
 599                        field_flags & AML_FIELD_UPDATE_RULE_MASK) {
 600                case AML_FIELD_UPDATE_PRESERVE:
 601                        /*
 602                         * Check if update rule needs to be applied (not if mask is all
 603                         * ones)  The left shift drops the bits we want to ignore.
 604                         */
 605                        if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
 606                                       ACPI_MUL_8(obj_desc->common_field.
 607                                                  access_byte_width))) != 0) {
 608                                /*
 609                                 * Read the current contents of the byte/word/dword containing
 610                                 * the field, and merge with the new field value.
 611                                 */
 612                                status =
 613                                    acpi_ex_field_datum_io(obj_desc,
 614                                                           field_datum_byte_offset,
 615                                                           &current_value,
 616                                                           ACPI_READ);
 617                                if (ACPI_FAILURE(status)) {
 618                                        return_ACPI_STATUS(status);
 619                                }
 620
 621                                merged_value |= (current_value & ~mask);
 622                        }
 623                        break;
 624
 625                case AML_FIELD_UPDATE_WRITE_AS_ONES:
 626
 627                        /* Set positions outside the field to all ones */
 628
 629                        merged_value |= ~mask;
 630                        break;
 631
 632                case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
 633
 634                        /* Set positions outside the field to all zeros */
 635
 636                        merged_value &= mask;
 637                        break;
 638
 639                default:
 640
 641                        ACPI_ERROR((AE_INFO,
 642                                    "Unknown UpdateRule value: 0x%X",
 643                                    (obj_desc->common_field.
 644                                     field_flags &
 645                                     AML_FIELD_UPDATE_RULE_MASK)));
 646                        return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 647                }
 648        }
 649
 650        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 651                          "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
 652                          ACPI_FORMAT_UINT64(mask),
 653                          field_datum_byte_offset,
 654                          obj_desc->common_field.access_byte_width,
 655                          ACPI_FORMAT_UINT64(field_value),
 656                          ACPI_FORMAT_UINT64(merged_value)));
 657
 658        /* Write the merged value */
 659
 660        status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
 661                                        &merged_value, ACPI_WRITE);
 662
 663        return_ACPI_STATUS(status);
 664}
 665
 666/*******************************************************************************
 667 *
 668 * FUNCTION:    acpi_ex_extract_from_field
 669 *
 670 * PARAMETERS:  obj_desc            - Field to be read
 671 *              buffer              - Where to store the field data
 672 *              buffer_length       - Length of Buffer
 673 *
 674 * RETURN:      Status
 675 *
 676 * DESCRIPTION: Retrieve the current value of the given field
 677 *
 678 ******************************************************************************/
 679
 680acpi_status
 681acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
 682                           void *buffer, u32 buffer_length)
 683{
 684        acpi_status status;
 685        u64 raw_datum;
 686        u64 merged_datum;
 687        u32 field_offset = 0;
 688        u32 buffer_offset = 0;
 689        u32 buffer_tail_bits;
 690        u32 datum_count;
 691        u32 field_datum_count;
 692        u32 access_bit_width;
 693        u32 i;
 694
 695        ACPI_FUNCTION_TRACE(ex_extract_from_field);
 696
 697        /* Validate target buffer and clear it */
 698
 699        if (buffer_length <
 700            ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
 701                ACPI_ERROR((AE_INFO,
 702                            "Field size %u (bits) is too large for buffer (%u)",
 703                            obj_desc->common_field.bit_length, buffer_length));
 704
 705                return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
 706        }
 707
 708        ACPI_MEMSET(buffer, 0, buffer_length);
 709        access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
 710
 711        /* Handle the simple case here */
 712
 713        if ((obj_desc->common_field.start_field_bit_offset == 0) &&
 714            (obj_desc->common_field.bit_length == access_bit_width)) {
 715                if (buffer_length >= sizeof(u64)) {
 716                        status =
 717                            acpi_ex_field_datum_io(obj_desc, 0, buffer,
 718                                                   ACPI_READ);
 719                } else {
 720                        /* Use raw_datum (u64) to handle buffers < 64 bits */
 721
 722                        status =
 723                            acpi_ex_field_datum_io(obj_desc, 0, &raw_datum,
 724                                                   ACPI_READ);
 725                        ACPI_MEMCPY(buffer, &raw_datum, buffer_length);
 726                }
 727
 728                return_ACPI_STATUS(status);
 729        }
 730
 731/* TBD: Move to common setup code */
 732
 733        /* Field algorithm is limited to sizeof(u64), truncate if needed */
 734
 735        if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
 736                obj_desc->common_field.access_byte_width = sizeof(u64);
 737                access_bit_width = sizeof(u64) * 8;
 738        }
 739
 740        /* Compute the number of datums (access width data items) */
 741
 742        datum_count =
 743            ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
 744                             access_bit_width);
 745
 746        field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 747                                             obj_desc->common_field.
 748                                             start_field_bit_offset,
 749                                             access_bit_width);
 750
 751        /* Priming read from the field */
 752
 753        status =
 754            acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
 755                                   ACPI_READ);
 756        if (ACPI_FAILURE(status)) {
 757                return_ACPI_STATUS(status);
 758        }
 759        merged_datum =
 760            raw_datum >> obj_desc->common_field.start_field_bit_offset;
 761
 762        /* Read the rest of the field */
 763
 764        for (i = 1; i < field_datum_count; i++) {
 765
 766                /* Get next input datum from the field */
 767
 768                field_offset += obj_desc->common_field.access_byte_width;
 769                status = acpi_ex_field_datum_io(obj_desc, field_offset,
 770                                                &raw_datum, ACPI_READ);
 771                if (ACPI_FAILURE(status)) {
 772                        return_ACPI_STATUS(status);
 773                }
 774
 775                /*
 776                 * Merge with previous datum if necessary.
 777                 *
 778                 * Note: Before the shift, check if the shift value will be larger than
 779                 * the integer size. If so, there is no need to perform the operation.
 780                 * This avoids the differences in behavior between different compilers
 781                 * concerning shift values larger than the target data width.
 782                 */
 783                if (access_bit_width -
 784                    obj_desc->common_field.start_field_bit_offset <
 785                    ACPI_INTEGER_BIT_SIZE) {
 786                        merged_datum |=
 787                            raw_datum << (access_bit_width -
 788                                          obj_desc->common_field.
 789                                          start_field_bit_offset);
 790                }
 791
 792                if (i == datum_count) {
 793                        break;
 794                }
 795
 796                /* Write merged datum to target buffer */
 797
 798                ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
 799                            ACPI_MIN(obj_desc->common_field.access_byte_width,
 800                                     buffer_length - buffer_offset));
 801
 802                buffer_offset += obj_desc->common_field.access_byte_width;
 803                merged_datum =
 804                    raw_datum >> obj_desc->common_field.start_field_bit_offset;
 805        }
 806
 807        /* Mask off any extra bits in the last datum */
 808
 809        buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
 810        if (buffer_tail_bits) {
 811                merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 812        }
 813
 814        /* Write the last datum to the buffer */
 815
 816        ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
 817                    ACPI_MIN(obj_desc->common_field.access_byte_width,
 818                             buffer_length - buffer_offset));
 819
 820        return_ACPI_STATUS(AE_OK);
 821}
 822
 823/*******************************************************************************
 824 *
 825 * FUNCTION:    acpi_ex_insert_into_field
 826 *
 827 * PARAMETERS:  obj_desc            - Field to be written
 828 *              buffer              - Data to be written
 829 *              buffer_length       - Length of Buffer
 830 *
 831 * RETURN:      Status
 832 *
 833 * DESCRIPTION: Store the Buffer contents into the given field
 834 *
 835 ******************************************************************************/
 836
 837acpi_status
 838acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 839                          void *buffer, u32 buffer_length)
 840{
 841        void *new_buffer;
 842        acpi_status status;
 843        u64 mask;
 844        u64 width_mask;
 845        u64 merged_datum;
 846        u64 raw_datum = 0;
 847        u32 field_offset = 0;
 848        u32 buffer_offset = 0;
 849        u32 buffer_tail_bits;
 850        u32 datum_count;
 851        u32 field_datum_count;
 852        u32 access_bit_width;
 853        u32 required_length;
 854        u32 i;
 855
 856        ACPI_FUNCTION_TRACE(ex_insert_into_field);
 857
 858        /* Validate input buffer */
 859
 860        new_buffer = NULL;
 861        required_length =
 862            ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
 863        /*
 864         * We must have a buffer that is at least as long as the field
 865         * we are writing to. This is because individual fields are
 866         * indivisible and partial writes are not supported -- as per
 867         * the ACPI specification.
 868         */
 869        if (buffer_length < required_length) {
 870
 871                /* We need to create a new buffer */
 872
 873                new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
 874                if (!new_buffer) {
 875                        return_ACPI_STATUS(AE_NO_MEMORY);
 876                }
 877
 878                /*
 879                 * Copy the original data to the new buffer, starting
 880                 * at Byte zero. All unused (upper) bytes of the
 881                 * buffer will be 0.
 882                 */
 883                ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
 884                buffer = new_buffer;
 885                buffer_length = required_length;
 886        }
 887
 888/* TBD: Move to common setup code */
 889
 890        /* Algo is limited to sizeof(u64), so cut the access_byte_width */
 891        if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
 892                obj_desc->common_field.access_byte_width = sizeof(u64);
 893        }
 894
 895        access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
 896
 897        /*
 898         * Create the bitmasks used for bit insertion.
 899         * Note: This if/else is used to bypass compiler differences with the
 900         * shift operator
 901         */
 902        if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
 903                width_mask = ACPI_UINT64_MAX;
 904        } else {
 905                width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
 906        }
 907
 908        mask = width_mask &
 909            ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
 910
 911        /* Compute the number of datums (access width data items) */
 912
 913        datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
 914                                       access_bit_width);
 915
 916        field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
 917                                             obj_desc->common_field.
 918                                             start_field_bit_offset,
 919                                             access_bit_width);
 920
 921        /* Get initial Datum from the input buffer */
 922
 923        ACPI_MEMCPY(&raw_datum, buffer,
 924                    ACPI_MIN(obj_desc->common_field.access_byte_width,
 925                             buffer_length - buffer_offset));
 926
 927        merged_datum =
 928            raw_datum << obj_desc->common_field.start_field_bit_offset;
 929
 930        /* Write the entire field */
 931
 932        for (i = 1; i < field_datum_count; i++) {
 933
 934                /* Write merged datum to the target field */
 935
 936                merged_datum &= mask;
 937                status = acpi_ex_write_with_update_rule(obj_desc, mask,
 938                                                        merged_datum,
 939                                                        field_offset);
 940                if (ACPI_FAILURE(status)) {
 941                        goto exit;
 942                }
 943
 944                field_offset += obj_desc->common_field.access_byte_width;
 945
 946                /*
 947                 * Start new output datum by merging with previous input datum
 948                 * if necessary.
 949                 *
 950                 * Note: Before the shift, check if the shift value will be larger than
 951                 * the integer size. If so, there is no need to perform the operation.
 952                 * This avoids the differences in behavior between different compilers
 953                 * concerning shift values larger than the target data width.
 954                 */
 955                if ((access_bit_width -
 956                     obj_desc->common_field.start_field_bit_offset) <
 957                    ACPI_INTEGER_BIT_SIZE) {
 958                        merged_datum =
 959                            raw_datum >> (access_bit_width -
 960                                          obj_desc->common_field.
 961                                          start_field_bit_offset);
 962                } else {
 963                        merged_datum = 0;
 964                }
 965
 966                mask = width_mask;
 967
 968                if (i == datum_count) {
 969                        break;
 970                }
 971
 972                /* Get the next input datum from the buffer */
 973
 974                buffer_offset += obj_desc->common_field.access_byte_width;
 975                ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
 976                            ACPI_MIN(obj_desc->common_field.access_byte_width,
 977                                     buffer_length - buffer_offset));
 978
 979                merged_datum |=
 980                    raw_datum << obj_desc->common_field.start_field_bit_offset;
 981        }
 982
 983        /* Mask off any extra bits in the last datum */
 984
 985        buffer_tail_bits = (obj_desc->common_field.bit_length +
 986                            obj_desc->common_field.start_field_bit_offset) %
 987            access_bit_width;
 988        if (buffer_tail_bits) {
 989                mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
 990        }
 991
 992        /* Write the last datum to the field */
 993
 994        merged_datum &= mask;
 995        status = acpi_ex_write_with_update_rule(obj_desc,
 996                                                mask, merged_datum,
 997                                                field_offset);
 998
 999exit:
1000        /* Free temporary buffer if we used one */
1001
1002        if (new_buffer) {
1003                ACPI_FREE(new_buffer);
1004        }
1005        return_ACPI_STATUS(status);
1006}
1007