ReactOS 0.4.15-dev-8146-gdc0ed6d
exfldio.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Module Name: exfldio - Aml Field I/O
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2022, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 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.h"
45#include "accommon.h"
46#include "acinterp.h"
47#include "amlcode.h"
48#include "acevents.h"
49#include "acdispat.h"
50
51
52#define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exfldio")
54
55/* Local prototypes */
56
57static ACPI_STATUS
59 ACPI_OPERAND_OBJECT *ObjDesc,
60 UINT32 FieldDatumByteOffset,
63
64static BOOLEAN
66 ACPI_OPERAND_OBJECT *ObjDesc,
68
69static ACPI_STATUS
71 ACPI_OPERAND_OBJECT *ObjDesc,
72 UINT32 FieldDatumByteOffset);
73
74
75/*******************************************************************************
76 *
77 * FUNCTION: AcpiExSetupRegion
78 *
79 * PARAMETERS: ObjDesc - Field to be read or written
80 * FieldDatumByteOffset - Byte offset of this datum within the
81 * parent field
82 *
83 * RETURN: Status
84 *
85 * DESCRIPTION: Common processing for AcpiExExtractFromField and
86 * AcpiExInsertIntoField. Initialize the Region if necessary and
87 * validate the request.
88 *
89 ******************************************************************************/
90
91static ACPI_STATUS
93 ACPI_OPERAND_OBJECT *ObjDesc,
94 UINT32 FieldDatumByteOffset)
95{
97 ACPI_OPERAND_OBJECT *RgnDesc;
99
100
101 ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
102
103
104 RgnDesc = ObjDesc->CommonField.RegionObj;
105
106 /* We must have a valid region */
107
108 if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
109 {
110 ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
111 RgnDesc->Common.Type,
112 AcpiUtGetObjectTypeName (RgnDesc)));
113
115 }
116
117 SpaceId = RgnDesc->Region.SpaceId;
118
119 /* Validate the Space ID */
120
122 {
124 "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId));
126 }
127
128 /*
129 * If the Region Address and Length have not been previously evaluated,
130 * evaluate them now and save the results.
131 */
132 if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
133 {
135 if (ACPI_FAILURE (Status))
136 {
138 }
139 }
140
141 /*
142 * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear
143 * address space and the request cannot be directly validated
144 */
148 {
149 /* SMBus or IPMI has a non-linear address space */
150
152 }
153
154#ifdef ACPI_UNDER_DEVELOPMENT
155 /*
156 * If the Field access is AnyAcc, we can now compute the optimal
157 * access (because we know the length of the parent region)
158 */
159 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
160 {
161 if (ACPI_FAILURE (Status))
162 {
164 }
165 }
166#endif
167
168 /*
169 * Validate the request. The entire request from the byte offset for a
170 * length of one field datum (access width) must fit within the region.
171 * (Region length is specified in bytes)
172 */
173 if (RgnDesc->Region.Length <
174 (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
175 ObjDesc->CommonField.AccessByteWidth))
176 {
177 if (AcpiGbl_EnableInterpreterSlack)
178 {
179 /*
180 * Slack mode only: We will go ahead and allow access to this
181 * field if it is within the region length rounded up to the next
182 * access width boundary. ACPI_SIZE cast for 64-bit compile.
183 */
184 if (ACPI_ROUND_UP (RgnDesc->Region.Length,
185 ObjDesc->CommonField.AccessByteWidth) >=
186 ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
187 ObjDesc->CommonField.AccessByteWidth +
188 FieldDatumByteOffset))
189 {
191 }
192 }
193
194 if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
195 {
196 /*
197 * This is the case where the AccessType (AccWord, etc.) is wider
198 * than the region itself. For example, a region of length one
199 * byte, and a field with Dword access specified.
200 */
202 "Field [%4.4s] access width (%u bytes) "
203 "too large for region [%4.4s] (length %u)",
204 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
205 ObjDesc->CommonField.AccessByteWidth,
206 AcpiUtGetNodeName (RgnDesc->Region.Node),
207 RgnDesc->Region.Length));
208 }
209
210 /*
211 * Offset rounded up to next multiple of field width
212 * exceeds region length, indicate an error
213 */
215 "Field [%4.4s] Base+Offset+Width %u+%u+%u "
216 "is beyond end of region [%4.4s] (length %u)",
217 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
218 ObjDesc->CommonField.BaseByteOffset,
219 FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
220 AcpiUtGetNodeName (RgnDesc->Region.Node),
221 RgnDesc->Region.Length));
222
224 }
225
227}
228
229
230/*******************************************************************************
231 *
232 * FUNCTION: AcpiExAccessRegion
233 *
234 * PARAMETERS: ObjDesc - Field to be read
235 * FieldDatumByteOffset - Byte offset of this datum within the
236 * parent field
237 * Value - Where to store value (must at least
238 * 64 bits)
239 * Function - Read or Write flag plus other region-
240 * dependent flags
241 *
242 * RETURN: Status
243 *
244 * DESCRIPTION: Read or Write a single field datum to an Operation Region.
245 *
246 ******************************************************************************/
247
250 ACPI_OPERAND_OBJECT *ObjDesc,
251 UINT32 FieldDatumByteOffset,
252 UINT64 *Value,
254{
256 ACPI_OPERAND_OBJECT *RgnDesc;
257 UINT32 RegionOffset;
258
259
260 ACPI_FUNCTION_TRACE (ExAccessRegion);
261
262
263 /*
264 * Ensure that the region operands are fully evaluated and verify
265 * the validity of the request
266 */
267 Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
268 if (ACPI_FAILURE (Status))
269 {
271 }
272
273 /*
274 * The physical address of this field datum is:
275 *
276 * 1) The base of the region, plus
277 * 2) The base offset of the field, plus
278 * 3) The current offset into the field
279 */
280 RgnDesc = ObjDesc->CommonField.RegionObj;
281 RegionOffset =
282 ObjDesc->CommonField.BaseByteOffset +
283 FieldDatumByteOffset;
284
286 {
287 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
288 }
289 else
290 {
291 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
292 }
293
295 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
297 RgnDesc->Region.SpaceId,
298 ObjDesc->CommonField.AccessByteWidth,
299 ObjDesc->CommonField.BaseByteOffset,
300 FieldDatumByteOffset,
301 ACPI_FORMAT_UINT64 (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 {
312 {
314 "Region %s (ID=%u) not implemented",
316 RgnDesc->Region.SpaceId));
317 }
318 else if (Status == AE_NOT_EXIST)
319 {
321 "Region %s (ID=%u) has no handler",
323 RgnDesc->Region.SpaceId));
324 }
325 }
326
328}
329
330
331/*******************************************************************************
332 *
333 * FUNCTION: AcpiExRegisterOverflow
334 *
335 * PARAMETERS: ObjDesc - Register(Field) to be written
336 * Value - Value to be stored
337 *
338 * RETURN: TRUE if value overflows the field, FALSE otherwise
339 *
340 * DESCRIPTION: Check if a value is out of range of the field being written.
341 * Used to check if the values written to Index and Bank registers
342 * are out of range. Normally, the value is simply truncated
343 * to fit the field, but this case is most likely a serious
344 * coding error in the ASL.
345 *
346 ******************************************************************************/
347
348static BOOLEAN
350 ACPI_OPERAND_OBJECT *ObjDesc,
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 */
370 "Index value 0x%8.8X%8.8X overflows field width 0x%X",
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
394 *
395 * DESCRIPTION: Read or Write a single datum of a field. The FieldType is
396 * demultiplexed here to handle the different types of fields
397 * (BufferField, RegionField, IndexField, BankField)
398 *
399 ******************************************************************************/
400
401static ACPI_STATUS
403 ACPI_OPERAND_OBJECT *ObjDesc,
404 UINT32 FieldDatumByteOffset,
405 UINT64 *Value,
407{
409 UINT64 LocalValue;
410
411
412 ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
413
414
415 if (ReadWrite == ACPI_READ)
416 {
417 if (!Value)
418 {
419 LocalValue = 0;
420
421 /* To support reads without saving return value */
422 Value = &LocalValue;
423 }
424
425 /* Clear the entire return buffer first, [Very Important!] */
426
427 *Value = 0;
428 }
429
430 /*
431 * The four types of fields are:
432 *
433 * BufferField - Read/write from/to a Buffer
434 * RegionField - Read/write from/to a Operation Region.
435 * BankField - Write to a Bank Register, then read/write from/to an
436 * OperationRegion
437 * IndexField - Write to an Index Register, then read/write from/to a
438 * Data Register
439 */
440 switch (ObjDesc->Common.Type)
441 {
443 /*
444 * If the BufferField arguments have not been previously evaluated,
445 * evaluate them now and save the results.
446 */
447 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
448 {
450 if (ACPI_FAILURE (Status))
451 {
453 }
454 }
455
456 if (ReadWrite == ACPI_READ)
457 {
458 /*
459 * Copy the data from the source buffer.
460 * Length is the field width in bytes.
461 */
462 memcpy (Value,
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 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
484 /*
485 * Ensure that the BankValue is not beyond the capacity of
486 * the register
487 */
489 (UINT64) ObjDesc->BankField.Value))
490 {
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 */
499 &ObjDesc->BankField.Value,
500 sizeof (ObjDesc->BankField.Value));
501 if (ACPI_FAILURE (Status))
502 {
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
512
514 /*
515 * For simple RegionFields, we just directly access the owning
516 * Operation Region.
517 */
519 ObjDesc, FieldDatumByteOffset, Value, ReadWrite);
520 break;
521
523 /*
524 * Ensure that the IndexValue is not beyond the capacity of
525 * the register
526 */
528 (UINT64) ObjDesc->IndexField.Value))
529 {
531 }
532
533 /* Write the index value to the IndexRegister (itself a RegionField) */
534
535 FieldDatumByteOffset += ObjDesc->IndexField.Value;
536
538 "Write to Index Register: Value %8.8X\n",
539 FieldDatumByteOffset));
540
542 &FieldDatumByteOffset, sizeof (FieldDatumByteOffset));
543 if (ACPI_FAILURE (Status))
544 {
546 }
547
548 if (ReadWrite == ACPI_READ)
549 {
550 /* Read the datum from the DataRegister */
551
553 "Read from Data Register\n"));
554
556 ObjDesc->IndexField.DataObj, Value, sizeof (UINT64));
557 }
558 else
559 {
560 /* Write the datum to the DataRegister */
561
563 "Write to Data Register: Value %8.8X%8.8X\n",
565
567 ObjDesc->IndexField.DataObj, Value, sizeof (UINT64));
568 }
569 break;
570
571 default:
572
573 ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
574 ObjDesc->Common.Type));
576 break;
577 }
578
579 if (ACPI_SUCCESS (Status))
580 {
581 if (ReadWrite == ACPI_READ)
582 {
584 "Value Read %8.8X%8.8X, Width %u\n",
586 ObjDesc->CommonField.AccessByteWidth));
587 }
588 else
589 {
591 "Value Written %8.8X%8.8X, Width %u\n",
593 ObjDesc->CommonField.AccessByteWidth));
594 }
595 }
596
598}
599
600
601/*******************************************************************************
602 *
603 * FUNCTION: AcpiExWriteWithUpdateRule
604 *
605 * PARAMETERS: ObjDesc - Field to be written
606 * Mask - bitmask within field datum
607 * FieldValue - Value to write
608 * FieldDatumByteOffset - Offset of datum within field
609 *
610 * RETURN: Status
611 *
612 * DESCRIPTION: Apply the field update rule to a field write
613 *
614 ******************************************************************************/
615
618 ACPI_OPERAND_OBJECT *ObjDesc,
619 UINT64 Mask,
620 UINT64 FieldValue,
621 UINT32 FieldDatumByteOffset)
622{
624 UINT64 MergedValue;
625 UINT64 CurrentValue;
626
627
628 ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
629
630
631 /* Start with the new bits */
632
633 MergedValue = FieldValue;
634
635 /* If the mask is all ones, we don't need to worry about the update rule */
636
637 if (Mask != ACPI_UINT64_MAX)
638 {
639 /* Decode the update rule */
640
641 switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
642 {
644 /*
645 * Check if update rule needs to be applied (not if mask is all
646 * ones) The left shift drops the bits we want to ignore.
647 */
648 if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
649 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
650 {
651 /*
652 * Read the current contents of the byte/word/dword containing
653 * the field, and merge with the new field value.
654 */
656 ObjDesc, FieldDatumByteOffset, &CurrentValue, ACPI_READ);
657 if (ACPI_FAILURE (Status))
658 {
660 }
661
662 MergedValue |= (CurrentValue & ~Mask);
663 }
664 break;
665
667
668 /* Set positions outside the field to all ones */
669
670 MergedValue |= ~Mask;
671 break;
672
674
675 /* Set positions outside the field to all zeros */
676
677 MergedValue &= Mask;
678 break;
679
680 default:
681
683 "Unknown UpdateRule value: 0x%X",
684 (ObjDesc->CommonField.FieldFlags &
687 }
688 }
689
691 "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
692 "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
694 FieldDatumByteOffset,
695 ObjDesc->CommonField.AccessByteWidth,
696 ACPI_FORMAT_UINT64 (FieldValue),
697 ACPI_FORMAT_UINT64 (MergedValue)));
698
699 /* Write the merged value */
700
702 ObjDesc, FieldDatumByteOffset, &MergedValue, ACPI_WRITE);
703
705}
706
707
708/*******************************************************************************
709 *
710 * FUNCTION: AcpiExExtractFromField
711 *
712 * PARAMETERS: ObjDesc - Field to be read
713 * Buffer - Where to store the field data
714 * BufferLength - Length of Buffer
715 *
716 * RETURN: Status
717 *
718 * DESCRIPTION: Retrieve the current value of the given field
719 *
720 ******************************************************************************/
721
724 ACPI_OPERAND_OBJECT *ObjDesc,
725 void *Buffer,
727{
729 UINT64 RawDatum;
730 UINT64 MergedDatum;
731 UINT32 FieldOffset = 0;
732 UINT32 BufferOffset = 0;
733 UINT32 BufferTailBits;
734 UINT32 DatumCount;
735 UINT32 FieldDatumCount;
736 UINT32 AccessBitWidth;
737 UINT32 i;
738
739
740 ACPI_FUNCTION_TRACE (ExExtractFromField);
741
742
743 /* Validate target buffer and clear it */
744
745 if (BufferLength <
746 ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
747 {
749 "Field size %u (bits) is too large for buffer (%u)",
750 ObjDesc->CommonField.BitLength, BufferLength));
751
753 }
754
756 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
757
758 /* Handle the simple case here */
759
760 if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
761 (ObjDesc->CommonField.BitLength == AccessBitWidth))
762 {
763 if (BufferLength >= sizeof (UINT64))
764 {
765 Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
766 }
767 else
768 {
769 /* Use RawDatum (UINT64) to handle buffers < 64 bits */
770
771 Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ);
772 memcpy (Buffer, &RawDatum, BufferLength);
773 }
774
776 }
777
778/* TBD: Move to common setup code */
779
780 /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
781
782 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
783 {
784 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
785 AccessBitWidth = sizeof (UINT64) * 8;
786 }
787
788 /* Compute the number of datums (access width data items) */
789
790 DatumCount = ACPI_ROUND_UP_TO (
791 ObjDesc->CommonField.BitLength, AccessBitWidth);
792
793 FieldDatumCount = ACPI_ROUND_UP_TO (
794 ObjDesc->CommonField.BitLength +
795 ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
796
797 /* Priming read from the field */
798
799 Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
800 if (ACPI_FAILURE (Status))
801 {
803 }
804 MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
805
806 /* Read the rest of the field */
807
808 for (i = 1; i < FieldDatumCount; i++)
809 {
810 /* Get next input datum from the field */
811
812 FieldOffset += ObjDesc->CommonField.AccessByteWidth;
814 ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
815 if (ACPI_FAILURE (Status))
816 {
818 }
819
820 /*
821 * Merge with previous datum if necessary.
822 *
823 * Note: Before the shift, check if the shift value will be larger than
824 * the integer size. If so, there is no need to perform the operation.
825 * This avoids the differences in behavior between different compilers
826 * concerning shift values larger than the target data width.
827 */
828 if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
830 {
831 MergedDatum |= RawDatum <<
832 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
833 }
834
835 if (i == DatumCount)
836 {
837 break;
838 }
839
840 /* Write merged datum to target buffer */
841
842 memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
843 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
844 BufferLength - BufferOffset));
845
846 BufferOffset += ObjDesc->CommonField.AccessByteWidth;
847 MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
848 }
849
850 /* Mask off any extra bits in the last datum */
851
852 BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
853 if (BufferTailBits)
854 {
855 MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
856 }
857
858 /* Write the last datum to the buffer */
859
860 memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
861 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
862 BufferLength - BufferOffset));
863
865}
866
867
868/*******************************************************************************
869 *
870 * FUNCTION: AcpiExInsertIntoField
871 *
872 * PARAMETERS: ObjDesc - Field to be written
873 * Buffer - Data to be written
874 * BufferLength - Length of Buffer
875 *
876 * RETURN: Status
877 *
878 * DESCRIPTION: Store the Buffer contents into the given field
879 *
880 ******************************************************************************/
881
884 ACPI_OPERAND_OBJECT *ObjDesc,
885 void *Buffer,
887{
888 void *NewBuffer;
890 UINT64 Mask;
891 UINT64 WidthMask;
892 UINT64 MergedDatum;
893 UINT64 RawDatum = 0;
894 UINT32 FieldOffset = 0;
895 UINT32 BufferOffset = 0;
896 UINT32 BufferTailBits;
897 UINT32 DatumCount;
898 UINT32 FieldDatumCount;
899 UINT32 AccessBitWidth;
901 UINT32 i;
902
903
904 ACPI_FUNCTION_TRACE (ExInsertIntoField);
905
906
907 /* Validate input buffer */
908
909 NewBuffer = NULL;
911 ObjDesc->CommonField.BitLength);
912
913 /*
914 * We must have a buffer that is at least as long as the field
915 * we are writing to. This is because individual fields are
916 * indivisible and partial writes are not supported -- as per
917 * the ACPI specification.
918 */
920 {
921 /* We need to create a new buffer */
922
924 if (!NewBuffer)
925 {
927 }
928
929 /*
930 * Copy the original data to the new buffer, starting
931 * at Byte zero. All unused (upper) bytes of the
932 * buffer will be 0.
933 */
934 memcpy ((char *) NewBuffer, (char *) Buffer, BufferLength);
935 Buffer = NewBuffer;
937 }
938
939/* TBD: Move to common setup code */
940
941 /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
942 if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
943 {
944 ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
945 }
946
947 AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
948
949 /* Create the bitmasks used for bit insertion */
950
951 WidthMask = ACPI_MASK_BITS_ABOVE_64 (AccessBitWidth);
952 Mask = WidthMask &
953 ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
954
955 /* Compute the number of datums (access width data items) */
956
957 DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
958 AccessBitWidth);
959
960 FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
961 ObjDesc->CommonField.StartFieldBitOffset,
962 AccessBitWidth);
963
964 /* Get initial Datum from the input buffer */
965
966 memcpy (&RawDatum, Buffer,
967 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
968 BufferLength - BufferOffset));
969
970 MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
971
972 /* Write the entire field */
973
974 for (i = 1; i < FieldDatumCount; i++)
975 {
976 /* Write merged datum to the target field */
977
978 MergedDatum &= Mask;
980 ObjDesc, Mask, MergedDatum, FieldOffset);
981 if (ACPI_FAILURE (Status))
982 {
983 goto Exit;
984 }
985
986 FieldOffset += ObjDesc->CommonField.AccessByteWidth;
987
988 /*
989 * Start new output datum by merging with previous input datum
990 * if necessary.
991 *
992 * Note: Before the shift, check if the shift value will be larger than
993 * the integer size. If so, there is no need to perform the operation.
994 * This avoids the differences in behavior between different compilers
995 * concerning shift values larger than the target data width.
996 */
997 if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
999 {
1000 MergedDatum = RawDatum >>
1001 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
1002 }
1003 else
1004 {
1005 MergedDatum = 0;
1006 }
1007
1008 Mask = WidthMask;
1009
1010 if (i == DatumCount)
1011 {
1012 break;
1013 }
1014
1015 /* Get the next input datum from the buffer */
1016
1017 BufferOffset += ObjDesc->CommonField.AccessByteWidth;
1018 memcpy (&RawDatum, ((char *) Buffer) + BufferOffset,
1019 ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1020 BufferLength - BufferOffset));
1021
1022 MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1023 }
1024
1025 /* Mask off any extra bits in the last datum */
1026
1027 BufferTailBits = (ObjDesc->CommonField.BitLength +
1028 ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
1029 if (BufferTailBits)
1030 {
1031 Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1032 }
1033
1034 /* Write the last datum to the field */
1035
1036 MergedDatum &= Mask;
1038 ObjDesc, Mask, MergedDatum, FieldOffset);
1039
1040Exit:
1041 /* Free temporary buffer if we used one */
1042
1043 if (NewBuffer)
1044 {
1045 ACPI_FREE (NewBuffer);
1046 }
1048}
unsigned char BOOLEAN
unsigned long long UINT64
unsigned char UINT8
unsigned int UINT32
#define AE_NOT_IMPLEMENTED
Definition: acexcep.h:122
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_AML_INTERNAL
Definition: acexcep.h:194
#define AE_BUFFER_OVERFLOW
Definition: acexcep.h:119
#define AE_AML_INVALID_SPACE_ID
Definition: acexcep.h:195
#define AE_AML_REGISTER_LIMIT
Definition: acexcep.h:204
#define AE_AML_OPERAND_VALUE
Definition: acexcep.h:183
#define AE_NO_MEMORY
Definition: acexcep.h:112
#define AE_NOT_EXIST
Definition: acexcep.h:114
#define AE_AML_OPERAND_TYPE
Definition: acexcep.h:182
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define AE_OK
Definition: acexcep.h:97
#define AE_AML_REGION_LIMIT
Definition: acexcep.h:188
#define ACPI_FORMAT_UINT64(i)
Definition: acmacros.h:71
#define ACPI_MUL_8(a)
Definition: acmacros.h:215
#define ACPI_MASK_BITS_ABOVE_64(width)
Definition: acmacros.h:348
#define ACPI_MASK_BITS_ABOVE(position)
Definition: acmacros.h:344
#define ACPI_ROUND_UP(value, boundary)
Definition: acmacros.h:242
#define ACPI_ROUND_UP_TO(value, boundary)
Definition: acmacros.h:263
#define ACPI_MASK_BITS_BELOW(position)
Definition: acmacros.h:345
#define ACPI_ROUND_BITS_UP_TO_BYTES(a)
Definition: acmacros.h:256
#define AOPOBJ_DATA_VALID
Definition: acobject.h:96
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
#define ACPI_FUNCTION_TRACE_U32(a, b)
Definition: acoutput.h:482
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_DB_BFIELD
Definition: acoutput.h:168
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
#define AE_INFO
Definition: acoutput.h:230
#define ACPI_DEBUG_PRINT_RAW(pl)
Definition: acoutput.h:476
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 ACPI_NOTIFY_HANDLER void *Context ACPI_ADR_SPACE_TYPE SpaceId
Definition: acpixf.h:832
#define ACPI_IO_MASK
Definition: actypes.h:753
#define ACPI_ADR_SPACE_IPMI
Definition: actypes.h:868
#define ACPI_TYPE_BUFFER_FIELD
Definition: actypes.h:701
#define ACPI_UINT64_MAX
Definition: actypes.h:67
#define ACPI_TYPE_LOCAL_BANK_FIELD
Definition: actypes.h:717
#define ACPI_READ
Definition: actypes.h:751
#define ACPI_TYPE_REGION
Definition: actypes.h:697
#define ACPI_FREE(a)
Definition: actypes.h:386
#define ACPI_TYPE_LOCAL_REGION_FIELD
Definition: actypes.h:716
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define ACPI_ADR_SPACE_GSBUS
Definition: actypes.h:870
#define ACPI_ADR_SPACE_SMBUS
Definition: actypes.h:865
#define ACPI_MIN(a, b)
Definition: actypes.h:535
#define ACPI_WRITE
Definition: actypes.h:752
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
#define ACPI_TYPE_LOCAL_INDEX_FIELD
Definition: actypes.h:718
#define ACPI_INTEGER_BIT_SIZE
Definition: actypes.h:490
#define ACPI_FALLTHROUGH
Definition: actypes.h:1466
const char * AcpiUtGetRegionName(UINT8 SpaceId)
Definition: utdecode.c:125
const char * AcpiUtGetNodeName(void *Object)
Definition: utdecode.c:306
const char * AcpiUtGetObjectTypeName(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: utdecode.c:264
#define AML_FIELD_UPDATE_RULE_MASK
Definition: amlcode.h:444
@ AML_FIELD_UPDATE_WRITE_AS_ONES
Definition: amlcode.h:476
@ AML_FIELD_UPDATE_WRITE_AS_ZEROS
Definition: amlcode.h:477
@ AML_FIELD_UPDATE_PRESERVE
Definition: amlcode.h:475
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
ACPI_STATUS AcpiDsGetRegionArguments(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsargs.c:395
ACPI_STATUS AcpiDsGetBufferFieldArguments(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsargs.c:196
ACPI_STATUS AcpiEvAddressSpaceDispatch(ACPI_OPERAND_OBJECT *RegionObj, ACPI_OPERAND_OBJECT *FieldObj, UINT32 Function, UINT32 RegionOffset, UINT32 BitWidth, UINT64 *Value)
Definition: evregion.c:150
static ACPI_STATUS AcpiExSetupRegion(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset)
Definition: exfldio.c:92
static ACPI_STATUS AcpiExFieldDatumIo(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 ReadWrite)
Definition: exfldio.c:402
ACPI_STATUS AcpiExExtractFromField(ACPI_OPERAND_OBJECT *ObjDesc, void *Buffer, UINT32 BufferLength)
Definition: exfldio.c:723
ACPI_STATUS AcpiExAccessRegion(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 Function)
Definition: exfldio.c:249
ACPI_STATUS AcpiExInsertIntoField(ACPI_OPERAND_OBJECT *ObjDesc, void *Buffer, UINT32 BufferLength)
Definition: exfldio.c:883
ACPI_STATUS AcpiExWriteWithUpdateRule(ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Mask, UINT64 FieldValue, UINT32 FieldDatumByteOffset)
Definition: exfldio.c:617
static BOOLEAN AcpiExRegisterOverflow(ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Value)
Definition: exfldio.c:349
BOOLEAN AcpiIsValidSpaceId(UINT8 SpaceId)
Definition: exutils.c:494
unsigned int Mask
Definition: fpcontrol.c:82
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
DRIVER_DISPATCH ReadWrite
Definition: readwrite.h:29
#define memset(x, y, z)
Definition: compat.h:39
static void Exit(void)
Definition: sock.c:1330
union acpi_operand_object * BankObj
Definition: acobject.h:359
union acpi_operand_object * BufferObj
Definition: acobject.h:386
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object * RegionObj
Definition: acobject.h:336
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object * IndexObj
Definition: acobject.h:373
union acpi_operand_object * DataObj
Definition: acobject.h:374
ACPI_NAMESPACE_NODE * Node
Definition: acobject.h:203
ACPI_OBJECT_COMMON_HEADER UINT8 SpaceId
Definition: acobject.h:202
ACPI_PHYSICAL_ADDRESS Address
Definition: acobject.h:206
ACPI_OBJECT_BANK_FIELD BankField
Definition: acobject.h:536
ACPI_OBJECT_BUFFER_FIELD BufferField
Definition: acobject.h:535
ACPI_OBJECT_REGION Region
Definition: acobject.h:527
ACPI_OBJECT_INDEX_FIELD IndexField
Definition: acobject.h:537
ACPI_OBJECT_COMMON Common
Definition: acobject.h:519
ACPI_OBJECT_FIELD_COMMON CommonField
Definition: acobject.h:533
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList