Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exfldio - Aml Field I/O
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /******************************************************************************
  8.  *
  9.  * 1. Copyright Notice
  10.  *
  11.  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
  12.  * All rights reserved.
  13.  *
  14.  * 2. License
  15.  *
  16.  * 2.1. This is your license from Intel Corp. under its intellectual property
  17.  * rights.  You may have additional license terms from the party that provided
  18.  * you this software, covering your right to use that party's intellectual
  19.  * property rights.
  20.  *
  21.  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
  22.  * copy of the source code appearing in this file ("Covered Code") an
  23.  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
  24.  * base code distributed originally by Intel ("Original Intel Code") to copy,
  25.  * make derivatives, distribute, use and display any portion of the Covered
  26.  * Code in any form, with the right to sublicense such rights; and
  27.  *
  28.  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
  29.  * license (with the right to sublicense), under only those claims of Intel
  30.  * patents that are infringed by the Original Intel Code, to make, use, sell,
  31.  * offer to sell, and import the Covered Code and derivative works thereof
  32.  * solely to the minimum extent necessary to exercise the above copyright
  33.  * license, and in no event shall the patent license extend to any additions
  34.  * to or modifications of the Original Intel Code.  No other license or right
  35.  * is granted directly or by implication, estoppel or otherwise;
  36.  *
  37.  * The above copyright and patent license is granted only if the following
  38.  * conditions are met:
  39.  *
  40.  * 3. Conditions
  41.  *
  42.  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
  43.  * Redistribution of source code of any substantial portion of the Covered
  44.  * Code or modification with rights to further distribute source must include
  45.  * the above Copyright Notice, the above License, this list of Conditions,
  46.  * and the following Disclaimer and Export Compliance provision.  In addition,
  47.  * Licensee must cause all Covered Code to which Licensee contributes to
  48.  * contain a file documenting the changes Licensee made to create that Covered
  49.  * Code and the date of any change.  Licensee must include in that file the
  50.  * documentation of any changes made by any predecessor Licensee.  Licensee
  51.  * must include a prominent statement that the modification is derived,
  52.  * directly or indirectly, from Original Intel Code.
  53.  *
  54.  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
  55.  * Redistribution of source code of any substantial portion of the Covered
  56.  * Code or modification without rights to further distribute source must
  57.  * include the following Disclaimer and Export Compliance provision in the
  58.  * documentation and/or other materials provided with distribution.  In
  59.  * addition, Licensee may not authorize further sublicense of source of any
  60.  * portion of the Covered Code, and must include terms to the effect that the
  61.  * license from Licensee to its licensee is limited to the intellectual
  62.  * property embodied in the software Licensee provides to its licensee, and
  63.  * not to intellectual property embodied in modifications its licensee may
  64.  * make.
  65.  *
  66.  * 3.3. Redistribution of Executable. Redistribution in executable form of any
  67.  * substantial portion of the Covered Code or modification must reproduce the
  68.  * above Copyright Notice, and the following Disclaimer and Export Compliance
  69.  * provision in the documentation and/or other materials provided with the
  70.  * distribution.
  71.  *
  72.  * 3.4. Intel retains all right, title, and interest in and to the Original
  73.  * Intel Code.
  74.  *
  75.  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
  76.  * Intel shall be used in advertising or otherwise to promote the sale, use or
  77.  * other dealings in products derived from or relating to the Covered Code
  78.  * without prior written authorization from Intel.
  79.  *
  80.  * 4. Disclaimer and Export Compliance
  81.  *
  82.  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
  83.  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
  84.  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
  85.  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
  86.  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
  87.  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
  88.  * PARTICULAR PURPOSE.
  89.  *
  90.  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
  91.  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
  92.  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
  93.  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
  94.  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
  95.  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
  96.  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
  97.  * LIMITED REMEDY.
  98.  *
  99.  * 4.3. Licensee shall not export, either directly or indirectly, any of this
  100.  * software or system incorporating such software without first obtaining any
  101.  * required license or other approval from the U. S. Department of Commerce or
  102.  * any other agency or department of the United States Government.  In the
  103.  * event Licensee exports any such software from the United States or
  104.  * re-exports any such software from a foreign destination, Licensee shall
  105.  * ensure that the distribution and export/re-export of the software is in
  106.  * compliance with all laws, regulations, orders, or other restrictions of the
  107.  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
  108.  * any of its subsidiaries will export/re-export any technical data, process,
  109.  * software, or service, directly or indirectly, to any country for which the
  110.  * United States government or any agency thereof requires an export license,
  111.  * other governmental approval, or letter of assurance, without first obtaining
  112.  * such license, approval or letter.
  113.  *
  114.  *****************************************************************************/
  115.  
  116.  
  117. #define __EXFLDIO_C__
  118.  
  119. #include "acpi.h"
  120. #include "accommon.h"
  121. #include "acinterp.h"
  122. #include "amlcode.h"
  123. #include "acevents.h"
  124. #include "acdispat.h"
  125.  
  126.  
  127. #define _COMPONENT          ACPI_EXECUTER
  128.         ACPI_MODULE_NAME    ("exfldio")
  129.  
  130. /* Local prototypes */
  131.  
  132. static ACPI_STATUS
  133. AcpiExFieldDatumIo (
  134.     ACPI_OPERAND_OBJECT     *ObjDesc,
  135.     UINT32                  FieldDatumByteOffset,
  136.     UINT64                  *Value,
  137.     UINT32                  ReadWrite);
  138.  
  139. static BOOLEAN
  140. AcpiExRegisterOverflow (
  141.     ACPI_OPERAND_OBJECT     *ObjDesc,
  142.     UINT64                  Value);
  143.  
  144. static ACPI_STATUS
  145. AcpiExSetupRegion (
  146.     ACPI_OPERAND_OBJECT     *ObjDesc,
  147.     UINT32                  FieldDatumByteOffset);
  148.  
  149.  
  150. /*******************************************************************************
  151.  *
  152.  * FUNCTION:    AcpiExSetupRegion
  153.  *
  154.  * PARAMETERS:  ObjDesc                 - Field to be read or written
  155.  *              FieldDatumByteOffset    - Byte offset of this datum within the
  156.  *                                        parent field
  157.  *
  158.  * RETURN:      Status
  159.  *
  160.  * DESCRIPTION: Common processing for AcpiExExtractFromField and
  161.  *              AcpiExInsertIntoField.  Initialize the Region if necessary and
  162.  *              validate the request.
  163.  *
  164.  ******************************************************************************/
  165.  
  166. static ACPI_STATUS
  167. AcpiExSetupRegion (
  168.     ACPI_OPERAND_OBJECT     *ObjDesc,
  169.     UINT32                  FieldDatumByteOffset)
  170. {
  171.     ACPI_STATUS             Status = AE_OK;
  172.     ACPI_OPERAND_OBJECT     *RgnDesc;
  173.  
  174.  
  175.     ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
  176.  
  177.  
  178.     RgnDesc = ObjDesc->CommonField.RegionObj;
  179.  
  180.     /* We must have a valid region */
  181.  
  182.     if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
  183.     {
  184.         ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
  185.             RgnDesc->Common.Type,
  186.             AcpiUtGetObjectTypeName (RgnDesc)));
  187.  
  188.         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
  189.     }
  190.  
  191.     /*
  192.      * If the Region Address and Length have not been previously evaluated,
  193.      * evaluate them now and save the results.
  194.      */
  195.     if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
  196.     {
  197.         Status = AcpiDsGetRegionArguments (RgnDesc);
  198.         if (ACPI_FAILURE (Status))
  199.         {
  200.             return_ACPI_STATUS (Status);
  201.         }
  202.     }
  203.  
  204.     /*
  205.      * Exit now for SMBus or IPMI address space, it has a non-linear
  206.      * address space and the request cannot be directly validated
  207.      */
  208.     if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
  209.         RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
  210.     {
  211.         /* SMBus or IPMI has a non-linear address space */
  212.  
  213.         return_ACPI_STATUS (AE_OK);
  214.     }
  215.  
  216. #ifdef ACPI_UNDER_DEVELOPMENT
  217.     /*
  218.      * If the Field access is AnyAcc, we can now compute the optimal
  219.      * access (because we know know the length of the parent region)
  220.      */
  221.     if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
  222.     {
  223.         if (ACPI_FAILURE (Status))
  224.         {
  225.             return_ACPI_STATUS (Status);
  226.         }
  227.     }
  228. #endif
  229.  
  230.     /*
  231.      * Validate the request.  The entire request from the byte offset for a
  232.      * length of one field datum (access width) must fit within the region.
  233.      * (Region length is specified in bytes)
  234.      */
  235.     if (RgnDesc->Region.Length <
  236.             (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
  237.             ObjDesc->CommonField.AccessByteWidth))
  238.     {
  239.         if (AcpiGbl_EnableInterpreterSlack)
  240.         {
  241.             /*
  242.              * Slack mode only:  We will go ahead and allow access to this
  243.              * field if it is within the region length rounded up to the next
  244.              * access width boundary. ACPI_SIZE cast for 64-bit compile.
  245.              */
  246.             if (ACPI_ROUND_UP (RgnDesc->Region.Length,
  247.                     ObjDesc->CommonField.AccessByteWidth) >=
  248.                 ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
  249.                     ObjDesc->CommonField.AccessByteWidth +
  250.                     FieldDatumByteOffset))
  251.             {
  252.                 return_ACPI_STATUS (AE_OK);
  253.             }
  254.         }
  255.  
  256.         if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
  257.         {
  258.             /*
  259.              * This is the case where the AccessType (AccWord, etc.) is wider
  260.              * than the region itself.  For example, a region of length one
  261.              * byte, and a field with Dword access specified.
  262.              */
  263.             ACPI_ERROR ((AE_INFO,
  264.                 "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
  265.                 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
  266.                 ObjDesc->CommonField.AccessByteWidth,
  267.                 AcpiUtGetNodeName (RgnDesc->Region.Node),
  268.                 RgnDesc->Region.Length));
  269.         }
  270.  
  271.         /*
  272.          * Offset rounded up to next multiple of field width
  273.          * exceeds region length, indicate an error
  274.          */
  275.         ACPI_ERROR ((AE_INFO,
  276.             "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
  277.             AcpiUtGetNodeName (ObjDesc->CommonField.Node),
  278.             ObjDesc->CommonField.BaseByteOffset,
  279.             FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
  280.             AcpiUtGetNodeName (RgnDesc->Region.Node),
  281.             RgnDesc->Region.Length));
  282.  
  283.         return_ACPI_STATUS (AE_AML_REGION_LIMIT);
  284.     }
  285.  
  286.     return_ACPI_STATUS (AE_OK);
  287. }
  288.  
  289.  
  290. /*******************************************************************************
  291.  *
  292.  * FUNCTION:    AcpiExAccessRegion
  293.  *
  294.  * PARAMETERS:  ObjDesc                 - Field to be read
  295.  *              FieldDatumByteOffset    - Byte offset of this datum within the
  296.  *                                        parent field
  297.  *              Value                   - Where to store value (must at least
  298.  *                                        64 bits)
  299.  *              Function                - Read or Write flag plus other region-
  300.  *                                        dependent flags
  301.  *
  302.  * RETURN:      Status
  303.  *
  304.  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
  305.  *
  306.  ******************************************************************************/
  307.  
  308. ACPI_STATUS
  309. AcpiExAccessRegion (
  310.     ACPI_OPERAND_OBJECT     *ObjDesc,
  311.     UINT32                  FieldDatumByteOffset,
  312.     UINT64                  *Value,
  313.     UINT32                  Function)
  314. {
  315.     ACPI_STATUS             Status;
  316.     ACPI_OPERAND_OBJECT     *RgnDesc;
  317.     UINT32                  RegionOffset;
  318.  
  319.  
  320.     ACPI_FUNCTION_TRACE (ExAccessRegion);
  321.  
  322.  
  323.     /*
  324.      * Ensure that the region operands are fully evaluated and verify
  325.      * the validity of the request
  326.      */
  327.     Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
  328.     if (ACPI_FAILURE (Status))
  329.     {
  330.         return_ACPI_STATUS (Status);
  331.     }
  332.  
  333.     /*
  334.      * The physical address of this field datum is:
  335.      *
  336.      * 1) The base of the region, plus
  337.      * 2) The base offset of the field, plus
  338.      * 3) The current offset into the field
  339.      */
  340.     RgnDesc = ObjDesc->CommonField.RegionObj;
  341.     RegionOffset =
  342.         ObjDesc->CommonField.BaseByteOffset +
  343.         FieldDatumByteOffset;
  344.  
  345.     if ((Function & ACPI_IO_MASK) == ACPI_READ)
  346.     {
  347.         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
  348.     }
  349.     else
  350.     {
  351.         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
  352.     }
  353.  
  354.     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
  355.         " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
  356.         AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
  357.         RgnDesc->Region.SpaceId,
  358.         ObjDesc->CommonField.AccessByteWidth,
  359.         ObjDesc->CommonField.BaseByteOffset,
  360.         FieldDatumByteOffset,
  361.         ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
  362.  
  363.     /* Invoke the appropriate AddressSpace/OpRegion handler */
  364.  
  365.     Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, RegionOffset,
  366.                 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
  367.  
  368.     if (ACPI_FAILURE (Status))
  369.     {
  370.         if (Status == AE_NOT_IMPLEMENTED)
  371.         {
  372.             ACPI_ERROR ((AE_INFO,
  373.                 "Region %s(0x%X) not implemented",
  374.                 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
  375.                 RgnDesc->Region.SpaceId));
  376.         }
  377.         else if (Status == AE_NOT_EXIST)
  378.         {
  379.             ACPI_ERROR ((AE_INFO,
  380.                 "Region %s(0x%X) has no handler",
  381.                 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
  382.                 RgnDesc->Region.SpaceId));
  383.         }
  384.     }
  385.  
  386.     return_ACPI_STATUS (Status);
  387. }
  388.  
  389.  
  390. /*******************************************************************************
  391.  *
  392.  * FUNCTION:    AcpiExRegisterOverflow
  393.  *
  394.  * PARAMETERS:  ObjDesc                 - Register(Field) to be written
  395.  *              Value                   - Value to be stored
  396.  *
  397.  * RETURN:      TRUE if value overflows the field, FALSE otherwise
  398.  *
  399.  * DESCRIPTION: Check if a value is out of range of the field being written.
  400.  *              Used to check if the values written to Index and Bank registers
  401.  *              are out of range.  Normally, the value is simply truncated
  402.  *              to fit the field, but this case is most likely a serious
  403.  *              coding error in the ASL.
  404.  *
  405.  ******************************************************************************/
  406.  
  407. static BOOLEAN
  408. AcpiExRegisterOverflow (
  409.     ACPI_OPERAND_OBJECT     *ObjDesc,
  410.     UINT64                  Value)
  411. {
  412.  
  413.     if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
  414.     {
  415.         /*
  416.          * The field is large enough to hold the maximum integer, so we can
  417.          * never overflow it.
  418.          */
  419.         return (FALSE);
  420.     }
  421.  
  422.     if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
  423.     {
  424.         /*
  425.          * The Value is larger than the maximum value that can fit into
  426.          * the register.
  427.          */
  428.         return (TRUE);
  429.     }
  430.  
  431.     /* The Value will fit into the field with no truncation */
  432.  
  433.     return (FALSE);
  434. }
  435.  
  436.  
  437. /*******************************************************************************
  438.  *
  439.  * FUNCTION:    AcpiExFieldDatumIo
  440.  *
  441.  * PARAMETERS:  ObjDesc                 - Field to be read
  442.  *              FieldDatumByteOffset    - Byte offset of this datum within the
  443.  *                                        parent field
  444.  *              Value                   - Where to store value (must be 64 bits)
  445.  *              ReadWrite               - Read or Write flag
  446.  *
  447.  * RETURN:      Status
  448.  *
  449.  * DESCRIPTION: Read or Write a single datum of a field.  The FieldType is
  450.  *              demultiplexed here to handle the different types of fields
  451.  *              (BufferField, RegionField, IndexField, BankField)
  452.  *
  453.  ******************************************************************************/
  454.  
  455. static ACPI_STATUS
  456. AcpiExFieldDatumIo (
  457.     ACPI_OPERAND_OBJECT     *ObjDesc,
  458.     UINT32                  FieldDatumByteOffset,
  459.     UINT64                  *Value,
  460.     UINT32                  ReadWrite)
  461. {
  462.     ACPI_STATUS             Status;
  463.     UINT64                  LocalValue;
  464.  
  465.  
  466.     ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
  467.  
  468.  
  469.     if (ReadWrite == ACPI_READ)
  470.     {
  471.         if (!Value)
  472.         {
  473.             LocalValue = 0;
  474.  
  475.             /* To support reads without saving return value */
  476.             Value = &LocalValue;
  477.         }
  478.  
  479.         /* Clear the entire return buffer first, [Very Important!] */
  480.  
  481.         *Value = 0;
  482.     }
  483.  
  484.     /*
  485.      * The four types of fields are:
  486.      *
  487.      * BufferField - Read/write from/to a Buffer
  488.      * RegionField - Read/write from/to a Operation Region.
  489.      * BankField   - Write to a Bank Register, then read/write from/to an
  490.      *               OperationRegion
  491.      * IndexField  - Write to an Index Register, then read/write from/to a
  492.      *               Data Register
  493.      */
  494.     switch (ObjDesc->Common.Type)
  495.     {
  496.     case ACPI_TYPE_BUFFER_FIELD:
  497.         /*
  498.          * If the BufferField arguments have not been previously evaluated,
  499.          * evaluate them now and save the results.
  500.          */
  501.         if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
  502.         {
  503.             Status = AcpiDsGetBufferFieldArguments (ObjDesc);
  504.             if (ACPI_FAILURE (Status))
  505.             {
  506.                 return_ACPI_STATUS (Status);
  507.             }
  508.         }
  509.  
  510.         if (ReadWrite == ACPI_READ)
  511.         {
  512.             /*
  513.              * Copy the data from the source buffer.
  514.              * Length is the field width in bytes.
  515.              */
  516.             ACPI_MEMCPY (Value,
  517.                 (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
  518.                     ObjDesc->BufferField.BaseByteOffset +
  519.                     FieldDatumByteOffset,
  520.                 ObjDesc->CommonField.AccessByteWidth);
  521.         }
  522.         else
  523.         {
  524.             /*
  525.              * Copy the data to the target buffer.
  526.              * Length is the field width in bytes.
  527.              */
  528.             ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
  529.                 ObjDesc->BufferField.BaseByteOffset +
  530.                 FieldDatumByteOffset,
  531.                 Value, ObjDesc->CommonField.AccessByteWidth);
  532.         }
  533.  
  534.         Status = AE_OK;
  535.         break;
  536.  
  537.  
  538.     case ACPI_TYPE_LOCAL_BANK_FIELD:
  539.  
  540.         /*
  541.          * Ensure that the BankValue is not beyond the capacity of
  542.          * the register
  543.          */
  544.         if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
  545.                 (UINT64) ObjDesc->BankField.Value))
  546.         {
  547.             return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
  548.         }
  549.  
  550.         /*
  551.          * For BankFields, we must write the BankValue to the BankRegister
  552.          * (itself a RegionField) before we can access the data.
  553.          */
  554.         Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
  555.                     &ObjDesc->BankField.Value,
  556.                     sizeof (ObjDesc->BankField.Value));
  557.         if (ACPI_FAILURE (Status))
  558.         {
  559.             return_ACPI_STATUS (Status);
  560.         }
  561.  
  562.         /*
  563.          * Now that the Bank has been selected, fall through to the
  564.          * RegionField case and write the datum to the Operation Region
  565.          */
  566.  
  567.         /*lint -fallthrough */
  568.  
  569.  
  570.     case ACPI_TYPE_LOCAL_REGION_FIELD:
  571.         /*
  572.          * For simple RegionFields, we just directly access the owning
  573.          * Operation Region.
  574.          */
  575.         Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
  576.                     ReadWrite);
  577.         break;
  578.  
  579.  
  580.     case ACPI_TYPE_LOCAL_INDEX_FIELD:
  581.  
  582.  
  583.         /*
  584.          * Ensure that the IndexValue is not beyond the capacity of
  585.          * the register
  586.          */
  587.         if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
  588.                 (UINT64) ObjDesc->IndexField.Value))
  589.         {
  590.             return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
  591.         }
  592.  
  593.         /* Write the index value to the IndexRegister (itself a RegionField) */
  594.  
  595.         FieldDatumByteOffset += ObjDesc->IndexField.Value;
  596.  
  597.         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  598.             "Write to Index Register: Value %8.8X\n",
  599.             FieldDatumByteOffset));
  600.  
  601.         Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
  602.                     &FieldDatumByteOffset,
  603.                     sizeof (FieldDatumByteOffset));
  604.         if (ACPI_FAILURE (Status))
  605.         {
  606.             return_ACPI_STATUS (Status);
  607.         }
  608.  
  609.         if (ReadWrite == ACPI_READ)
  610.         {
  611.             /* Read the datum from the DataRegister */
  612.  
  613.             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  614.                 "Read from Data Register\n"));
  615.  
  616.             Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
  617.                         Value, sizeof (UINT64));
  618.         }
  619.         else
  620.         {
  621.             /* Write the datum to the DataRegister */
  622.  
  623.             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  624.                 "Write to Data Register: Value %8.8X%8.8X\n",
  625.                 ACPI_FORMAT_UINT64 (*Value)));
  626.  
  627.             Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
  628.                         Value, sizeof (UINT64));
  629.         }
  630.         break;
  631.  
  632.  
  633.     default:
  634.  
  635.         ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
  636.             ObjDesc->Common.Type));
  637.         Status = AE_AML_INTERNAL;
  638.         break;
  639.     }
  640.  
  641.     if (ACPI_SUCCESS (Status))
  642.     {
  643.         if (ReadWrite == ACPI_READ)
  644.         {
  645.             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  646.                 "Value Read %8.8X%8.8X, Width %u\n",
  647.                 ACPI_FORMAT_UINT64 (*Value),
  648.                 ObjDesc->CommonField.AccessByteWidth));
  649.         }
  650.         else
  651.         {
  652.             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  653.                 "Value Written %8.8X%8.8X, Width %u\n",
  654.                 ACPI_FORMAT_UINT64 (*Value),
  655.                 ObjDesc->CommonField.AccessByteWidth));
  656.         }
  657.     }
  658.  
  659.     return_ACPI_STATUS (Status);
  660. }
  661.  
  662.  
  663. /*******************************************************************************
  664.  *
  665.  * FUNCTION:    AcpiExWriteWithUpdateRule
  666.  *
  667.  * PARAMETERS:  ObjDesc                 - Field to be written
  668.  *              Mask                    - bitmask within field datum
  669.  *              FieldValue              - Value to write
  670.  *              FieldDatumByteOffset    - Offset of datum within field
  671.  *
  672.  * RETURN:      Status
  673.  *
  674.  * DESCRIPTION: Apply the field update rule to a field write
  675.  *
  676.  ******************************************************************************/
  677.  
  678. ACPI_STATUS
  679. AcpiExWriteWithUpdateRule (
  680.     ACPI_OPERAND_OBJECT     *ObjDesc,
  681.     UINT64                  Mask,
  682.     UINT64                  FieldValue,
  683.     UINT32                  FieldDatumByteOffset)
  684. {
  685.     ACPI_STATUS             Status = AE_OK;
  686.     UINT64                  MergedValue;
  687.     UINT64                  CurrentValue;
  688.  
  689.  
  690.     ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
  691.  
  692.  
  693.     /* Start with the new bits  */
  694.  
  695.     MergedValue = FieldValue;
  696.  
  697.     /* If the mask is all ones, we don't need to worry about the update rule */
  698.  
  699.     if (Mask != ACPI_UINT64_MAX)
  700.     {
  701.         /* Decode the update rule */
  702.  
  703.         switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
  704.         {
  705.         case AML_FIELD_UPDATE_PRESERVE:
  706.             /*
  707.              * Check if update rule needs to be applied (not if mask is all
  708.              * ones)  The left shift drops the bits we want to ignore.
  709.              */
  710.             if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
  711.                            ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
  712.             {
  713.                 /*
  714.                  * Read the current contents of the byte/word/dword containing
  715.                  * the field, and merge with the new field value.
  716.                  */
  717.                 Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
  718.                             &CurrentValue, ACPI_READ);
  719.                 if (ACPI_FAILURE (Status))
  720.                 {
  721.                     return_ACPI_STATUS (Status);
  722.                 }
  723.  
  724.                 MergedValue |= (CurrentValue & ~Mask);
  725.             }
  726.             break;
  727.  
  728.         case AML_FIELD_UPDATE_WRITE_AS_ONES:
  729.  
  730.             /* Set positions outside the field to all ones */
  731.  
  732.             MergedValue |= ~Mask;
  733.             break;
  734.  
  735.         case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
  736.  
  737.             /* Set positions outside the field to all zeros */
  738.  
  739.             MergedValue &= Mask;
  740.             break;
  741.  
  742.         default:
  743.  
  744.             ACPI_ERROR ((AE_INFO,
  745.                 "Unknown UpdateRule value: 0x%X",
  746.                 (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
  747.             return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
  748.         }
  749.     }
  750.  
  751.     ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
  752.         "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
  753.         ACPI_FORMAT_UINT64 (Mask),
  754.         FieldDatumByteOffset,
  755.         ObjDesc->CommonField.AccessByteWidth,
  756.         ACPI_FORMAT_UINT64 (FieldValue),
  757.         ACPI_FORMAT_UINT64 (MergedValue)));
  758.  
  759.     /* Write the merged value */
  760.  
  761.     Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
  762.                 &MergedValue, ACPI_WRITE);
  763.  
  764.     return_ACPI_STATUS (Status);
  765. }
  766.  
  767.  
  768. /*******************************************************************************
  769.  *
  770.  * FUNCTION:    AcpiExExtractFromField
  771.  *
  772.  * PARAMETERS:  ObjDesc             - Field to be read
  773.  *              Buffer              - Where to store the field data
  774.  *              BufferLength        - Length of Buffer
  775.  *
  776.  * RETURN:      Status
  777.  *
  778.  * DESCRIPTION: Retrieve the current value of the given field
  779.  *
  780.  ******************************************************************************/
  781.  
  782. ACPI_STATUS
  783. AcpiExExtractFromField (
  784.     ACPI_OPERAND_OBJECT     *ObjDesc,
  785.     void                    *Buffer,
  786.     UINT32                  BufferLength)
  787. {
  788.     ACPI_STATUS             Status;
  789.     UINT64                  RawDatum;
  790.     UINT64                  MergedDatum;
  791.     UINT32                  FieldOffset = 0;
  792.     UINT32                  BufferOffset = 0;
  793.     UINT32                  BufferTailBits;
  794.     UINT32                  DatumCount;
  795.     UINT32                  FieldDatumCount;
  796.     UINT32                  AccessBitWidth;
  797.     UINT32                  i;
  798.  
  799.  
  800.     ACPI_FUNCTION_TRACE (ExExtractFromField);
  801.  
  802.  
  803.     /* Validate target buffer and clear it */
  804.  
  805.     if (BufferLength <
  806.         ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
  807.     {
  808.         ACPI_ERROR ((AE_INFO,
  809.             "Field size %u (bits) is too large for buffer (%u)",
  810.             ObjDesc->CommonField.BitLength, BufferLength));
  811.  
  812.         return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
  813.     }
  814.  
  815.     ACPI_MEMSET (Buffer, 0, BufferLength);
  816.     AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
  817.  
  818.     /* Handle the simple case here */
  819.  
  820.     if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
  821.         (ObjDesc->CommonField.BitLength == AccessBitWidth))
  822.     {
  823.         Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
  824.         return_ACPI_STATUS (Status);
  825.     }
  826.  
  827. /* TBD: Move to common setup code */
  828.  
  829.     /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
  830.  
  831.     if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
  832.     {
  833.         ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
  834.         AccessBitWidth = sizeof (UINT64) * 8;
  835.     }
  836.  
  837.     /* Compute the number of datums (access width data items) */
  838.  
  839.     DatumCount = ACPI_ROUND_UP_TO (
  840.         ObjDesc->CommonField.BitLength, AccessBitWidth);
  841.  
  842.     FieldDatumCount = ACPI_ROUND_UP_TO (
  843.         ObjDesc->CommonField.BitLength +
  844.         ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
  845.  
  846.     /* Priming read from the field */
  847.  
  848.     Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
  849.     if (ACPI_FAILURE (Status))
  850.     {
  851.         return_ACPI_STATUS (Status);
  852.     }
  853.     MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
  854.  
  855.     /* Read the rest of the field */
  856.  
  857.     for (i = 1; i < FieldDatumCount; i++)
  858.     {
  859.         /* Get next input datum from the field */
  860.  
  861.         FieldOffset += ObjDesc->CommonField.AccessByteWidth;
  862.         Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
  863.                     &RawDatum, ACPI_READ);
  864.         if (ACPI_FAILURE (Status))
  865.         {
  866.             return_ACPI_STATUS (Status);
  867.         }
  868.  
  869.         /*
  870.          * Merge with previous datum if necessary.
  871.          *
  872.          * Note: Before the shift, check if the shift value will be larger than
  873.          * the integer size. If so, there is no need to perform the operation.
  874.          * This avoids the differences in behavior between different compilers
  875.          * concerning shift values larger than the target data width.
  876.          */
  877.         if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
  878.             ACPI_INTEGER_BIT_SIZE)
  879.         {
  880.             MergedDatum |= RawDatum <<
  881.                 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
  882.         }
  883.  
  884.         if (i == DatumCount)
  885.         {
  886.             break;
  887.         }
  888.  
  889.         /* Write merged datum to target buffer */
  890.  
  891.         ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
  892.             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
  893.                 BufferLength - BufferOffset));
  894.  
  895.         BufferOffset += ObjDesc->CommonField.AccessByteWidth;
  896.         MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
  897.     }
  898.  
  899.     /* Mask off any extra bits in the last datum */
  900.  
  901.     BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
  902.     if (BufferTailBits)
  903.     {
  904.         MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
  905.     }
  906.  
  907.     /* Write the last datum to the buffer */
  908.  
  909.     ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
  910.         ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
  911.             BufferLength - BufferOffset));
  912.  
  913.     return_ACPI_STATUS (AE_OK);
  914. }
  915.  
  916.  
  917. /*******************************************************************************
  918.  *
  919.  * FUNCTION:    AcpiExInsertIntoField
  920.  *
  921.  * PARAMETERS:  ObjDesc             - Field to be written
  922.  *              Buffer              - Data to be written
  923.  *              BufferLength        - Length of Buffer
  924.  *
  925.  * RETURN:      Status
  926.  *
  927.  * DESCRIPTION: Store the Buffer contents into the given field
  928.  *
  929.  ******************************************************************************/
  930.  
  931. ACPI_STATUS
  932. AcpiExInsertIntoField (
  933.     ACPI_OPERAND_OBJECT     *ObjDesc,
  934.     void                    *Buffer,
  935.     UINT32                  BufferLength)
  936. {
  937.     void                    *NewBuffer;
  938.     ACPI_STATUS             Status;
  939.     UINT64                  Mask;
  940.     UINT64                  WidthMask;
  941.     UINT64                  MergedDatum;
  942.     UINT64                  RawDatum = 0;
  943.     UINT32                  FieldOffset = 0;
  944.     UINT32                  BufferOffset = 0;
  945.     UINT32                  BufferTailBits;
  946.     UINT32                  DatumCount;
  947.     UINT32                  FieldDatumCount;
  948.     UINT32                  AccessBitWidth;
  949.     UINT32                  RequiredLength;
  950.     UINT32                  i;
  951.  
  952.  
  953.     ACPI_FUNCTION_TRACE (ExInsertIntoField);
  954.  
  955.  
  956.     /* Validate input buffer */
  957.  
  958.     NewBuffer = NULL;
  959.     RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
  960.                         ObjDesc->CommonField.BitLength);
  961.     /*
  962.      * We must have a buffer that is at least as long as the field
  963.      * we are writing to.  This is because individual fields are
  964.      * indivisible and partial writes are not supported -- as per
  965.      * the ACPI specification.
  966.      */
  967.     if (BufferLength < RequiredLength)
  968.     {
  969.         /* We need to create a new buffer */
  970.  
  971.         NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
  972.         if (!NewBuffer)
  973.         {
  974.             return_ACPI_STATUS (AE_NO_MEMORY);
  975.         }
  976.  
  977.         /*
  978.          * Copy the original data to the new buffer, starting
  979.          * at Byte zero.  All unused (upper) bytes of the
  980.          * buffer will be 0.
  981.          */
  982.         ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength);
  983.         Buffer = NewBuffer;
  984.         BufferLength = RequiredLength;
  985.     }
  986.  
  987. /* TBD: Move to common setup code */
  988.  
  989.     /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
  990.     if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
  991.     {
  992.         ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
  993.     }
  994.  
  995.     AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
  996.  
  997.     /*
  998.      * Create the bitmasks used for bit insertion.
  999.      * Note: This if/else is used to bypass compiler differences with the
  1000.      * shift operator
  1001.      */
  1002.     if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE)
  1003.     {
  1004.         WidthMask = ACPI_UINT64_MAX;
  1005.     }
  1006.     else
  1007.     {
  1008.         WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth);
  1009.     }
  1010.  
  1011.     Mask = WidthMask &
  1012.         ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
  1013.  
  1014.     /* Compute the number of datums (access width data items) */
  1015.  
  1016.     DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
  1017.         AccessBitWidth);
  1018.  
  1019.     FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
  1020.         ObjDesc->CommonField.StartFieldBitOffset,
  1021.         AccessBitWidth);
  1022.  
  1023.     /* Get initial Datum from the input buffer */
  1024.  
  1025.     ACPI_MEMCPY (&RawDatum, Buffer,
  1026.         ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
  1027.             BufferLength - BufferOffset));
  1028.  
  1029.     MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
  1030.  
  1031.     /* Write the entire field */
  1032.  
  1033.     for (i = 1; i < FieldDatumCount; i++)
  1034.     {
  1035.         /* Write merged datum to the target field */
  1036.  
  1037.         MergedDatum &= Mask;
  1038.         Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask,
  1039.                     MergedDatum, FieldOffset);
  1040.         if (ACPI_FAILURE (Status))
  1041.         {
  1042.             goto Exit;
  1043.         }
  1044.  
  1045.         FieldOffset += ObjDesc->CommonField.AccessByteWidth;
  1046.  
  1047.         /*
  1048.          * Start new output datum by merging with previous input datum
  1049.          * if necessary.
  1050.          *
  1051.          * Note: Before the shift, check if the shift value will be larger than
  1052.          * the integer size. If so, there is no need to perform the operation.
  1053.          * This avoids the differences in behavior between different compilers
  1054.          * concerning shift values larger than the target data width.
  1055.          */
  1056.         if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
  1057.             ACPI_INTEGER_BIT_SIZE)
  1058.         {
  1059.             MergedDatum = RawDatum >>
  1060.                 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
  1061.         }
  1062.         else
  1063.         {
  1064.             MergedDatum = 0;
  1065.         }
  1066.  
  1067.         Mask = WidthMask;
  1068.  
  1069.         if (i == DatumCount)
  1070.         {
  1071.             break;
  1072.         }
  1073.  
  1074.         /* Get the next input datum from the buffer */
  1075.  
  1076.         BufferOffset += ObjDesc->CommonField.AccessByteWidth;
  1077.         ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset,
  1078.             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
  1079.                  BufferLength - BufferOffset));
  1080.  
  1081.         MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
  1082.     }
  1083.  
  1084.     /* Mask off any extra bits in the last datum */
  1085.  
  1086.     BufferTailBits = (ObjDesc->CommonField.BitLength +
  1087.         ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
  1088.     if (BufferTailBits)
  1089.     {
  1090.         Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
  1091.     }
  1092.  
  1093.     /* Write the last datum to the field */
  1094.  
  1095.     MergedDatum &= Mask;
  1096.     Status = AcpiExWriteWithUpdateRule (ObjDesc,
  1097.                 Mask, MergedDatum, FieldOffset);
  1098.  
  1099. Exit:
  1100.     /* Free temporary buffer if we used one */
  1101.  
  1102.     if (NewBuffer)
  1103.     {
  1104.         ACPI_FREE (NewBuffer);
  1105.     }
  1106.     return_ACPI_STATUS (Status);
  1107. }
  1108.  
  1109.  
  1110.