ReactOS 0.4.16-dev-91-g764881a
exfldio.c File Reference
#include "acpi.h"
#include "accommon.h"
#include "acinterp.h"
#include "amlcode.h"
#include "acevents.h"
#include "acdispat.h"
Include dependency graph for exfldio.c:

Go to the source code of this file.

Macros

#define _COMPONENT   ACPI_EXECUTER
 

Functions

static ACPI_STATUS AcpiExFieldDatumIo (ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 ReadWrite)
 
static BOOLEAN AcpiExRegisterOverflow (ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Value)
 
static ACPI_STATUS AcpiExSetupRegion (ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset)
 
ACPI_STATUS AcpiExAccessRegion (ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 Function)
 
ACPI_STATUS AcpiExWriteWithUpdateRule (ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Mask, UINT64 FieldValue, UINT32 FieldDatumByteOffset)
 
ACPI_STATUS AcpiExExtractFromField (ACPI_OPERAND_OBJECT *ObjDesc, void *Buffer, UINT32 BufferLength)
 
ACPI_STATUS AcpiExInsertIntoField (ACPI_OPERAND_OBJECT *ObjDesc, void *Buffer, UINT32 BufferLength)
 

Macro Definition Documentation

◆ _COMPONENT

#define _COMPONENT   ACPI_EXECUTER

Definition at line 52 of file exfldio.c.

Function Documentation

◆ AcpiExAccessRegion()

ACPI_STATUS AcpiExAccessRegion ( ACPI_OPERAND_OBJECT ObjDesc,
UINT32  FieldDatumByteOffset,
UINT64 Value,
UINT32  Function 
)

Definition at line 249 of file exfldio.c.

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}
unsigned int UINT32
#define AE_NOT_IMPLEMENTED
Definition: acexcep.h:122
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_NOT_EXIST
Definition: acexcep.h:114
#define ACPI_FORMAT_UINT64(i)
Definition: acmacros.h:71
#define ACPI_MUL_8(a)
Definition: acmacros.h:215
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#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
#define ACPI_IO_MASK
Definition: actypes.h:753
#define ACPI_READ
Definition: actypes.h:751
UINT32 ACPI_STATUS
Definition: actypes.h:460
const char * AcpiUtGetRegionName(UINT8 SpaceId)
Definition: utdecode.c:125
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
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
Status
Definition: gdiplustypes.h:25
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object * RegionObj
Definition: acobject.h:336
ACPI_OBJECT_COMMON_HEADER UINT8 SpaceId
Definition: acobject.h:202
ACPI_PHYSICAL_ADDRESS Address
Definition: acobject.h:206
ACPI_OBJECT_REGION Region
Definition: acobject.h:527
ACPI_OBJECT_FIELD_COMMON CommonField
Definition: acobject.h:533
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

Referenced by AcpiExFieldDatumIo(), AcpiExReadGpio(), AcpiExReadSerialBus(), AcpiExWriteDataToField(), AcpiExWriteGpio(), and AcpiExWriteSerialBus().

◆ AcpiExExtractFromField()

ACPI_STATUS AcpiExExtractFromField ( ACPI_OPERAND_OBJECT ObjDesc,
void Buffer,
UINT32  BufferLength 
)

Definition at line 723 of file exfldio.c.

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}
unsigned long long UINT64
#define AE_BUFFER_OVERFLOW
Definition: acexcep.h:119
#define AE_OK
Definition: acexcep.h:97
#define ACPI_MASK_BITS_ABOVE(position)
Definition: acmacros.h:344
#define ACPI_ROUND_UP_TO(value, boundary)
Definition: acmacros.h:263
#define ACPI_ROUND_BITS_UP_TO_BYTES(a)
Definition: acmacros.h:256
#define ACPI_MIN(a, b)
Definition: actypes.h:535
#define ACPI_INTEGER_BIT_SIZE
Definition: actypes.h:490
Definition: bufpool.h:45
static ACPI_STATUS AcpiExFieldDatumIo(ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset, UINT64 *Value, UINT32 ReadWrite)
Definition: exfldio.c:402
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
#define memset(x, y, z)
Definition: compat.h:39
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList

Referenced by AcpiExFieldDatumIo(), and AcpiExReadDataFromField().

◆ AcpiExFieldDatumIo()

static ACPI_STATUS AcpiExFieldDatumIo ( ACPI_OPERAND_OBJECT ObjDesc,
UINT32  FieldDatumByteOffset,
UINT64 Value,
UINT32  ReadWrite 
)
static

