exfldio.c revision 69746
1/****************************************************************************** 2 * 3 * Module Name: amfldio - Aml Field I/O 4 * $Revision: 32 $ 5 * 6 *****************************************************************************/ 7 8/****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999, Intel Corp. All rights 13 * reserved. 14 * 15 * 2. License 16 * 17 * 2.1. This is your license from Intel Corp. under its intellectual property 18 * rights. You may have additional license terms from the party that provided 19 * you this software, covering your right to use that party's intellectual 20 * property rights. 21 * 22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23 * copy of the source code appearing in this file ("Covered Code") an 24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25 * base code distributed originally by Intel ("Original Intel Code") to copy, 26 * make derivatives, distribute, use and display any portion of the Covered 27 * Code in any form, with the right to sublicense such rights; and 28 * 29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30 * license (with the right to sublicense), under only those claims of Intel 31 * patents that are infringed by the Original Intel Code, to make, use, sell, 32 * offer to sell, and import the Covered Code and derivative works thereof 33 * solely to the minimum extent necessary to exercise the above copyright 34 * license, and in no event shall the patent license extend to any additions 35 * to or modifications of the Original Intel Code. No other license or right 36 * is granted directly or by implication, estoppel or otherwise; 37 * 38 * The above copyright and patent license is granted only if the following 39 * conditions are met: 40 * 41 * 3. Conditions 42 * 43 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44 * Redistribution of source code of any substantial portion of the Covered 45 * Code or modification with rights to further distribute source must include 46 * the above Copyright Notice, the above License, this list of Conditions, 47 * and the following Disclaimer and Export Compliance provision. In addition, 48 * Licensee must cause all Covered Code to which Licensee contributes to 49 * contain a file documenting the changes Licensee made to create that Covered 50 * Code and the date of any change. Licensee must include in that file the 51 * documentation of any changes made by any predecessor Licensee. Licensee 52 * must include a prominent statement that the modification is derived, 53 * directly or indirectly, from Original Intel Code. 54 * 55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56 * Redistribution of source code of any substantial portion of the Covered 57 * Code or modification without rights to further distribute source must 58 * include the following Disclaimer and Export Compliance provision in the 59 * documentation and/or other materials provided with distribution. In 60 * addition, Licensee may not authorize further sublicense of source of any 61 * portion of the Covered Code, and must include terms to the effect that the 62 * license from Licensee to its licensee is limited to the intellectual 63 * property embodied in the software Licensee provides to its licensee, and 64 * not to intellectual property embodied in modifications its licensee may 65 * make. 66 * 67 * 3.3. Redistribution of Executable. Redistribution in executable form of any 68 * substantial portion of the Covered Code or modification must reproduce the 69 * above Copyright Notice, and the following Disclaimer and Export Compliance 70 * provision in the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3.4. Intel retains all right, title, and interest in and to the Original 74 * Intel Code. 75 * 76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77 * Intel shall be used in advertising or otherwise to promote the sale, use or 78 * other dealings in products derived from or relating to the Covered Code 79 * without prior written authorization from Intel. 80 * 81 * 4. Disclaimer and Export Compliance 82 * 83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89 * PARTICULAR PURPOSE. 90 * 91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98 * LIMITED REMEDY. 99 * 100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 101 * software or system incorporating such software without first obtaining any 102 * required license or other approval from the U. S. Department of Commerce or 103 * any other agency or department of the United States Government. In the 104 * event Licensee exports any such software from the United States or 105 * re-exports any such software from a foreign destination, Licensee shall 106 * ensure that the distribution and export/re-export of the software is in 107 * compliance with all laws, regulations, orders, or other restrictions of the 108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109 * any of its subsidiaries will export/re-export any technical data, process, 110 * software, or service, directly or indirectly, to any country for which the 111 * United States government or any agency thereof requires an export license, 112 * other governmental approval, or letter of assurance, without first obtaining 113 * such license, approval or letter. 114 * 115 *****************************************************************************/ 116 117 118#define __AMFLDIO_C__ 119 120#include "acpi.h" 121#include "acinterp.h" 122#include "amlcode.h" 123#include "acnamesp.h" 124#include "achware.h" 125#include "acevents.h" 126 127 128#define _COMPONENT INTERPRETER 129 MODULE_NAME ("amfldio") 130 131 132/******************************************************************************* 133 * 134 * FUNCTION: AcpiAmlReadFieldData 135 * 136 * PARAMETERS: *ObjDesc - Field to be read 137 * *Value - Where to store value 138 * FieldBitWidth - Field Width in bits (8, 16, or 32) 139 * 140 * RETURN: Status 141 * 142 * DESCRIPTION: Retrieve the value of the given field 143 * 144 ******************************************************************************/ 145 146ACPI_STATUS 147AcpiAmlReadFieldData ( 148 ACPI_OPERAND_OBJECT *ObjDesc, 149 UINT32 FieldByteOffset, 150 UINT32 FieldBitWidth, 151 UINT32 *Value) 152{ 153 ACPI_STATUS Status; 154 ACPI_OPERAND_OBJECT *RgnDesc = NULL; 155 ACPI_PHYSICAL_ADDRESS Address; 156 UINT32 LocalValue = 0; 157 UINT32 FieldByteWidth; 158 159 160 FUNCTION_TRACE ("AmlReadFieldData"); 161 162 163 /* ObjDesc is validated by callers */ 164 165 if (ObjDesc) 166 { 167 RgnDesc = ObjDesc->Field.Container; 168 } 169 170 171 FieldByteWidth = DIV_8 (FieldBitWidth); 172 Status = AcpiAmlSetupField (ObjDesc, RgnDesc, FieldBitWidth); 173 if (ACPI_FAILURE (Status)) 174 { 175 return_ACPI_STATUS (Status); 176 } 177 178 /* SetupField validated RgnDesc and FieldBitWidth */ 179 180 if (!Value) 181 { 182 Value = &LocalValue; /* support reads without saving value */ 183 } 184 185 186 /* 187 * Set offset to next multiple of field width, 188 * add region base address and offset within the field 189 */ 190 Address = RgnDesc->Region.Address + 191 (ObjDesc->Field.Offset * FieldByteWidth) + 192 FieldByteOffset; 193 194 DEBUG_PRINT (TRACE_OPREGION, 195 ("AmlReadFieldData: Region %s(%X) at %08lx width %X\n", 196 AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 197 RgnDesc->Region.SpaceId, Address, 198 FieldBitWidth)); 199 200 201 /* Invoke the appropriate AddressSpace/OpRegion handler */ 202 203 Status = AcpiEvAddressSpaceDispatch (RgnDesc, ADDRESS_SPACE_READ, 204 Address, FieldBitWidth, Value); 205 206 if (Status == AE_NOT_IMPLEMENTED) 207 { 208 DEBUG_PRINT (ACPI_ERROR, 209 ("AmlReadFieldData: **** Region %s(%X) not implemented\n", 210 AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 211 RgnDesc->Region.SpaceId)); 212 } 213 214 else if (Status == AE_NOT_EXIST) 215 { 216 DEBUG_PRINT (ACPI_ERROR, 217 ("AmlReadFieldData: **** Region %s(%X) has no handler\n", 218 AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 219 RgnDesc->Region.SpaceId)); 220 } 221 222 DEBUG_PRINT (TRACE_OPREGION, 223 ("AmlReadField: Returned value=%08lx \n", *Value)); 224 225 return_ACPI_STATUS (Status); 226} 227 228 229/******************************************************************************* 230 * 231 * FUNCTION: AcpiAmlReadField 232 * 233 * PARAMETERS: *ObjDesc - Field to be read 234 * *Value - Where to store value 235 * FieldBitWidth - Field Width in bits (8, 16, or 32) 236 * 237 * RETURN: Status 238 * 239 * DESCRIPTION: Retrieve the value of the given field 240 * 241 ******************************************************************************/ 242 243ACPI_STATUS 244AcpiAmlReadField ( 245 ACPI_OPERAND_OBJECT *ObjDesc, 246 void *Buffer, 247 UINT32 BufferLength, 248 UINT32 ByteLength, 249 UINT32 DatumLength, 250 UINT32 BitGranularity, 251 UINT32 ByteGranularity) 252{ 253 ACPI_STATUS Status; 254 UINT32 ThisFieldByteOffset; 255 UINT32 ThisFieldDatumOffset; 256 UINT32 PreviousRawDatum; 257 UINT32 ThisRawDatum; 258 UINT32 ValidFieldBits; 259 UINT32 Mask; 260 UINT32 MergedDatum = 0; 261 262 263 FUNCTION_TRACE ("AmlReadField"); 264 265 /* 266 * Clear the caller's buffer (the whole buffer length as given) 267 * This is very important, especially in the cases where a byte is read, 268 * but the buffer is really a UINT32 (4 bytes). 269 */ 270 271 MEMSET (Buffer, 0, BufferLength); 272 273 /* Read the first raw datum to prime the loop */ 274 275 ThisFieldByteOffset = 0; 276 ThisFieldDatumOffset= 0; 277 278 Status = AcpiAmlReadFieldData (ObjDesc, ThisFieldByteOffset, BitGranularity, 279 &PreviousRawDatum); 280 if (ACPI_FAILURE (Status)) 281 { 282 goto Cleanup; 283 } 284 285 /* We might actually be done if the request fits in one datum */ 286 287 if ((DatumLength == 1) && 288 ((ObjDesc->Field.BitOffset + ObjDesc->FieldUnit.Length) <= 289 (UINT16) BitGranularity)) 290 { 291 MergedDatum = PreviousRawDatum; 292 293 MergedDatum = (MergedDatum >> ObjDesc->Field.BitOffset); 294 295 ValidFieldBits = ObjDesc->FieldUnit.Length % BitGranularity; 296 if (ValidFieldBits) 297 { 298 Mask = (((UINT32) 1 << ValidFieldBits) - (UINT32) 1); 299 MergedDatum &= Mask; 300 } 301 302 303 /* 304 * Place the MergedDatum into the proper format and return buffer 305 * field 306 */ 307 308 switch (ByteGranularity) 309 { 310 case 1: 311 ((UINT8 *) Buffer) [ThisFieldDatumOffset] = (UINT8) MergedDatum; 312 break; 313 314 case 2: 315 MOVE_UNALIGNED16_TO_16 (&(((UINT16 *) Buffer)[ThisFieldDatumOffset]), &MergedDatum); 316 break; 317 318 case 4: 319 MOVE_UNALIGNED32_TO_32 (&(((UINT32 *) Buffer)[ThisFieldDatumOffset]), &MergedDatum); 320 break; 321 } 322 323 ThisFieldByteOffset = 1; 324 ThisFieldDatumOffset = 1; 325 } 326 327 else 328 { 329 /* We need to get more raw data to complete one or more field data */ 330 331 while (ThisFieldDatumOffset < DatumLength) 332 { 333 /* 334 * Get the next raw datum, it contains bits of the current 335 * field datum 336 */ 337 338 Status = AcpiAmlReadFieldData (ObjDesc, 339 ThisFieldByteOffset + ByteGranularity, 340 BitGranularity, &ThisRawDatum); 341 if (ACPI_FAILURE (Status)) 342 { 343 goto Cleanup; 344 } 345 346 /* Before merging the data, make sure the unused bits are clear */ 347 348 switch (ByteGranularity) 349 { 350 case 1: 351 ThisRawDatum &= 0x000000FF; 352 PreviousRawDatum &= 0x000000FF; 353 break; 354 355 case 2: 356 ThisRawDatum &= 0x0000FFFF; 357 PreviousRawDatum &= 0x0000FFFF; 358 break; 359 } 360 361 /* 362 * Put together bits of the two raw data to make a complete 363 * field datum 364 */ 365 366 367 if (ObjDesc->Field.BitOffset != 0) 368 { 369 MergedDatum = 370 (PreviousRawDatum >> ObjDesc->Field.BitOffset) | 371 (ThisRawDatum << (BitGranularity - ObjDesc->Field.BitOffset)); 372 } 373 374 else 375 { 376 MergedDatum = PreviousRawDatum; 377 } 378 379 /* 380 * Prepare the merged datum for storing into the caller's 381 * buffer. It is possible to have a 32-bit buffer 382 * (ByteGranularity == 4), but a ObjDesc->Field.Length 383 * of 8 or 16, meaning that the upper bytes of merged data 384 * are undesired. This section fixes that. 385 */ 386 switch (ObjDesc->Field.Length) 387 { 388 case 8: 389 MergedDatum &= 0x000000FF; 390 break; 391 392 case 16: 393 MergedDatum &= 0x0000FFFF; 394 break; 395 } 396 397 /* 398 * Now store the datum in the caller's buffer, according to 399 * the data type 400 */ 401 switch (ByteGranularity) 402 { 403 case 1: 404 ((UINT8 *) Buffer) [ThisFieldDatumOffset] = (UINT8) MergedDatum; 405 break; 406 407 case 2: 408 MOVE_UNALIGNED16_TO_16 (&(((UINT16 *) Buffer) [ThisFieldDatumOffset]), &MergedDatum); 409 break; 410 411 case 4: 412 MOVE_UNALIGNED32_TO_32 (&(((UINT32 *) Buffer) [ThisFieldDatumOffset]), &MergedDatum); 413 break; 414 } 415 416 /* 417 * Save the most recent datum since it contains bits of 418 * the *next* field datum 419 */ 420 421 PreviousRawDatum = ThisRawDatum; 422 423 ThisFieldByteOffset += ByteGranularity; 424 ThisFieldDatumOffset++; 425 426 } /* while */ 427 } 428 429Cleanup: 430 431 return_ACPI_STATUS (Status); 432} 433 434 435/******************************************************************************* 436 * 437 * FUNCTION: AcpiAmlWriteFieldData 438 * 439 * PARAMETERS: *ObjDesc - Field to be set 440 * Value - Value to store 441 * FieldBitWidth - Field Width in bits (8, 16, or 32) 442 * 443 * RETURN: Status 444 * 445 * DESCRIPTION: Store the value into the given field 446 * 447 ******************************************************************************/ 448 449static ACPI_STATUS 450AcpiAmlWriteFieldData ( 451 ACPI_OPERAND_OBJECT *ObjDesc, 452 UINT32 FieldByteOffset, 453 UINT32 FieldBitWidth, 454 UINT32 Value) 455{ 456 ACPI_STATUS Status = AE_OK; 457 ACPI_OPERAND_OBJECT *RgnDesc = NULL; 458 ACPI_PHYSICAL_ADDRESS Address; 459 UINT32 FieldByteWidth; 460 461 462 FUNCTION_TRACE ("AmlWriteFieldData"); 463 464 465 /* ObjDesc is validated by callers */ 466 467 if (ObjDesc) 468 { 469 RgnDesc = ObjDesc->Field.Container; 470 } 471 472 FieldByteWidth = DIV_8 (FieldBitWidth); 473 Status = AcpiAmlSetupField (ObjDesc, RgnDesc, FieldBitWidth); 474 if (ACPI_FAILURE (Status)) 475 { 476 return_ACPI_STATUS (Status); 477 } 478 479 480 /* 481 * Set offset to next multiple of field width, 482 * add region base address and offset within the field 483 */ 484 Address = RgnDesc->Region.Address + 485 (ObjDesc->Field.Offset * FieldByteWidth) + 486 FieldByteOffset; 487 488 DEBUG_PRINT (TRACE_OPREGION, 489 ("AmlWriteField: Store %lx in Region %s(%X) at %p width %X\n", 490 Value, AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 491 RgnDesc->Region.SpaceId, Address, 492 FieldBitWidth)); 493 494 /* Invoke the appropriate AddressSpace/OpRegion handler */ 495 496 Status = AcpiEvAddressSpaceDispatch (RgnDesc, ADDRESS_SPACE_WRITE, 497 Address, FieldBitWidth, &Value); 498 499 if (Status == AE_NOT_IMPLEMENTED) 500 { 501 DEBUG_PRINT (ACPI_ERROR, 502 ("AmlWriteField: **** Region type %s(%X) not implemented\n", 503 AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 504 RgnDesc->Region.SpaceId)); 505 } 506 507 else if (Status == AE_NOT_EXIST) 508 { 509 DEBUG_PRINT (ACPI_ERROR, 510 ("AmlWriteField: **** Region type %s(%X) does not have a handler\n", 511 AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 512 RgnDesc->Region.SpaceId)); 513 } 514 515 return_ACPI_STATUS (Status); 516} 517 518 519/***************************************************************************** 520 * 521 * FUNCTION: AcpiAmlWriteFieldDataWithUpdateRule 522 * 523 * PARAMETERS: *ObjDesc - Field to be set 524 * Value - Value to store 525 * FieldBitWidth - Field Width in bits (8, 16, or 32) 526 * 527 * RETURN: Status 528 * 529 * DESCRIPTION: Apply the field update rule to a field write 530 * 531 ****************************************************************************/ 532 533static ACPI_STATUS 534AcpiAmlWriteFieldDataWithUpdateRule ( 535 ACPI_OPERAND_OBJECT *ObjDesc, 536 UINT32 Mask, 537 UINT32 FieldValue, 538 UINT32 ThisFieldByteOffset, 539 UINT32 BitGranularity) 540{ 541 ACPI_STATUS Status = AE_OK; 542 UINT32 MergedValue; 543 UINT32 CurrentValue; 544 545 546 /* Start with the new bits */ 547 548 MergedValue = FieldValue; 549 550 /* Check if update rule needs to be applied (not if mask is all ones) */ 551 552 553 /* Decode the update rule */ 554 555 switch (ObjDesc->Field.UpdateRule) 556 { 557 558 case UPDATE_PRESERVE: 559 560 /* 561 * Read the current contents of the byte/word/dword containing 562 * the field, and merge with the new field value. 563 */ 564 Status = AcpiAmlReadFieldData (ObjDesc, ThisFieldByteOffset, 565 BitGranularity, &CurrentValue); 566 MergedValue |= (CurrentValue & ~Mask); 567 break; 568 569 570 case UPDATE_WRITE_AS_ONES: 571 572 /* Set positions outside the field to all ones */ 573 574 MergedValue |= ~Mask; 575 break; 576 577 578 case UPDATE_WRITE_AS_ZEROS: 579 580 /* Set positions outside the field to all zeros */ 581 582 MergedValue &= Mask; 583 break; 584 585 586 default: 587 DEBUG_PRINT (ACPI_ERROR, 588 ("WriteFieldDataWithUpdateRule: Unknown UpdateRule setting: %x\n", 589 ObjDesc->Field.UpdateRule)); 590 Status = AE_AML_OPERAND_VALUE; 591 } 592 593 594 /* Write the merged value */ 595 596 if (ACPI_SUCCESS (Status)) 597 { 598 Status = AcpiAmlWriteFieldData (ObjDesc, ThisFieldByteOffset, 599 BitGranularity, MergedValue); 600 } 601 602 return (Status); 603} 604 605 606/***************************************************************************** 607 * 608 * FUNCTION: AcpiAmlWriteField 609 * 610 * PARAMETERS: *ObjDesc - Field to be set 611 * Value - Value to store 612 * FieldBitWidth - Field Width in bits (8, 16, or 32) 613 * 614 * RETURN: Status 615 * 616 * DESCRIPTION: Store the value into the given field 617 * 618 ****************************************************************************/ 619 620ACPI_STATUS 621AcpiAmlWriteField ( 622 ACPI_OPERAND_OBJECT *ObjDesc, 623 void *Buffer, 624 UINT32 BufferLength, 625 UINT32 ByteLength, 626 UINT32 DatumLength, 627 UINT32 BitGranularity, 628 UINT32 ByteGranularity) 629{ 630 ACPI_STATUS Status; 631 UINT32 ThisFieldByteOffset; 632 UINT32 ThisFieldDatumOffset; 633 UINT32 Mask; 634 UINT32 MergedDatum; 635 UINT32 PreviousRawDatum; 636 UINT32 ThisRawDatum; 637 UINT32 FieldValue; 638 UINT32 ValidFieldBits; 639 640 641 FUNCTION_TRACE ("AmlWriteField"); 642 643 644 /* 645 * Break the request into up to three parts: 646 * non-aligned part at start, aligned part in middle, non-aligned part 647 * at end --- Just like an I/O request --- 648 */ 649 650 ThisFieldByteOffset = 0; 651 ThisFieldDatumOffset= 0; 652 653 /* Get a datum */ 654 655 switch (ByteGranularity) 656 { 657 case 1: 658 PreviousRawDatum = ((UINT8 *) Buffer) [ThisFieldDatumOffset]; 659 break; 660 661 case 2: 662 MOVE_UNALIGNED16_TO_32 (&PreviousRawDatum, &(((UINT16 *) Buffer) [ThisFieldDatumOffset])); 663 break; 664 665 case 4: 666 MOVE_UNALIGNED32_TO_32 (&PreviousRawDatum, &(((UINT32 *) Buffer) [ThisFieldDatumOffset])); 667 break; 668 669 default: 670 DEBUG_PRINT (ACPI_ERROR, ("AmlWriteField: Invalid granularity: %x\n", 671 ByteGranularity)); 672 Status = AE_AML_OPERAND_VALUE; 673 goto Cleanup; 674 } 675 676 677 /* 678 * Write a partial field datum if field does not begin on a datum boundary 679 * 680 * Construct Mask with 1 bits where the field is, 0 bits elsewhere 681 * 682 * 1) Bits above the field 683 */ 684 685 Mask = (((UINT32)(-1)) << (UINT32)ObjDesc->Field.BitOffset); 686 687 /* 2) Only the bottom 5 bits are valid for a shift operation. */ 688 689 if ((ObjDesc->Field.BitOffset + ObjDesc->FieldUnit.Length) < 32) 690 { 691 /* Bits above the field */ 692 693 Mask &= (~(((UINT32)(-1)) << ((UINT32)ObjDesc->Field.BitOffset + 694 (UINT32)ObjDesc->FieldUnit.Length))); 695 } 696 697 /* 3) Shift and mask the value into the field position */ 698 699 FieldValue = (PreviousRawDatum << ObjDesc->Field.BitOffset) & Mask; 700 701 Status = AcpiAmlWriteFieldDataWithUpdateRule (ObjDesc, Mask, FieldValue, 702 ThisFieldByteOffset, 703 BitGranularity); 704 if (ACPI_FAILURE (Status)) 705 { 706 goto Cleanup; 707 } 708 709 710 /* If the field fits within one datum, we are done. */ 711 712 if ((DatumLength == 1) && 713 ((ObjDesc->Field.BitOffset + ObjDesc->FieldUnit.Length) <= 714 (UINT16) BitGranularity)) 715 { 716 goto Cleanup; 717 } 718 719 /* 720 * We don't need to worry about the update rule for these data, because 721 * all of the bits are part of the field. 722 * 723 * Can't write the last datum, however, because it might contain bits that 724 * are not part of the field -- the update rule must be applied. 725 */ 726 727 while (ThisFieldDatumOffset < (DatumLength - 1)) 728 { 729 ThisFieldDatumOffset++; 730 731 /* Get the next raw datum, it contains bits of the current field datum... */ 732 733 switch (ByteGranularity) 734 { 735 case 1: 736 ThisRawDatum = ((UINT8 *) Buffer) [ThisFieldDatumOffset]; 737 break; 738 739 case 2: 740 MOVE_UNALIGNED16_TO_32 (&ThisRawDatum, &(((UINT16 *) Buffer) [ThisFieldDatumOffset])); 741 break; 742 743 case 4: 744 MOVE_UNALIGNED32_TO_32 (&ThisRawDatum, &(((UINT32 *) Buffer) [ThisFieldDatumOffset])); 745 break; 746 747 default: 748 DEBUG_PRINT (ACPI_ERROR, ("AmlWriteField: Invalid Byte Granularity: %x\n", 749 ByteGranularity)); 750 Status = AE_AML_OPERAND_VALUE; 751 goto Cleanup; 752 } 753 754 /* 755 * Put together bits of the two raw data to make a complete field 756 * datum 757 */ 758 759 if (ObjDesc->Field.BitOffset != 0) 760 { 761 MergedDatum = 762 (PreviousRawDatum >> (BitGranularity - ObjDesc->Field.BitOffset)) | 763 (ThisRawDatum << ObjDesc->Field.BitOffset); 764 } 765 766 else 767 { 768 MergedDatum = ThisRawDatum; 769 } 770 771 /* Now write the completed datum */ 772 773 774 Status = AcpiAmlWriteFieldData (ObjDesc, 775 ThisFieldByteOffset + ByteGranularity, 776 BitGranularity, MergedDatum); 777 if (ACPI_FAILURE (Status)) 778 { 779 goto Cleanup; 780 } 781 782 783 /* 784 * Save the most recent datum since it contains bits of 785 * the *next* field datum 786 */ 787 788 PreviousRawDatum = ThisRawDatum; 789 790 ThisFieldByteOffset += ByteGranularity; 791 792 } /* while */ 793 794 795 /* Write a partial field datum if field does not end on a datum boundary */ 796 797 if ((ObjDesc->FieldUnit.Length + ObjDesc->FieldUnit.BitOffset) % 798 BitGranularity) 799 { 800 switch (ByteGranularity) 801 { 802 case 1: 803 ThisRawDatum = ((UINT8 *) Buffer) [ThisFieldDatumOffset]; 804 break; 805 806 case 2: 807 MOVE_UNALIGNED16_TO_32 (&ThisRawDatum, &(((UINT16 *) Buffer) [ThisFieldDatumOffset])); 808 break; 809 810 case 4: 811 MOVE_UNALIGNED32_TO_32 (&ThisRawDatum, &(((UINT32 *) Buffer) [ThisFieldDatumOffset])); 812 break; 813 } 814 815 /* Construct Mask with 1 bits where the field is, 0 bits elsewhere */ 816 817 ValidFieldBits = ((ObjDesc->FieldUnit.Length % BitGranularity) + 818 ObjDesc->Field.BitOffset); 819 820 Mask = (((UINT32) 1 << ValidFieldBits) - (UINT32) 1); 821 822 /* Shift and mask the value into the field position */ 823 824 FieldValue = (PreviousRawDatum >> 825 (BitGranularity - ObjDesc->Field.BitOffset)) & Mask; 826 827 Status = AcpiAmlWriteFieldDataWithUpdateRule (ObjDesc, Mask, FieldValue, 828 ThisFieldByteOffset + ByteGranularity, 829 BitGranularity); 830 if (ACPI_FAILURE (Status)) 831 { 832 goto Cleanup; 833 } 834 } 835 836 837Cleanup: 838 839 return_ACPI_STATUS (Status); 840} 841 842 843