1 /******************************************************************************
2 *
3 * Module Name: exfldio - Aml Field I/O
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2011, 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.
81 *
82 * PARAMETERS: ObjDesc - Field to be read or written
83 * FieldDatumByteOffset - Byte offset of this datum within the
84 * parent field
85 *
86 * RETURN: Status
87 *
88 * DESCRIPTION: Common processing for AcpiExExtractFromField and
89 * AcpiExInsertIntoField. Initialize the Region if necessary and
90 * validate the request.
91 *
92 ******************************************************************************/
93
94 static ACPI_STATUS
95 AcpiExSetupRegion (
96 ACPI_OPERAND_OBJECT *ObjDesc,
97 UINT32 FieldDatumByteOffset)
98 {
99 ACPI_STATUS Status = AE_OK;
100 ACPI_OPERAND_OBJECT *RgnDesc;
101
102
103 ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
104
105
106 RgnDesc = ObjDesc->CommonField.RegionObj;
107
108 /* We must have a valid region */
109
110 if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
111 {
112 ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
113 RgnDesc->Common.Type,
114 AcpiUtGetObjectTypeName (RgnDesc)));
115
116 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
117 }
118
119 /*
120 * If the Region Address and Length have not been previously evaluated,
121 * evaluate them now and save the results.
122 */
123 if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
124 {
125 Status = AcpiDsGetRegionArguments (RgnDesc);
126 if (ACPI_FAILURE (Status))
127 {
128 return_ACPI_STATUS (Status);
129 }
130 }
131
132 /*
133 * Exit now for SMBus or IPMI address space, it has a non-linear
134 * address space and the request cannot be directly validated
135 */
136 if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
137 RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
138 {
139 /* SMBus or IPMI has a non-linear address space */
140
141 return_ACPI_STATUS (AE_OK);
142 }
143
144 #ifdef ACPI_UNDER_DEVELOPMENT
145 /*
146 * If the Field access is AnyAcc, we can now compute the optimal
147 * access (because we know know the length of the parent region)
148 */
149 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
150 {
151 if (ACPI_FAILURE (Status))
152 {
153 return_ACPI_STATUS (Status);
154 }
155 }
156 #endif
157
273 if ((Function & ACPI_IO_MASK) == ACPI_READ)
274 {
275 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
276 }
277 else
278 {
279 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
280 }
281
282 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
283 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
284 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
285 RgnDesc->Region.SpaceId,
286 ObjDesc->CommonField.AccessByteWidth,
287 ObjDesc->CommonField.BaseByteOffset,
288 FieldDatumByteOffset,
289 ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
290
291 /* Invoke the appropriate AddressSpace/OpRegion handler */
292
293 Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, RegionOffset,
294 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
295
296 if (ACPI_FAILURE (Status))
297 {
298 if (Status == AE_NOT_IMPLEMENTED)
299 {
300 ACPI_ERROR ((AE_INFO,
301 "Region %s (ID=%u) not implemented",
302 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
303 RgnDesc->Region.SpaceId));
304 }
305 else if (Status == AE_NOT_EXIST)
306 {
307 ACPI_ERROR ((AE_INFO,
308 "Region %s (ID=%u) has no handler",
309 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
310 RgnDesc->Region.SpaceId));
311 }
312 }
313
336 AcpiExRegisterOverflow (
337 ACPI_OPERAND_OBJECT *ObjDesc,
338 UINT64 Value)
339 {
340
341 if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
342 {
343 /*
344 * The field is large enough to hold the maximum integer, so we can
345 * never overflow it.
346 */
347 return (FALSE);
348 }
349
350 if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
351 {
352 /*
353 * The Value is larger than the maximum value that can fit into
354 * the register.
355 */
356 return (TRUE);
357 }
358
359 /* The Value will fit into the field with no truncation */
360
361 return (FALSE);
362 }
363
364
365 /*******************************************************************************
366 *
367 * FUNCTION: AcpiExFieldDatumIo
368 *
369 * PARAMETERS: ObjDesc - Field to be read
370 * FieldDatumByteOffset - Byte offset of this datum within the
371 * parent field
372 * Value - Where to store value (must be 64 bits)
373 * ReadWrite - Read or Write flag
374 *
375 * RETURN: Status
445 (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
446 ObjDesc->BufferField.BaseByteOffset +
447 FieldDatumByteOffset,
448 ObjDesc->CommonField.AccessByteWidth);
449 }
450 else
451 {
452 /*
453 * Copy the data to the target buffer.
454 * Length is the field width in bytes.
455 */
456 ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
457 ObjDesc->BufferField.BaseByteOffset +
458 FieldDatumByteOffset,
459 Value, ObjDesc->CommonField.AccessByteWidth);
460 }
461
462 Status = AE_OK;
463 break;
464
465
466 case ACPI_TYPE_LOCAL_BANK_FIELD:
467
468 /*
469 * Ensure that the BankValue is not beyond the capacity of
470 * the register
471 */
472 if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
473 (UINT64) ObjDesc->BankField.Value))
474 {
475 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
476 }
477
478 /*
479 * For BankFields, we must write the BankValue to the BankRegister
480 * (itself a RegionField) before we can access the data.
481 */
482 Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
483 &ObjDesc->BankField.Value,
484 sizeof (ObjDesc->BankField.Value));
485 if (ACPI_FAILURE (Status))
486 {
487 return_ACPI_STATUS (Status);
488 }
489
490 /*
491 * Now that the Bank has been selected, fall through to the
492 * RegionField case and write the datum to the Operation Region
493 */
494
495 /*lint -fallthrough */
496
497
498 case ACPI_TYPE_LOCAL_REGION_FIELD:
499 /*
500 * For simple RegionFields, we just directly access the owning
501 * Operation Region.
502 */
503 Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
504 ReadWrite);
505 break;
506
507
508 case ACPI_TYPE_LOCAL_INDEX_FIELD:
509
510
511 /*
512 * Ensure that the IndexValue is not beyond the capacity of
513 * the register
514 */
515 if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
516 (UINT64) ObjDesc->IndexField.Value))
517 {
518 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
519 }
520
521 /* Write the index value to the IndexRegister (itself a RegionField) */
522
523 FieldDatumByteOffset += ObjDesc->IndexField.Value;
524
525 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
526 "Write to Index Register: Value %8.8X\n",
527 FieldDatumByteOffset));
528
529 Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
530 &FieldDatumByteOffset,
540
541 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
542 "Read from Data Register\n"));
543
544 Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
545 Value, sizeof (UINT64));
546 }
547 else
548 {
549 /* Write the datum to the DataRegister */
550
551 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
552 "Write to Data Register: Value %8.8X%8.8X\n",
553 ACPI_FORMAT_UINT64 (*Value)));
554
555 Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
556 Value, sizeof (UINT64));
557 }
558 break;
559
560
561 default:
562
563 ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
564 ObjDesc->Common.Type));
565 Status = AE_AML_INTERNAL;
566 break;
567 }
568
569 if (ACPI_SUCCESS (Status))
570 {
571 if (ReadWrite == ACPI_READ)
572 {
573 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
574 "Value Read %8.8X%8.8X, Width %u\n",
575 ACPI_FORMAT_UINT64 (*Value),
576 ObjDesc->CommonField.AccessByteWidth));
577 }
578 else
579 {
580 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
731 /* Validate target buffer and clear it */
732
733 if (BufferLength <
734 ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
735 {
736 ACPI_ERROR ((AE_INFO,
737 "Field size %u (bits) is too large for buffer (%u)",
738 ObjDesc->CommonField.BitLength, BufferLength));
739
740 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
741 }
742
743 ACPI_MEMSET (Buffer, 0, BufferLength);
744 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
745
746 /* Handle the simple case here */
747
748 if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
749 (ObjDesc->CommonField.BitLength == AccessBitWidth))
750 {
751 Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
752 return_ACPI_STATUS (Status);
753 }
754
755 /* TBD: Move to common setup code */
756
757 /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
758
759 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
760 {
761 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
762 AccessBitWidth = sizeof (UINT64) * 8;
763 }
764
765 /* Compute the number of datums (access width data items) */
766
767 DatumCount = ACPI_ROUND_UP_TO (
768 ObjDesc->CommonField.BitLength, AccessBitWidth);
769
770 FieldDatumCount = ACPI_ROUND_UP_TO (
771 ObjDesc->CommonField.BitLength +
1016 if (BufferTailBits)
1017 {
1018 Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1019 }
1020
1021 /* Write the last datum to the field */
1022
1023 MergedDatum &= Mask;
1024 Status = AcpiExWriteWithUpdateRule (ObjDesc,
1025 Mask, MergedDatum, FieldOffset);
1026
1027 Exit:
1028 /* Free temporary buffer if we used one */
1029
1030 if (NewBuffer)
1031 {
1032 ACPI_FREE (NewBuffer);
1033 }
1034 return_ACPI_STATUS (Status);
1035 }
1036
1037
|
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.
81 *
82 * PARAMETERS: ObjDesc - Field to be read or written
83 * FieldDatumByteOffset - Byte offset of this datum within the
84 * parent field
85 *
86 * RETURN: Status
87 *
88 * DESCRIPTION: Common processing for AcpiExExtractFromField and
89 * AcpiExInsertIntoField. Initialize the Region if necessary and
90 * validate the request.
91 *
92 ******************************************************************************/
93
94 static ACPI_STATUS
95 AcpiExSetupRegion (
96 ACPI_OPERAND_OBJECT *ObjDesc,
97 UINT32 FieldDatumByteOffset)
98 {
99 ACPI_STATUS Status = AE_OK;
100 ACPI_OPERAND_OBJECT *RgnDesc;
101 UINT8 SpaceId;
102
103
104 ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
105
106
107 RgnDesc = ObjDesc->CommonField.RegionObj;
108
109 /* We must have a valid region */
110
111 if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
112 {
113 ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
114 RgnDesc->Common.Type,
115 AcpiUtGetObjectTypeName (RgnDesc)));
116
117 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
118 }
119
120 SpaceId = RgnDesc->Region.SpaceId;
121
122 /* Validate the Space ID */
123
124 if (!AcpiIsValidSpaceId (SpaceId))
125 {
126 ACPI_ERROR ((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
127 return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
128 }
129
130 /*
131 * If the Region Address and Length have not been previously evaluated,
132 * evaluate them now and save the results.
133 */
134 if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
135 {
136 Status = AcpiDsGetRegionArguments (RgnDesc);
137 if (ACPI_FAILURE (Status))
138 {
139 return_ACPI_STATUS (Status);
140 }
141 }
142
143 /*
144 * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
145 * address space and the request cannot be directly validated
146 */
147 if (SpaceId == ACPI_ADR_SPACE_SMBUS ||
148 SpaceId == ACPI_ADR_SPACE_GSBUS ||
149 SpaceId == ACPI_ADR_SPACE_IPMI)
150 {
151 /* SMBus or IPMI has a non-linear address space */
152
153 return_ACPI_STATUS (AE_OK);
154 }
155
156 #ifdef ACPI_UNDER_DEVELOPMENT
157 /*
158 * If the Field access is AnyAcc, we can now compute the optimal
159 * access (because we know know the length of the parent region)
160 */
161 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
162 {
163 if (ACPI_FAILURE (Status))
164 {
165 return_ACPI_STATUS (Status);
166 }
167 }
168 #endif
169
285 if ((Function & ACPI_IO_MASK) == ACPI_READ)
286 {
287 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
288 }
289 else
290 {
291 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
292 }
293
294 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
295 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
296 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
297 RgnDesc->Region.SpaceId,
298 ObjDesc->CommonField.AccessByteWidth,
299 ObjDesc->CommonField.BaseByteOffset,
300 FieldDatumByteOffset,
301 ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
302
303 /* Invoke the appropriate AddressSpace/OpRegion handler */
304
305 Status = AcpiEvAddressSpaceDispatch (RgnDesc, ObjDesc,
306 Function, RegionOffset,
307 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
308
309 if (ACPI_FAILURE (Status))
310 {
311 if (Status == AE_NOT_IMPLEMENTED)
312 {
313 ACPI_ERROR ((AE_INFO,
314 "Region %s (ID=%u) not implemented",
315 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
316 RgnDesc->Region.SpaceId));
317 }
318 else if (Status == AE_NOT_EXIST)
319 {
320 ACPI_ERROR ((AE_INFO,
321 "Region %s (ID=%u) has no handler",
322 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
323 RgnDesc->Region.SpaceId));
324 }
325 }
326
349 AcpiExRegisterOverflow (
350 ACPI_OPERAND_OBJECT *ObjDesc,
351 UINT64 Value)
352 {
353
354 if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
355 {
356 /*
357 * The field is large enough to hold the maximum integer, so we can
358 * never overflow it.
359 */
360 return (FALSE);
361 }
362
363 if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
364 {
365 /*
366 * The Value is larger than the maximum value that can fit into
367 * the register.
368 */
369 ACPI_ERROR ((AE_INFO,
370 "Index value 0x%8.8X%8.8X overflows field width 0x%X",
371 ACPI_FORMAT_UINT64 (Value),
372 ObjDesc->CommonField.BitLength));
373
374 return (TRUE);
375 }
376
377 /* The Value will fit into the field with no truncation */
378
379 return (FALSE);
380 }
381
382
383 /*******************************************************************************
384 *
385 * FUNCTION: AcpiExFieldDatumIo
386 *
387 * PARAMETERS: ObjDesc - Field to be read
388 * FieldDatumByteOffset - Byte offset of this datum within the
389 * parent field
390 * Value - Where to store value (must be 64 bits)
391 * ReadWrite - Read or Write flag
392 *
393 * RETURN: Status
463 (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
464 ObjDesc->BufferField.BaseByteOffset +
465 FieldDatumByteOffset,
466 ObjDesc->CommonField.AccessByteWidth);
467 }
468 else
469 {
470 /*
471 * Copy the data to the target buffer.
472 * Length is the field width in bytes.
473 */
474 ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
475 ObjDesc->BufferField.BaseByteOffset +
476 FieldDatumByteOffset,
477 Value, ObjDesc->CommonField.AccessByteWidth);
478 }
479
480 Status = AE_OK;
481 break;
482
483 case ACPI_TYPE_LOCAL_BANK_FIELD:
484 /*
485 * Ensure that the BankValue is not beyond the capacity of
486 * the register
487 */
488 if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
489 (UINT64) ObjDesc->BankField.Value))
490 {
491 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
492 }
493
494 /*
495 * For BankFields, we must write the BankValue to the BankRegister
496 * (itself a RegionField) before we can access the data.
497 */
498 Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
499 &ObjDesc->BankField.Value,
500 sizeof (ObjDesc->BankField.Value));
501 if (ACPI_FAILURE (Status))
502 {
503 return_ACPI_STATUS (Status);
504 }
505
506 /*
507 * Now that the Bank has been selected, fall through to the
508 * RegionField case and write the datum to the Operation Region
509 */
510
511 /*lint -fallthrough */
512
513 case ACPI_TYPE_LOCAL_REGION_FIELD:
514 /*
515 * For simple RegionFields, we just directly access the owning
516 * Operation Region.
517 */
518 Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
519 ReadWrite);
520 break;
521
522 case ACPI_TYPE_LOCAL_INDEX_FIELD:
523 /*
524 * Ensure that the IndexValue is not beyond the capacity of
525 * the register
526 */
527 if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
528 (UINT64) ObjDesc->IndexField.Value))
529 {
530 return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
531 }
532
533 /* Write the index value to the IndexRegister (itself a RegionField) */
534
535 FieldDatumByteOffset += ObjDesc->IndexField.Value;
536
537 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
538 "Write to Index Register: Value %8.8X\n",
539 FieldDatumByteOffset));
540
541 Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
542 &FieldDatumByteOffset,
552
553 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
554 "Read from Data Register\n"));
555
556 Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
557 Value, sizeof (UINT64));
558 }
559 else
560 {
561 /* Write the datum to the DataRegister */
562
563 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
564 "Write to Data Register: Value %8.8X%8.8X\n",
565 ACPI_FORMAT_UINT64 (*Value)));
566
567 Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
568 Value, sizeof (UINT64));
569 }
570 break;
571
572 default:
573
574 ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
575 ObjDesc->Common.Type));
576 Status = AE_AML_INTERNAL;
577 break;
578 }
579
580 if (ACPI_SUCCESS (Status))
581 {
582 if (ReadWrite == ACPI_READ)
583 {
584 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
585 "Value Read %8.8X%8.8X, Width %u\n",
586 ACPI_FORMAT_UINT64 (*Value),
587 ObjDesc->CommonField.AccessByteWidth));
588 }
589 else
590 {
591 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
742 /* Validate target buffer and clear it */
743
744 if (BufferLength <
745 ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
746 {
747 ACPI_ERROR ((AE_INFO,
748 "Field size %u (bits) is too large for buffer (%u)",
749 ObjDesc->CommonField.BitLength, BufferLength));
750
751 return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
752 }
753
754 ACPI_MEMSET (Buffer, 0, BufferLength);
755 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
756
757 /* Handle the simple case here */
758
759 if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
760 (ObjDesc->CommonField.BitLength == AccessBitWidth))
761 {
762 if (BufferLength >= sizeof (UINT64))
763 {
764 Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
765 }
766 else
767 {
768 /* Use RawDatum (UINT64) to handle buffers < 64 bits */
769
770 Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ);
771 ACPI_MEMCPY (Buffer, &RawDatum, BufferLength);
772 }
773
774 return_ACPI_STATUS (Status);
775 }
776
777 /* TBD: Move to common setup code */
778
779 /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
780
781 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
782 {
783 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
784 AccessBitWidth = sizeof (UINT64) * 8;
785 }
786
787 /* Compute the number of datums (access width data items) */
788
789 DatumCount = ACPI_ROUND_UP_TO (
790 ObjDesc->CommonField.BitLength, AccessBitWidth);
791
792 FieldDatumCount = ACPI_ROUND_UP_TO (
793 ObjDesc->CommonField.BitLength +
1038 if (BufferTailBits)
1039 {
1040 Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1041 }
1042
1043 /* Write the last datum to the field */
1044
1045 MergedDatum &= Mask;
1046 Status = AcpiExWriteWithUpdateRule (ObjDesc,
1047 Mask, MergedDatum, FieldOffset);
1048
1049 Exit:
1050 /* Free temporary buffer if we used one */
1051
1052 if (NewBuffer)
1053 {
1054 ACPI_FREE (NewBuffer);
1055 }
1056 return_ACPI_STATUS (Status);
1057 }
|