Definition at line 402 of file exfldio.c.

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}
#define AE_AML_INTERNAL
Definition: acexcep.h:194
#define AE_AML_REGISTER_LIMIT
Definition: acexcep.h:204
#define ACPI_SUCCESS(a)
Definition: acexcep.h:94
#define AOPOBJ_DATA_VALID
Definition: acobject.h:96
#define ACPI_FUNCTION_TRACE_U32(a, b)
Definition: acoutput.h:482
#define ACPI_TYPE_BUFFER_FIELD
Definition: actypes.h:701
#define ACPI_TYPE_LOCAL_BANK_FIELD
Definition: actypes.h:717
#define ACPI_TYPE_LOCAL_REGION_FIELD
Definition: actypes.h:716
#define ACPI_TYPE_LOCAL_INDEX_FIELD
Definition: actypes.h:718
#define ACPI_FALLTHROUGH
Definition: actypes.h:1466
ACPI_STATUS AcpiDsGetBufferFieldArguments(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsargs.c:196
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
static BOOLEAN AcpiExRegisterOverflow(ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Value)
Definition: exfldio.c:349
DRIVER_DISPATCH ReadWrite
Definition: readwrite.h:29
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 * IndexObj
Definition: acobject.h:373
union acpi_operand_object * DataObj
Definition: acobject.h:374
ACPI_OBJECT_BANK_FIELD BankField
Definition: acobject.h:536
ACPI_OBJECT_BUFFER_FIELD BufferField
Definition: acobject.h:535
ACPI_OBJECT_INDEX_FIELD IndexField
Definition: acobject.h:537
ACPI_OBJECT_COMMON Common
Definition: acobject.h:519

Referenced by AcpiExExtractFromField(), and AcpiExWriteWithUpdateRule().

◆ AcpiExInsertIntoField()

ACPI_STATUS AcpiExInsertIntoField ( ACPI_OPERAND_OBJECT ObjDesc,
void Buffer,
UINT32  BufferLength 
)

Definition at line 883 of file exfldio.c.

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}
#define AE_NO_MEMORY
Definition: acexcep.h:112
#define ACPI_MASK_BITS_ABOVE_64(width)
Definition: acmacros.h:348
#define ACPI_MASK_BITS_BELOW(position)
Definition: acmacros.h:345
#define ACPI_FREE(a)
Definition: actypes.h:386
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
#define NULL
Definition: types.h:112
ACPI_STATUS AcpiExWriteWithUpdateRule(ACPI_OPERAND_OBJECT *ObjDesc, UINT64 Mask, UINT64 FieldValue, UINT32 FieldDatumByteOffset)
Definition: exfldio.c:617
unsigned int Mask
Definition: fpcontrol.c:82
static void Exit(void)
Definition: sock.c:1330
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30

Referenced by AcpiExFieldDatumIo(), and AcpiExWriteDataToField().

◆ AcpiExRegisterOverflow()

static BOOLEAN AcpiExRegisterOverflow ( ACPI_OPERAND_OBJECT ObjDesc,
UINT64  Value 
)
static

Definition at line 349 of file exfldio.c.

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}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117

Referenced by AcpiExFieldDatumIo().

◆ AcpiExSetupRegion()

static ACPI_STATUS AcpiExSetupRegion ( ACPI_OPERAND_OBJECT ObjDesc,
UINT32  FieldDatumByteOffset 
)
static

Definition at line 92 of file exfldio.c.

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}
unsigned char UINT8
#define AE_AML_INVALID_SPACE_ID
Definition: acexcep.h:195
#define AE_AML_OPERAND_TYPE
Definition: acexcep.h:182
#define AE_AML_REGION_LIMIT
Definition: acexcep.h:188
#define ACPI_ROUND_UP(value, boundary)
Definition: acmacros.h:242
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_ADR_SPACE_IPMI
Definition: actypes.h:868
#define ACPI_TYPE_REGION
Definition: actypes.h:697
#define ACPI_ADR_SPACE_GSBUS
Definition: actypes.h:870
#define ACPI_ADR_SPACE_SMBUS
Definition: actypes.h:865
const char * AcpiUtGetNodeName(void *Object)
Definition: utdecode.c:306
const char * AcpiUtGetObjectTypeName(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: utdecode.c:264
ACPI_STATUS AcpiDsGetRegionArguments(ACPI_OPERAND_OBJECT *ObjDesc)
Definition: dsargs.c:395
BOOLEAN AcpiIsValidSpaceId(UINT8 SpaceId)
Definition: exutils.c:494
ACPI_NAMESPACE_NODE * Node
Definition: acobject.h:203

Referenced by AcpiExAccessRegion().

◆ AcpiExWriteWithUpdateRule()

ACPI_STATUS AcpiExWriteWithUpdateRule ( ACPI_OPERAND_OBJECT ObjDesc,
UINT64  Mask,
UINT64  FieldValue,
UINT32  FieldDatumByteOffset 
)

Definition at line 617 of file exfldio.c.

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}
#define AE_AML_OPERAND_VALUE
Definition: acexcep.h:183
#define ACPI_UINT64_MAX
Definition: actypes.h:67
#define ACPI_WRITE
Definition: actypes.h:752
#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

Referenced by AcpiExInsertIntoField().