0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "amlcode.h"
0014 #include "acevents.h"
0015 #include "acdispat.h"
0016
0017 #define _COMPONENT ACPI_EXECUTER
0018 ACPI_MODULE_NAME("exfldio")
0019
0020
0021 static acpi_status
0022 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
0023 u32 field_datum_byte_offset, u64 *value, u32 read_write);
0024
0025 static u8
0026 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
0027
0028 static acpi_status
0029 acpi_ex_setup_region(union acpi_operand_object *obj_desc,
0030 u32 field_datum_byte_offset);
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 static acpi_status
0049 acpi_ex_setup_region(union acpi_operand_object *obj_desc,
0050 u32 field_datum_byte_offset)
0051 {
0052 acpi_status status = AE_OK;
0053 union acpi_operand_object *rgn_desc;
0054 u8 space_id;
0055
0056 ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
0057
0058 rgn_desc = obj_desc->common_field.region_obj;
0059
0060
0061
0062 if (rgn_desc->common.type != ACPI_TYPE_REGION) {
0063 ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)",
0064 rgn_desc->common.type,
0065 acpi_ut_get_object_type_name(rgn_desc)));
0066
0067 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0068 }
0069
0070 space_id = rgn_desc->region.space_id;
0071
0072
0073
0074 if (!acpi_is_valid_space_id(space_id)) {
0075 ACPI_ERROR((AE_INFO,
0076 "Invalid/unknown Address Space ID: 0x%2.2X",
0077 space_id));
0078 return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
0079 }
0080
0081
0082
0083
0084
0085 if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
0086 status = acpi_ds_get_region_arguments(rgn_desc);
0087 if (ACPI_FAILURE(status)) {
0088 return_ACPI_STATUS(status);
0089 }
0090 }
0091
0092
0093
0094
0095
0096 if (space_id == ACPI_ADR_SPACE_SMBUS ||
0097 space_id == ACPI_ADR_SPACE_GSBUS ||
0098 space_id == ACPI_ADR_SPACE_IPMI) {
0099
0100
0101
0102 return_ACPI_STATUS(AE_OK);
0103 }
0104 #ifdef ACPI_UNDER_DEVELOPMENT
0105
0106
0107
0108
0109 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
0110 if (ACPI_FAILURE(status)) {
0111 return_ACPI_STATUS(status);
0112 }
0113 }
0114 #endif
0115
0116
0117
0118
0119
0120
0121 if (rgn_desc->region.length <
0122 (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
0123 obj_desc->common_field.access_byte_width)) {
0124 if (acpi_gbl_enable_interpreter_slack) {
0125
0126
0127
0128
0129
0130 if (ACPI_ROUND_UP(rgn_desc->region.length,
0131 obj_desc->common_field.
0132 access_byte_width) >=
0133 ((acpi_size)obj_desc->common_field.
0134 base_byte_offset +
0135 obj_desc->common_field.access_byte_width +
0136 field_datum_byte_offset)) {
0137 return_ACPI_STATUS(AE_OK);
0138 }
0139 }
0140
0141 if (rgn_desc->region.length <
0142 obj_desc->common_field.access_byte_width) {
0143
0144
0145
0146
0147
0148 ACPI_ERROR((AE_INFO,
0149 "Field [%4.4s] access width (%u bytes) "
0150 "too large for region [%4.4s] (length %u)",
0151 acpi_ut_get_node_name(obj_desc->
0152 common_field.node),
0153 obj_desc->common_field.access_byte_width,
0154 acpi_ut_get_node_name(rgn_desc->region.
0155 node),
0156 rgn_desc->region.length));
0157 }
0158
0159
0160
0161
0162
0163 ACPI_ERROR((AE_INFO,
0164 "Field [%4.4s] Base+Offset+Width %u+%u+%u "
0165 "is beyond end of region [%4.4s] (length %u)",
0166 acpi_ut_get_node_name(obj_desc->common_field.node),
0167 obj_desc->common_field.base_byte_offset,
0168 field_datum_byte_offset,
0169 obj_desc->common_field.access_byte_width,
0170 acpi_ut_get_node_name(rgn_desc->region.node),
0171 rgn_desc->region.length));
0172
0173 return_ACPI_STATUS(AE_AML_REGION_LIMIT);
0174 }
0175
0176 return_ACPI_STATUS(AE_OK);
0177 }
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 acpi_status
0198 acpi_ex_access_region(union acpi_operand_object *obj_desc,
0199 u32 field_datum_byte_offset, u64 *value, u32 function)
0200 {
0201 acpi_status status;
0202 union acpi_operand_object *rgn_desc;
0203 u32 region_offset;
0204
0205 ACPI_FUNCTION_TRACE(ex_access_region);
0206
0207
0208
0209
0210
0211 status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset);
0212 if (ACPI_FAILURE(status)) {
0213 return_ACPI_STATUS(status);
0214 }
0215
0216
0217
0218
0219
0220
0221
0222
0223 rgn_desc = obj_desc->common_field.region_obj;
0224 region_offset =
0225 obj_desc->common_field.base_byte_offset + field_datum_byte_offset;
0226
0227 if ((function & ACPI_IO_MASK) == ACPI_READ) {
0228 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]"));
0229 } else {
0230 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]"));
0231 }
0232
0233 ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
0234 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
0235 acpi_ut_get_region_name(rgn_desc->region.
0236 space_id),
0237 rgn_desc->region.space_id,
0238 obj_desc->common_field.access_byte_width,
0239 obj_desc->common_field.base_byte_offset,
0240 field_datum_byte_offset,
0241 ACPI_FORMAT_UINT64(rgn_desc->region.address +
0242 region_offset)));
0243
0244
0245
0246 status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc,
0247 function, region_offset,
0248 ACPI_MUL_8(obj_desc->
0249 common_field.
0250 access_byte_width),
0251 value);
0252
0253 if (ACPI_FAILURE(status)) {
0254 if (status == AE_NOT_IMPLEMENTED) {
0255 ACPI_ERROR((AE_INFO,
0256 "Region %s (ID=%u) not implemented",
0257 acpi_ut_get_region_name(rgn_desc->region.
0258 space_id),
0259 rgn_desc->region.space_id));
0260 } else if (status == AE_NOT_EXIST) {
0261 ACPI_ERROR((AE_INFO,
0262 "Region %s (ID=%u) has no handler",
0263 acpi_ut_get_region_name(rgn_desc->region.
0264 space_id),
0265 rgn_desc->region.space_id));
0266 }
0267 }
0268
0269 return_ACPI_STATUS(status);
0270 }
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 static u8
0290 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
0291 {
0292
0293 if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
0294
0295
0296
0297
0298 return (FALSE);
0299 }
0300
0301 if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) {
0302
0303
0304
0305
0306 ACPI_ERROR((AE_INFO,
0307 "Index value 0x%8.8X%8.8X overflows field width 0x%X",
0308 ACPI_FORMAT_UINT64(value),
0309 obj_desc->common_field.bit_length));
0310
0311 return (TRUE);
0312 }
0313
0314
0315
0316 return (FALSE);
0317 }
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 static acpi_status
0338 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
0339 u32 field_datum_byte_offset, u64 *value, u32 read_write)
0340 {
0341 acpi_status status;
0342 u64 local_value;
0343
0344 ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
0345
0346 if (read_write == ACPI_READ) {
0347 if (!value) {
0348 local_value = 0;
0349
0350
0351 value = &local_value;
0352 }
0353
0354
0355
0356 *value = 0;
0357 }
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 switch (obj_desc->common.type) {
0370 case ACPI_TYPE_BUFFER_FIELD:
0371
0372
0373
0374
0375 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
0376 status = acpi_ds_get_buffer_field_arguments(obj_desc);
0377 if (ACPI_FAILURE(status)) {
0378 return_ACPI_STATUS(status);
0379 }
0380 }
0381
0382 if (read_write == ACPI_READ) {
0383
0384
0385
0386
0387 memcpy(value,
0388 (obj_desc->buffer_field.buffer_obj)->buffer.
0389 pointer +
0390 obj_desc->buffer_field.base_byte_offset +
0391 field_datum_byte_offset,
0392 obj_desc->common_field.access_byte_width);
0393 } else {
0394
0395
0396
0397
0398 memcpy((obj_desc->buffer_field.buffer_obj)->buffer.
0399 pointer +
0400 obj_desc->buffer_field.base_byte_offset +
0401 field_datum_byte_offset, value,
0402 obj_desc->common_field.access_byte_width);
0403 }
0404
0405 status = AE_OK;
0406 break;
0407
0408 case ACPI_TYPE_LOCAL_BANK_FIELD:
0409
0410
0411
0412
0413 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
0414 (u64) obj_desc->bank_field.
0415 value)) {
0416 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
0417 }
0418
0419
0420
0421
0422
0423 status =
0424 acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
0425 &obj_desc->bank_field.value,
0426 sizeof(obj_desc->bank_field.
0427 value));
0428 if (ACPI_FAILURE(status)) {
0429 return_ACPI_STATUS(status);
0430 }
0431
0432
0433
0434
0435
0436
0437 ACPI_FALLTHROUGH;
0438
0439 case ACPI_TYPE_LOCAL_REGION_FIELD:
0440
0441
0442
0443
0444 status =
0445 acpi_ex_access_region(obj_desc, field_datum_byte_offset,
0446 value, read_write);
0447 break;
0448
0449 case ACPI_TYPE_LOCAL_INDEX_FIELD:
0450
0451
0452
0453
0454 if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
0455 (u64) obj_desc->index_field.
0456 value)) {
0457 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
0458 }
0459
0460
0461
0462 field_datum_byte_offset += obj_desc->index_field.value;
0463
0464 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0465 "Write to Index Register: Value %8.8X\n",
0466 field_datum_byte_offset));
0467
0468 status =
0469 acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
0470 &field_datum_byte_offset,
0471 sizeof(field_datum_byte_offset));
0472 if (ACPI_FAILURE(status)) {
0473 return_ACPI_STATUS(status);
0474 }
0475
0476 if (read_write == ACPI_READ) {
0477
0478
0479
0480 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0481 "Read from Data Register\n"));
0482
0483 status =
0484 acpi_ex_extract_from_field(obj_desc->index_field.
0485 data_obj, value,
0486 sizeof(u64));
0487 } else {
0488
0489
0490 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0491 "Write to Data Register: Value %8.8X%8.8X\n",
0492 ACPI_FORMAT_UINT64(*value)));
0493
0494 status =
0495 acpi_ex_insert_into_field(obj_desc->index_field.
0496 data_obj, value,
0497 sizeof(u64));
0498 }
0499 break;
0500
0501 default:
0502
0503 ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u",
0504 obj_desc->common.type));
0505 status = AE_AML_INTERNAL;
0506 break;
0507 }
0508
0509 if (ACPI_SUCCESS(status)) {
0510 if (read_write == ACPI_READ) {
0511 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0512 "Value Read %8.8X%8.8X, Width %u\n",
0513 ACPI_FORMAT_UINT64(*value),
0514 obj_desc->common_field.
0515 access_byte_width));
0516 } else {
0517 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0518 "Value Written %8.8X%8.8X, Width %u\n",
0519 ACPI_FORMAT_UINT64(*value),
0520 obj_desc->common_field.
0521 access_byte_width));
0522 }
0523 }
0524
0525 return_ACPI_STATUS(status);
0526 }
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543 acpi_status
0544 acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc,
0545 u64 mask,
0546 u64 field_value, u32 field_datum_byte_offset)
0547 {
0548 acpi_status status = AE_OK;
0549 u64 merged_value;
0550 u64 current_value;
0551
0552 ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
0553
0554
0555
0556 merged_value = field_value;
0557
0558
0559
0560 if (mask != ACPI_UINT64_MAX) {
0561
0562
0563
0564 switch (obj_desc->common_field.
0565 field_flags & AML_FIELD_UPDATE_RULE_MASK) {
0566 case AML_FIELD_UPDATE_PRESERVE:
0567
0568
0569
0570
0571 if ((~mask << (ACPI_MUL_8(sizeof(mask)) -
0572 ACPI_MUL_8(obj_desc->common_field.
0573 access_byte_width))) != 0) {
0574
0575
0576
0577
0578 status =
0579 acpi_ex_field_datum_io(obj_desc,
0580 field_datum_byte_offset,
0581 ¤t_value,
0582 ACPI_READ);
0583 if (ACPI_FAILURE(status)) {
0584 return_ACPI_STATUS(status);
0585 }
0586
0587 merged_value |= (current_value & ~mask);
0588 }
0589 break;
0590
0591 case AML_FIELD_UPDATE_WRITE_AS_ONES:
0592
0593
0594
0595 merged_value |= ~mask;
0596 break;
0597
0598 case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
0599
0600
0601
0602 merged_value &= mask;
0603 break;
0604
0605 default:
0606
0607 ACPI_ERROR((AE_INFO,
0608 "Unknown UpdateRule value: 0x%X",
0609 (obj_desc->common_field.field_flags &
0610 AML_FIELD_UPDATE_RULE_MASK)));
0611 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
0612 }
0613 }
0614
0615 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
0616 "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
0617 "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
0618 ACPI_FORMAT_UINT64(mask),
0619 field_datum_byte_offset,
0620 obj_desc->common_field.access_byte_width,
0621 ACPI_FORMAT_UINT64(field_value),
0622 ACPI_FORMAT_UINT64(merged_value)));
0623
0624
0625
0626 status =
0627 acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
0628 &merged_value, ACPI_WRITE);
0629
0630 return_ACPI_STATUS(status);
0631 }
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647 acpi_status
0648 acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
0649 void *buffer, u32 buffer_length)
0650 {
0651 acpi_status status;
0652 u64 raw_datum;
0653 u64 merged_datum;
0654 u32 field_offset = 0;
0655 u32 buffer_offset = 0;
0656 u32 buffer_tail_bits;
0657 u32 datum_count;
0658 u32 field_datum_count;
0659 u32 access_bit_width;
0660 u32 i;
0661
0662 ACPI_FUNCTION_TRACE(ex_extract_from_field);
0663
0664
0665
0666 if (buffer_length <
0667 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
0668 ACPI_ERROR((AE_INFO,
0669 "Field size %u (bits) is too large for buffer (%u)",
0670 obj_desc->common_field.bit_length, buffer_length));
0671
0672 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
0673 }
0674
0675 memset(buffer, 0, buffer_length);
0676 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
0677
0678
0679
0680 if ((obj_desc->common_field.start_field_bit_offset == 0) &&
0681 (obj_desc->common_field.bit_length == access_bit_width)) {
0682 if (buffer_length >= sizeof(u64)) {
0683 status =
0684 acpi_ex_field_datum_io(obj_desc, 0, buffer,
0685 ACPI_READ);
0686 } else {
0687
0688
0689 status =
0690 acpi_ex_field_datum_io(obj_desc, 0, &raw_datum,
0691 ACPI_READ);
0692 memcpy(buffer, &raw_datum, buffer_length);
0693 }
0694
0695 return_ACPI_STATUS(status);
0696 }
0697
0698
0699
0700
0701
0702 if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
0703 obj_desc->common_field.access_byte_width = sizeof(u64);
0704 access_bit_width = sizeof(u64) * 8;
0705 }
0706
0707
0708
0709 datum_count =
0710 ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
0711 access_bit_width);
0712
0713 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
0714 obj_desc->common_field.
0715 start_field_bit_offset,
0716 access_bit_width);
0717
0718
0719
0720 status =
0721 acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
0722 ACPI_READ);
0723 if (ACPI_FAILURE(status)) {
0724 return_ACPI_STATUS(status);
0725 }
0726 merged_datum =
0727 raw_datum >> obj_desc->common_field.start_field_bit_offset;
0728
0729
0730
0731 for (i = 1; i < field_datum_count; i++) {
0732
0733
0734
0735 field_offset += obj_desc->common_field.access_byte_width;
0736 status =
0737 acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
0738 ACPI_READ);
0739 if (ACPI_FAILURE(status)) {
0740 return_ACPI_STATUS(status);
0741 }
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751 if (access_bit_width -
0752 obj_desc->common_field.start_field_bit_offset <
0753 ACPI_INTEGER_BIT_SIZE) {
0754 merged_datum |=
0755 raw_datum << (access_bit_width -
0756 obj_desc->common_field.
0757 start_field_bit_offset);
0758 }
0759
0760 if (i == datum_count) {
0761 break;
0762 }
0763
0764
0765
0766 memcpy(((char *)buffer) + buffer_offset, &merged_datum,
0767 ACPI_MIN(obj_desc->common_field.access_byte_width,
0768 buffer_length - buffer_offset));
0769
0770 buffer_offset += obj_desc->common_field.access_byte_width;
0771 merged_datum =
0772 raw_datum >> obj_desc->common_field.start_field_bit_offset;
0773 }
0774
0775
0776
0777 buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
0778 if (buffer_tail_bits) {
0779 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
0780 }
0781
0782
0783
0784 memcpy(((char *)buffer) + buffer_offset, &merged_datum,
0785 ACPI_MIN(obj_desc->common_field.access_byte_width,
0786 buffer_length - buffer_offset));
0787
0788 return_ACPI_STATUS(AE_OK);
0789 }
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805 acpi_status
0806 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
0807 void *buffer, u32 buffer_length)
0808 {
0809 void *new_buffer;
0810 acpi_status status;
0811 u64 mask;
0812 u64 width_mask;
0813 u64 merged_datum;
0814 u64 raw_datum = 0;
0815 u32 field_offset = 0;
0816 u32 buffer_offset = 0;
0817 u32 buffer_tail_bits;
0818 u32 datum_count;
0819 u32 field_datum_count;
0820 u32 access_bit_width;
0821 u32 required_length;
0822 u32 i;
0823
0824 ACPI_FUNCTION_TRACE(ex_insert_into_field);
0825
0826
0827
0828 new_buffer = NULL;
0829 required_length =
0830 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
0831
0832
0833
0834
0835
0836
0837
0838 if (buffer_length < required_length) {
0839
0840
0841
0842 new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
0843 if (!new_buffer) {
0844 return_ACPI_STATUS(AE_NO_MEMORY);
0845 }
0846
0847
0848
0849
0850
0851
0852 memcpy((char *)new_buffer, (char *)buffer, buffer_length);
0853 buffer = new_buffer;
0854 buffer_length = required_length;
0855 }
0856
0857
0858
0859
0860 if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
0861 obj_desc->common_field.access_byte_width = sizeof(u64);
0862 }
0863
0864 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
0865
0866
0867
0868 width_mask = ACPI_MASK_BITS_ABOVE_64(access_bit_width);
0869 mask = width_mask &
0870 ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
0871
0872
0873
0874 datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
0875 access_bit_width);
0876
0877 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
0878 obj_desc->common_field.
0879 start_field_bit_offset,
0880 access_bit_width);
0881
0882
0883
0884 memcpy(&raw_datum, buffer,
0885 ACPI_MIN(obj_desc->common_field.access_byte_width,
0886 buffer_length - buffer_offset));
0887
0888 merged_datum =
0889 raw_datum << obj_desc->common_field.start_field_bit_offset;
0890
0891
0892
0893 for (i = 1; i < field_datum_count; i++) {
0894
0895
0896
0897 merged_datum &= mask;
0898 status =
0899 acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
0900 field_offset);
0901 if (ACPI_FAILURE(status)) {
0902 goto exit;
0903 }
0904
0905 field_offset += obj_desc->common_field.access_byte_width;
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916 if ((access_bit_width -
0917 obj_desc->common_field.start_field_bit_offset) <
0918 ACPI_INTEGER_BIT_SIZE) {
0919 merged_datum =
0920 raw_datum >> (access_bit_width -
0921 obj_desc->common_field.
0922 start_field_bit_offset);
0923 } else {
0924 merged_datum = 0;
0925 }
0926
0927 mask = width_mask;
0928
0929 if (i == datum_count) {
0930 break;
0931 }
0932
0933
0934
0935 buffer_offset += obj_desc->common_field.access_byte_width;
0936 memcpy(&raw_datum, ((char *)buffer) + buffer_offset,
0937 ACPI_MIN(obj_desc->common_field.access_byte_width,
0938 buffer_length - buffer_offset));
0939
0940 merged_datum |=
0941 raw_datum << obj_desc->common_field.start_field_bit_offset;
0942 }
0943
0944
0945
0946 buffer_tail_bits = (obj_desc->common_field.bit_length +
0947 obj_desc->common_field.start_field_bit_offset) %
0948 access_bit_width;
0949 if (buffer_tail_bits) {
0950 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
0951 }
0952
0953
0954
0955 merged_datum &= mask;
0956 status =
0957 acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
0958 field_offset);
0959
0960 exit:
0961
0962
0963 if (new_buffer) {
0964 ACPI_FREE(new_buffer);
0965 }
0966 return_ACPI_STATUS(status);
0967 }