Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.19-rc6 929 lines 28 kB view raw
1/****************************************************************************** 2 * 3 * Module Name: exfldio - Aml Field I/O 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2006, R. Byron Moore 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 <acpi/acinterp.h> 46#include <acpi/amlcode.h> 47#include <acpi/acevents.h> 48#include <acpi/acdispat.h> 49 50#define _COMPONENT ACPI_EXECUTER 51ACPI_MODULE_NAME("exfldio") 52 53/* Local prototypes */ 54static acpi_status 55acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, 56 u32 field_datum_byte_offset, 57 acpi_integer * value, u32 read_write); 58 59static u8 60acpi_ex_register_overflow(union acpi_operand_object *obj_desc, 61 acpi_integer value); 62 63static acpi_status 64acpi_ex_setup_region(union acpi_operand_object *obj_desc, 65 u32 field_datum_byte_offset); 66 67/******************************************************************************* 68 * 69 * FUNCTION: acpi_ex_setup_region 70 * 71 * PARAMETERS: obj_desc - Field to be read or written 72 * field_datum_byte_offset - Byte offset of this datum within the 73 * parent field 74 * 75 * RETURN: Status 76 * 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. 80 * 81 ******************************************************************************/ 82 83static acpi_status 84acpi_ex_setup_region(union acpi_operand_object *obj_desc, 85 u32 field_datum_byte_offset) 86{ 87 acpi_status status = AE_OK; 88 union acpi_operand_object *rgn_desc; 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 (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))); 100 101 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 102 } 103 104 /* 105 * If the Region Address and Length have not been previously evaluated, 106 * evaluate them now and save the results. 107 */ 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); 112 } 113 } 114 115 /* Exit if Address/Length have been disallowed by the host OS */ 116 117 if (rgn_desc->common.flags & AOPOBJ_INVALID) { 118 return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); 119 } 120 121 /* 122 * Exit now for SMBus address space, it has a non-linear address space 123 * and the request cannot be directly validated 124 */ 125 if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { 126 127 /* SMBus has a non-linear address space */ 128 129 return_ACPI_STATUS(AE_OK); 130 } 131#ifdef ACPI_UNDER_DEVELOPMENT 132 /* 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) 135 */ 136 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 137 if (ACPI_FAILURE(status)) { 138 return_ACPI_STATUS(status); 139 } 140 } 141#endif 142 143 /* 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) 147 */ 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) { 153 /* 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. 157 */ 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); 165 } 166 } 167 168 if (rgn_desc->region.length < 169 obj_desc->common_field.access_byte_width) { 170 /* 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. 174 */ 175 ACPI_ERROR((AE_INFO, 176 "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)", 177 acpi_ut_get_node_name(obj_desc-> 178 common_field.node), 179 obj_desc->common_field.access_byte_width, 180 acpi_ut_get_node_name(rgn_desc->region. 181 node), 182 rgn_desc->region.length)); 183 } 184 185 /* 186 * Offset rounded up to next multiple of field width 187 * exceeds region length, indicate an error 188 */ 189 ACPI_ERROR((AE_INFO, 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)); 197 198 return_ACPI_STATUS(AE_AML_REGION_LIMIT); 199 } 200 201 return_ACPI_STATUS(AE_OK); 202} 203 204/******************************************************************************* 205 * 206 * FUNCTION: acpi_ex_access_region 207 * 208 * PARAMETERS: obj_desc - Field to be read 209 * field_datum_byte_offset - Byte offset of this datum within the 210 * parent field 211 * Value - Where to store value (must at least 212 * the size of acpi_integer) 213 * Function - Read or Write flag plus other region- 214 * dependent flags 215 * 216 * RETURN: Status 217 * 218 * DESCRIPTION: Read or Write a single field datum to an Operation Region. 219 * 220 ******************************************************************************/ 221 222acpi_status 223acpi_ex_access_region(union acpi_operand_object *obj_desc, 224 u32 field_datum_byte_offset, 225 acpi_integer * value, u32 function) 226{ 227 acpi_status status; 228 union acpi_operand_object *rgn_desc; 229 acpi_physical_address address; 230 231 ACPI_FUNCTION_TRACE(ex_access_region); 232 233 /* 234 * Ensure that the region operands are fully evaluated and verify 235 * the validity of the request 236 */ 237 status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset); 238 if (ACPI_FAILURE(status)) { 239 return_ACPI_STATUS(status); 240 } 241 242 /* 243 * The physical address of this field datum is: 244 * 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 248 */ 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; 252 253 if ((function & ACPI_IO_MASK) == ACPI_READ) { 254 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]")); 255 } else { 256 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]")); 257 } 258 259 ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, 260 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", 261 acpi_ut_get_region_name(rgn_desc->region. 262 space_id), 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, 267 ACPI_FORMAT_UINT64(address))); 268 269 /* Invoke the appropriate address_space/op_region handler */ 270 271 status = acpi_ev_address_space_dispatch(rgn_desc, function, 272 address, 273 ACPI_MUL_8(obj_desc-> 274 common_field. 275 access_byte_width), 276 value); 277 278 if (ACPI_FAILURE(status)) { 279 if (status == AE_NOT_IMPLEMENTED) { 280 ACPI_ERROR((AE_INFO, 281 "Region %s(%X) not implemented", 282 acpi_ut_get_region_name(rgn_desc->region. 283 space_id), 284 rgn_desc->region.space_id)); 285 } else if (status == AE_NOT_EXIST) { 286 ACPI_ERROR((AE_INFO, 287 "Region %s(%X) has no handler", 288 acpi_ut_get_region_name(rgn_desc->region. 289 space_id), 290 rgn_desc->region.space_id)); 291 } 292 } 293 294 return_ACPI_STATUS(status); 295} 296 297/******************************************************************************* 298 * 299 * FUNCTION: acpi_ex_register_overflow 300 * 301 * PARAMETERS: obj_desc - Register(Field) to be written 302 * Value - Value to be stored 303 * 304 * RETURN: TRUE if value overflows the field, FALSE otherwise 305 * 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. 311 * 312 ******************************************************************************/ 313 314static u8 315acpi_ex_register_overflow(union acpi_operand_object *obj_desc, 316 acpi_integer value) 317{ 318 319 if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { 320 /* 321 * The field is large enough to hold the maximum integer, so we can 322 * never overflow it. 323 */ 324 return (FALSE); 325 } 326 327 if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) { 328 /* 329 * The Value is larger than the maximum value that can fit into 330 * the register. 331 */ 332 return (TRUE); 333 } 334 335 /* The Value will fit into the field with no truncation */ 336 337 return (FALSE); 338} 339 340/******************************************************************************* 341 * 342 * FUNCTION: acpi_ex_field_datum_io 343 * 344 * PARAMETERS: obj_desc - Field to be read 345 * field_datum_byte_offset - Byte offset of this datum within the 346 * parent field 347 * Value - Where to store value (must be 64 bits) 348 * read_write - Read or Write flag 349 * 350 * RETURN: Status 351 * 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) 355 * 356 ******************************************************************************/ 357 358static acpi_status 359acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, 360 u32 field_datum_byte_offset, 361 acpi_integer * value, u32 read_write) 362{ 363 acpi_status status; 364 acpi_integer local_value; 365 366 ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); 367 368 if (read_write == ACPI_READ) { 369 if (!value) { 370 local_value = 0; 371 372 /* To support reads without saving return value */ 373 value = &local_value; 374 } 375 376 /* Clear the entire return buffer first, [Very Important!] */ 377 378 *value = 0; 379 } 380 381 /* 382 * The four types of fields are: 383 * 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 387 * operation_region 388 * index_field - Write to an Index Register, then read/write from/to a 389 * Data Register 390 */ 391 switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { 392 case ACPI_TYPE_BUFFER_FIELD: 393 /* 394 * If the buffer_field arguments have not been previously evaluated, 395 * evaluate them now and save the results. 396 */ 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); 401 } 402 } 403 404 if (read_write == ACPI_READ) { 405 /* 406 * Copy the data from the source buffer. 407 * Length is the field width in bytes. 408 */ 409 ACPI_MEMCPY(value, 410 (obj_desc->buffer_field.buffer_obj)->buffer. 411 pointer + 412 obj_desc->buffer_field.base_byte_offset + 413 field_datum_byte_offset, 414 obj_desc->common_field.access_byte_width); 415 } else { 416 /* 417 * Copy the data to the target buffer. 418 * Length is the field width in bytes. 419 */ 420 ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer. 421 pointer + 422 obj_desc->buffer_field.base_byte_offset + 423 field_datum_byte_offset, value, 424 obj_desc->common_field.access_byte_width); 425 } 426 427 status = AE_OK; 428 break; 429 430 case ACPI_TYPE_LOCAL_BANK_FIELD: 431 432 /* 433 * Ensure that the bank_value is not beyond the capacity of 434 * the register 435 */ 436 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj, 437 (acpi_integer) obj_desc-> 438 bank_field.value)) { 439 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); 440 } 441 442 /* 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. 445 */ 446 status = 447 acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj, 448 &obj_desc->bank_field.value, 449 sizeof(obj_desc->bank_field. 450 value)); 451 if (ACPI_FAILURE(status)) { 452 return_ACPI_STATUS(status); 453 } 454 455 /* 456 * Now that the Bank has been selected, fall through to the 457 * region_field case and write the datum to the Operation Region 458 */ 459 460 /*lint -fallthrough */ 461 462 case ACPI_TYPE_LOCAL_REGION_FIELD: 463 /* 464 * For simple region_fields, we just directly access the owning 465 * Operation Region. 466 */ 467 status = 468 acpi_ex_access_region(obj_desc, field_datum_byte_offset, 469 value, read_write); 470 break; 471 472 case ACPI_TYPE_LOCAL_INDEX_FIELD: 473 474 /* 475 * Ensure that the index_value is not beyond the capacity of 476 * the register 477 */ 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); 482 } 483 484 /* Write the index value to the index_register (itself a region_field) */ 485 486 field_datum_byte_offset += obj_desc->index_field.value; 487 488 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 489 "Write to Index Register: Value %8.8X\n", 490 field_datum_byte_offset)); 491 492 status = 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); 498 } 499 500 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 501 "I/O to Data Register: ValuePtr %p\n", 502 value)); 503 504 if (read_write == ACPI_READ) { 505 506 /* Read the datum from the data_register */ 507 508 status = 509 acpi_ex_extract_from_field(obj_desc->index_field. 510 data_obj, value, 511 sizeof(acpi_integer)); 512 } else { 513 /* Write the datum to the data_register */ 514 515 status = 516 acpi_ex_insert_into_field(obj_desc->index_field. 517 data_obj, value, 518 sizeof(acpi_integer)); 519 } 520 break; 521 522 default: 523 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; 527 break; 528 } 529 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. 536 access_byte_width)); 537 } else { 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. 542 access_byte_width)); 543 } 544 } 545 546 return_ACPI_STATUS(status); 547} 548 549/******************************************************************************* 550 * 551 * FUNCTION: acpi_ex_write_with_update_rule 552 * 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 557 * 558 * RETURN: Status 559 * 560 * DESCRIPTION: Apply the field update rule to a field write 561 * 562 ******************************************************************************/ 563 564acpi_status 565acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, 566 acpi_integer mask, 567 acpi_integer field_value, 568 u32 field_datum_byte_offset) 569{ 570 acpi_status status = AE_OK; 571 acpi_integer merged_value; 572 acpi_integer current_value; 573 574 ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); 575 576 /* Start with the new bits */ 577 578 merged_value = field_value; 579 580 /* If the mask is all ones, we don't need to worry about the update rule */ 581 582 if (mask != ACPI_INTEGER_MAX) { 583 584 /* Decode the update rule */ 585 586 switch (obj_desc->common_field. 587 field_flags & AML_FIELD_UPDATE_RULE_MASK) { 588 case AML_FIELD_UPDATE_PRESERVE: 589 /* 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. 592 */ 593 if ((~mask << (ACPI_MUL_8(sizeof(mask)) - 594 ACPI_MUL_8(obj_desc->common_field. 595 access_byte_width))) != 0) { 596 /* 597 * Read the current contents of the byte/word/dword containing 598 * the field, and merge with the new field value. 599 */ 600 status = 601 acpi_ex_field_datum_io(obj_desc, 602 field_datum_byte_offset, 603 &current_value, 604 ACPI_READ); 605 if (ACPI_FAILURE(status)) { 606 return_ACPI_STATUS(status); 607 } 608 609 merged_value |= (current_value & ~mask); 610 } 611 break; 612 613 case AML_FIELD_UPDATE_WRITE_AS_ONES: 614 615 /* Set positions outside the field to all ones */ 616 617 merged_value |= ~mask; 618 break; 619 620 case AML_FIELD_UPDATE_WRITE_AS_ZEROS: 621 622 /* Set positions outside the field to all zeros */ 623 624 merged_value &= mask; 625 break; 626 627 default: 628 629 ACPI_ERROR((AE_INFO, 630 "Unknown UpdateRule value: %X", 631 (obj_desc->common_field. 632 field_flags & 633 AML_FIELD_UPDATE_RULE_MASK))); 634 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 635 } 636 } 637 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))); 645 646 /* Write the merged value */ 647 648 status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset, 649 &merged_value, ACPI_WRITE); 650 651 return_ACPI_STATUS(status); 652} 653 654/******************************************************************************* 655 * 656 * FUNCTION: acpi_ex_extract_from_field 657 * 658 * PARAMETERS: obj_desc - Field to be read 659 * Buffer - Where to store the field data 660 * buffer_length - Length of Buffer 661 * 662 * RETURN: Status 663 * 664 * DESCRIPTION: Retrieve the current value of the given field 665 * 666 ******************************************************************************/ 667 668acpi_status 669acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, 670 void *buffer, u32 buffer_length) 671{ 672 acpi_status status; 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; 678 u32 datum_count; 679 u32 field_datum_count; 680 u32 i; 681 682 ACPI_FUNCTION_TRACE(ex_extract_from_field); 683 684 /* Validate target buffer and clear it */ 685 686 if (buffer_length < 687 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { 688 ACPI_ERROR((AE_INFO, 689 "Field size %X (bits) is too large for buffer (%X)", 690 obj_desc->common_field.bit_length, buffer_length)); 691 692 return_ACPI_STATUS(AE_BUFFER_OVERFLOW); 693 } 694 ACPI_MEMSET(buffer, 0, buffer_length); 695 696 /* Compute the number of datums (access width data items) */ 697 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. 704 access_bit_width); 705 706 /* Priming read from the field */ 707 708 status = 709 acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum, 710 ACPI_READ); 711 if (ACPI_FAILURE(status)) { 712 return_ACPI_STATUS(status); 713 } 714 merged_datum = 715 raw_datum >> obj_desc->common_field.start_field_bit_offset; 716 717 /* Read the rest of the field */ 718 719 for (i = 1; i < field_datum_count; i++) { 720 721 /* Get next input datum from the field */ 722 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); 728 } 729 730 /* 731 * Merge with previous datum if necessary. 732 * 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. 737 */ 738 if ((obj_desc->common_field.access_bit_width - 739 obj_desc->common_field.start_field_bit_offset) < 740 ACPI_INTEGER_BIT_SIZE) { 741 merged_datum |= 742 raw_datum << (obj_desc->common_field. 743 access_bit_width - 744 obj_desc->common_field. 745 start_field_bit_offset); 746 } 747 748 if (i == datum_count) { 749 break; 750 } 751 752 /* Write merged datum to target buffer */ 753 754 ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, 755 ACPI_MIN(obj_desc->common_field.access_byte_width, 756 buffer_length - buffer_offset)); 757 758 buffer_offset += obj_desc->common_field.access_byte_width; 759 merged_datum = 760 raw_datum >> obj_desc->common_field.start_field_bit_offset; 761 } 762 763 /* Mask off any extra bits in the last datum */ 764 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); 769 } 770 771 /* Write the last datum to the buffer */ 772 773 ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, 774 ACPI_MIN(obj_desc->common_field.access_byte_width, 775 buffer_length - buffer_offset)); 776 777 return_ACPI_STATUS(AE_OK); 778} 779 780/******************************************************************************* 781 * 782 * FUNCTION: acpi_ex_insert_into_field 783 * 784 * PARAMETERS: obj_desc - Field to be written 785 * Buffer - Data to be written 786 * buffer_length - Length of Buffer 787 * 788 * RETURN: Status 789 * 790 * DESCRIPTION: Store the Buffer contents into the given field 791 * 792 ******************************************************************************/ 793 794acpi_status 795acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, 796 void *buffer, u32 buffer_length) 797{ 798 acpi_status status; 799 acpi_integer mask; 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; 806 u32 datum_count; 807 u32 field_datum_count; 808 u32 i; 809 810 ACPI_FUNCTION_TRACE(ex_insert_into_field); 811 812 /* Validate input buffer */ 813 814 if (buffer_length < 815 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { 816 ACPI_ERROR((AE_INFO, 817 "Field size %X (bits) is too large for buffer (%X)", 818 obj_desc->common_field.bit_length, buffer_length)); 819 820 return_ACPI_STATUS(AE_BUFFER_OVERFLOW); 821 } 822 823 /* 824 * Create the bitmasks used for bit insertion. 825 * Note: This if/else is used to bypass compiler differences with the 826 * shift operator 827 */ 828 if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) { 829 width_mask = ACPI_INTEGER_MAX; 830 } else { 831 width_mask = 832 ACPI_MASK_BITS_ABOVE(obj_desc->common_field. 833 access_bit_width); 834 } 835 836 mask = width_mask & 837 ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); 838 839 /* Compute the number of datums (access width data items) */ 840 841 datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, 842 obj_desc->common_field.access_bit_width); 843 844 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + 845 obj_desc->common_field. 846 start_field_bit_offset, 847 obj_desc->common_field. 848 access_bit_width); 849 850 /* Get initial Datum from the input buffer */ 851 852 ACPI_MEMCPY(&raw_datum, buffer, 853 ACPI_MIN(obj_desc->common_field.access_byte_width, 854 buffer_length - buffer_offset)); 855 856 merged_datum = 857 raw_datum << obj_desc->common_field.start_field_bit_offset; 858 859 /* Write the entire field */ 860 861 for (i = 1; i < field_datum_count; i++) { 862 863 /* Write merged datum to the target field */ 864 865 merged_datum &= mask; 866 status = acpi_ex_write_with_update_rule(obj_desc, mask, 867 merged_datum, 868 field_offset); 869 if (ACPI_FAILURE(status)) { 870 return_ACPI_STATUS(status); 871 } 872 873 field_offset += obj_desc->common_field.access_byte_width; 874 875 /* 876 * Start new output datum by merging with previous input datum 877 * if necessary. 878 * 879 * Note: Before the shift, check if the shift value will be larger than 880 * the integer size. If so, there is no need to perform the operation. 881 * This avoids the differences in behavior between different compilers 882 * concerning shift values larger than the target data width. 883 */ 884 if ((obj_desc->common_field.access_bit_width - 885 obj_desc->common_field.start_field_bit_offset) < 886 ACPI_INTEGER_BIT_SIZE) { 887 merged_datum = 888 raw_datum >> (obj_desc->common_field. 889 access_bit_width - 890 obj_desc->common_field. 891 start_field_bit_offset); 892 } else { 893 merged_datum = 0; 894 } 895 896 mask = width_mask; 897 898 if (i == datum_count) { 899 break; 900 } 901 902 /* Get the next input datum from the buffer */ 903 904 buffer_offset += obj_desc->common_field.access_byte_width; 905 ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, 906 ACPI_MIN(obj_desc->common_field.access_byte_width, 907 buffer_length - buffer_offset)); 908 merged_datum |= 909 raw_datum << obj_desc->common_field.start_field_bit_offset; 910 } 911 912 /* Mask off any extra bits in the last datum */ 913 914 buffer_tail_bits = (obj_desc->common_field.bit_length + 915 obj_desc->common_field.start_field_bit_offset) % 916 obj_desc->common_field.access_bit_width; 917 if (buffer_tail_bits) { 918 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); 919 } 920 921 /* Write the last datum to the field */ 922 923 merged_datum &= mask; 924 status = acpi_ex_write_with_update_rule(obj_desc, 925 mask, merged_datum, 926 field_offset); 927 928 return_ACPI_STATUS(status); 929}