ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

exfldio.c
Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * Module Name: exfldio - Aml Field I/O
00004  *
00005  *****************************************************************************/
00006 
00007 /******************************************************************************
00008  *
00009  * 1. Copyright Notice
00010  *
00011  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
00012  * All rights reserved.
00013  *
00014  * 2. License
00015  *
00016  * 2.1. This is your license from Intel Corp. under its intellectual property
00017  * rights.  You may have additional license terms from the party that provided
00018  * you this software, covering your right to use that party's intellectual
00019  * property rights.
00020  *
00021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
00022  * copy of the source code appearing in this file ("Covered Code") an
00023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
00024  * base code distributed originally by Intel ("Original Intel Code") to copy,
00025  * make derivatives, distribute, use and display any portion of the Covered
00026  * Code in any form, with the right to sublicense such rights; and
00027  *
00028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
00029  * license (with the right to sublicense), under only those claims of Intel
00030  * patents that are infringed by the Original Intel Code, to make, use, sell,
00031  * offer to sell, and import the Covered Code and derivative works thereof
00032  * solely to the minimum extent necessary to exercise the above copyright
00033  * license, and in no event shall the patent license extend to any additions
00034  * to or modifications of the Original Intel Code.  No other license or right
00035  * is granted directly or by implication, estoppel or otherwise;
00036  *
00037  * The above copyright and patent license is granted only if the following
00038  * conditions are met:
00039  *
00040  * 3. Conditions
00041  *
00042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
00043  * Redistribution of source code of any substantial portion of the Covered
00044  * Code or modification with rights to further distribute source must include
00045  * the above Copyright Notice, the above License, this list of Conditions,
00046  * and the following Disclaimer and Export Compliance provision.  In addition,
00047  * Licensee must cause all Covered Code to which Licensee contributes to
00048  * contain a file documenting the changes Licensee made to create that Covered
00049  * Code and the date of any change.  Licensee must include in that file the
00050  * documentation of any changes made by any predecessor Licensee.  Licensee
00051  * must include a prominent statement that the modification is derived,
00052  * directly or indirectly, from Original Intel Code.
00053  *
00054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
00055  * Redistribution of source code of any substantial portion of the Covered
00056  * Code or modification without rights to further distribute source must
00057  * include the following Disclaimer and Export Compliance provision in the
00058  * documentation and/or other materials provided with distribution.  In
00059  * addition, Licensee may not authorize further sublicense of source of any
00060  * portion of the Covered Code, and must include terms to the effect that the
00061  * license from Licensee to its licensee is limited to the intellectual
00062  * property embodied in the software Licensee provides to its licensee, and
00063  * not to intellectual property embodied in modifications its licensee may
00064  * make.
00065  *
00066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
00067  * substantial portion of the Covered Code or modification must reproduce the
00068  * above Copyright Notice, and the following Disclaimer and Export Compliance
00069  * provision in the documentation and/or other materials provided with the
00070  * distribution.
00071  *
00072  * 3.4. Intel retains all right, title, and interest in and to the Original
00073  * Intel Code.
00074  *
00075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
00076  * Intel shall be used in advertising or otherwise to promote the sale, use or
00077  * other dealings in products derived from or relating to the Covered Code
00078  * without prior written authorization from Intel.
00079  *
00080  * 4. Disclaimer and Export Compliance
00081  *
00082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
00083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
00084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
00085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
00086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
00087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
00088  * PARTICULAR PURPOSE.
00089  *
00090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
00091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
00092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
00093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
00094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
00095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
00096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
00097  * LIMITED REMEDY.
00098  *
00099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
00100  * software or system incorporating such software without first obtaining any
00101  * required license or other approval from the U. S. Department of Commerce or
00102  * any other agency or department of the United States Government.  In the
00103  * event Licensee exports any such software from the United States or
00104  * re-exports any such software from a foreign destination, Licensee shall
00105  * ensure that the distribution and export/re-export of the software is in
00106  * compliance with all laws, regulations, orders, or other restrictions of the
00107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
00108  * any of its subsidiaries will export/re-export any technical data, process,
00109  * software, or service, directly or indirectly, to any country for which the
00110  * United States government or any agency thereof requires an export license,
00111  * other governmental approval, or letter of assurance, without first obtaining
00112  * such license, approval or letter.
00113  *
00114  *****************************************************************************/
00115 
00116 
00117 #define __EXFLDIO_C__
00118 
00119 #include "acpi.h"
00120 #include "accommon.h"
00121 #include "acinterp.h"
00122 #include "amlcode.h"
00123 #include "acevents.h"
00124 #include "acdispat.h"
00125 
00126 
00127 #define _COMPONENT          ACPI_EXECUTER
00128         ACPI_MODULE_NAME    ("exfldio")
00129 
00130 /* Local prototypes */
00131 
00132 static ACPI_STATUS
00133 AcpiExFieldDatumIo (
00134     ACPI_OPERAND_OBJECT     *ObjDesc,
00135     UINT32                  FieldDatumByteOffset,
00136     UINT64                  *Value,
00137     UINT32                  ReadWrite);
00138 
00139 static BOOLEAN
00140 AcpiExRegisterOverflow (
00141     ACPI_OPERAND_OBJECT     *ObjDesc,
00142     UINT64                  Value);
00143 
00144 static ACPI_STATUS
00145 AcpiExSetupRegion (
00146     ACPI_OPERAND_OBJECT     *ObjDesc,
00147     UINT32                  FieldDatumByteOffset);
00148 
00149 
00150 /*******************************************************************************
00151  *
00152  * FUNCTION:    AcpiExSetupRegion
00153  *
00154  * PARAMETERS:  ObjDesc                 - Field to be read or written
00155  *              FieldDatumByteOffset    - Byte offset of this datum within the
00156  *                                        parent field
00157  *
00158  * RETURN:      Status
00159  *
00160  * DESCRIPTION: Common processing for AcpiExExtractFromField and
00161  *              AcpiExInsertIntoField.  Initialize the Region if necessary and
00162  *              validate the request.
00163  *
00164  ******************************************************************************/
00165 
00166 static ACPI_STATUS
00167 AcpiExSetupRegion (
00168     ACPI_OPERAND_OBJECT     *ObjDesc,
00169     UINT32                  FieldDatumByteOffset)
00170 {
00171     ACPI_STATUS             Status = AE_OK;
00172     ACPI_OPERAND_OBJECT     *RgnDesc;
00173 
00174 
00175     ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
00176 
00177 
00178     RgnDesc = ObjDesc->CommonField.RegionObj;
00179 
00180     /* We must have a valid region */
00181 
00182     if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
00183     {
00184         ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
00185             RgnDesc->Common.Type,
00186             AcpiUtGetObjectTypeName (RgnDesc)));
00187 
00188         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
00189     }
00190 
00191     /*
00192      * If the Region Address and Length have not been previously evaluated,
00193      * evaluate them now and save the results.
00194      */
00195     if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
00196     {
00197         Status = AcpiDsGetRegionArguments (RgnDesc);
00198         if (ACPI_FAILURE (Status))
00199         {
00200             return_ACPI_STATUS (Status);
00201         }
00202     }
00203 
00204     /*
00205      * Exit now for SMBus or IPMI address space, it has a non-linear
00206      * address space and the request cannot be directly validated
00207      */
00208     if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
00209         RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
00210     {
00211         /* SMBus or IPMI has a non-linear address space */
00212 
00213         return_ACPI_STATUS (AE_OK);
00214     }
00215 
00216 #ifdef ACPI_UNDER_DEVELOPMENT
00217     /*
00218      * If the Field access is AnyAcc, we can now compute the optimal
00219      * access (because we know know the length of the parent region)
00220      */
00221     if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
00222     {
00223         if (ACPI_FAILURE (Status))
00224         {
00225             return_ACPI_STATUS (Status);
00226         }
00227     }
00228 #endif
00229 
00230     /*
00231      * Validate the request.  The entire request from the byte offset for a
00232      * length of one field datum (access width) must fit within the region.
00233      * (Region length is specified in bytes)
00234      */
00235     if (RgnDesc->Region.Length <
00236             (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
00237             ObjDesc->CommonField.AccessByteWidth))
00238     {
00239         if (AcpiGbl_EnableInterpreterSlack)
00240         {
00241             /*
00242              * Slack mode only:  We will go ahead and allow access to this
00243              * field if it is within the region length rounded up to the next
00244              * access width boundary. ACPI_SIZE cast for 64-bit compile.
00245              */
00246             if (ACPI_ROUND_UP (RgnDesc->Region.Length,
00247                     ObjDesc->CommonField.AccessByteWidth) >=
00248                 ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
00249                     ObjDesc->CommonField.AccessByteWidth +
00250                     FieldDatumByteOffset))
00251             {
00252                 return_ACPI_STATUS (AE_OK);
00253             }
00254         }
00255 
00256         if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
00257         {
00258             /*
00259              * This is the case where the AccessType (AccWord, etc.) is wider
00260              * than the region itself.  For example, a region of length one
00261              * byte, and a field with Dword access specified.
00262              */
00263             ACPI_ERROR ((AE_INFO,
00264                 "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
00265                 AcpiUtGetNodeName (ObjDesc->CommonField.Node),
00266                 ObjDesc->CommonField.AccessByteWidth,
00267                 AcpiUtGetNodeName (RgnDesc->Region.Node),
00268                 RgnDesc->Region.Length));
00269         }
00270 
00271         /*
00272          * Offset rounded up to next multiple of field width
00273          * exceeds region length, indicate an error
00274          */
00275         ACPI_ERROR ((AE_INFO,
00276             "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
00277             AcpiUtGetNodeName (ObjDesc->CommonField.Node),
00278             ObjDesc->CommonField.BaseByteOffset,
00279             FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
00280             AcpiUtGetNodeName (RgnDesc->Region.Node),
00281             RgnDesc->Region.Length));
00282 
00283         return_ACPI_STATUS (AE_AML_REGION_LIMIT);
00284     }
00285 
00286     return_ACPI_STATUS (AE_OK);
00287 }
00288 
00289 
00290 /*******************************************************************************
00291  *
00292  * FUNCTION:    AcpiExAccessRegion
00293  *
00294  * PARAMETERS:  ObjDesc                 - Field to be read
00295  *              FieldDatumByteOffset    - Byte offset of this datum within the
00296  *                                        parent field
00297  *              Value                   - Where to store value (must at least
00298  *                                        64 bits)
00299  *              Function                - Read or Write flag plus other region-
00300  *                                        dependent flags
00301  *
00302  * RETURN:      Status
00303  *
00304  * DESCRIPTION: Read or Write a single field datum to an Operation Region.
00305  *
00306  ******************************************************************************/
00307 
00308 ACPI_STATUS
00309 AcpiExAccessRegion (
00310     ACPI_OPERAND_OBJECT     *ObjDesc,
00311     UINT32                  FieldDatumByteOffset,
00312     UINT64                  *Value,
00313     UINT32                  Function)
00314 {
00315     ACPI_STATUS             Status;
00316     ACPI_OPERAND_OBJECT     *RgnDesc;
00317     UINT32                  RegionOffset;
00318 
00319 
00320     ACPI_FUNCTION_TRACE (ExAccessRegion);
00321 
00322 
00323     /*
00324      * Ensure that the region operands are fully evaluated and verify
00325      * the validity of the request
00326      */
00327     Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
00328     if (ACPI_FAILURE (Status))
00329     {
00330         return_ACPI_STATUS (Status);
00331     }
00332 
00333     /*
00334      * The physical address of this field datum is:
00335      *
00336      * 1) The base of the region, plus
00337      * 2) The base offset of the field, plus
00338      * 3) The current offset into the field
00339      */
00340     RgnDesc = ObjDesc->CommonField.RegionObj;
00341     RegionOffset =
00342         ObjDesc->CommonField.BaseByteOffset +
00343         FieldDatumByteOffset;
00344 
00345     if ((Function & ACPI_IO_MASK) == ACPI_READ)
00346     {
00347         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
00348     }
00349     else
00350     {
00351         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
00352     }
00353 
00354     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
00355         " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
00356         AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
00357         RgnDesc->Region.SpaceId,
00358         ObjDesc->CommonField.AccessByteWidth,
00359         ObjDesc->CommonField.BaseByteOffset,
00360         FieldDatumByteOffset,
00361         ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
00362 
00363     /* Invoke the appropriate AddressSpace/OpRegion handler */
00364 
00365     Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, RegionOffset,
00366                 ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
00367 
00368     if (ACPI_FAILURE (Status))
00369     {
00370         if (Status == AE_NOT_IMPLEMENTED)
00371         {
00372             ACPI_ERROR ((AE_INFO,
00373                 "Region %s (ID=%u) not implemented",
00374                 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
00375                 RgnDesc->Region.SpaceId));
00376         }
00377         else if (Status == AE_NOT_EXIST)
00378         {
00379             ACPI_ERROR ((AE_INFO,
00380                 "Region %s (ID=%u) has no handler",
00381                 AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
00382                 RgnDesc->Region.SpaceId));
00383         }
00384     }
00385 
00386     return_ACPI_STATUS (Status);
00387 }
00388 
00389 
00390 /*******************************************************************************
00391  *
00392  * FUNCTION:    AcpiExRegisterOverflow
00393  *
00394  * PARAMETERS:  ObjDesc                 - Register(Field) to be written
00395  *              Value                   - Value to be stored
00396  *
00397  * RETURN:      TRUE if value overflows the field, FALSE otherwise
00398  *
00399  * DESCRIPTION: Check if a value is out of range of the field being written.
00400  *              Used to check if the values written to Index and Bank registers
00401  *              are out of range.  Normally, the value is simply truncated
00402  *              to fit the field, but this case is most likely a serious
00403  *              coding error in the ASL.
00404  *
00405  ******************************************************************************/
00406 
00407 static BOOLEAN
00408 AcpiExRegisterOverflow (
00409     ACPI_OPERAND_OBJECT     *ObjDesc,
00410     UINT64                  Value)
00411 {
00412 
00413     if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
00414     {
00415         /*
00416          * The field is large enough to hold the maximum integer, so we can
00417          * never overflow it.
00418          */
00419         return (FALSE);
00420     }
00421 
00422     if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
00423     {
00424         /*
00425          * The Value is larger than the maximum value that can fit into
00426          * the register.
00427          */
00428         return (TRUE);
00429     }
00430 
00431     /* The Value will fit into the field with no truncation */
00432 
00433     return (FALSE);
00434 }
00435 
00436 
00437 /*******************************************************************************
00438  *
00439  * FUNCTION:    AcpiExFieldDatumIo
00440  *
00441  * PARAMETERS:  ObjDesc                 - Field to be read
00442  *              FieldDatumByteOffset    - Byte offset of this datum within the
00443  *                                        parent field
00444  *              Value                   - Where to store value (must be 64 bits)
00445  *              ReadWrite               - Read or Write flag
00446  *
00447  * RETURN:      Status
00448  *
00449  * DESCRIPTION: Read or Write a single datum of a field.  The FieldType is
00450  *              demultiplexed here to handle the different types of fields
00451  *              (BufferField, RegionField, IndexField, BankField)
00452  *
00453  ******************************************************************************/
00454 
00455 static ACPI_STATUS
00456 AcpiExFieldDatumIo (
00457     ACPI_OPERAND_OBJECT     *ObjDesc,
00458     UINT32                  FieldDatumByteOffset,
00459     UINT64                  *Value,
00460     UINT32                  ReadWrite)
00461 {
00462     ACPI_STATUS             Status;
00463     UINT64                  LocalValue;
00464 
00465 
00466     ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
00467 
00468 
00469     if (ReadWrite == ACPI_READ)
00470     {
00471         if (!Value)
00472         {
00473             LocalValue = 0;
00474 
00475             /* To support reads without saving return value */
00476             Value = &LocalValue;
00477         }
00478 
00479         /* Clear the entire return buffer first, [Very Important!] */
00480 
00481         *Value = 0;
00482     }
00483 
00484     /*
00485      * The four types of fields are:
00486      *
00487      * BufferField - Read/write from/to a Buffer
00488      * RegionField - Read/write from/to a Operation Region.
00489      * BankField   - Write to a Bank Register, then read/write from/to an
00490      *               OperationRegion
00491      * IndexField  - Write to an Index Register, then read/write from/to a
00492      *               Data Register
00493      */
00494     switch (ObjDesc->Common.Type)
00495     {
00496     case ACPI_TYPE_BUFFER_FIELD:
00497         /*
00498          * If the BufferField arguments have not been previously evaluated,
00499          * evaluate them now and save the results.
00500          */
00501         if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
00502         {
00503             Status = AcpiDsGetBufferFieldArguments (ObjDesc);
00504             if (ACPI_FAILURE (Status))
00505             {
00506                 return_ACPI_STATUS (Status);
00507             }
00508         }
00509 
00510         if (ReadWrite == ACPI_READ)
00511         {
00512             /*
00513              * Copy the data from the source buffer.
00514              * Length is the field width in bytes.
00515              */
00516             ACPI_MEMCPY (Value,
00517                 (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
00518                     ObjDesc->BufferField.BaseByteOffset +
00519                     FieldDatumByteOffset,
00520                 ObjDesc->CommonField.AccessByteWidth);
00521         }
00522         else
00523         {
00524             /*
00525              * Copy the data to the target buffer.
00526              * Length is the field width in bytes.
00527              */
00528             ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
00529                 ObjDesc->BufferField.BaseByteOffset +
00530                 FieldDatumByteOffset,
00531                 Value, ObjDesc->CommonField.AccessByteWidth);
00532         }
00533 
00534         Status = AE_OK;
00535         break;
00536 
00537 
00538     case ACPI_TYPE_LOCAL_BANK_FIELD:
00539 
00540         /*
00541          * Ensure that the BankValue is not beyond the capacity of
00542          * the register
00543          */
00544         if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
00545                 (UINT64) ObjDesc->BankField.Value))
00546         {
00547             return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
00548         }
00549 
00550         /*
00551          * For BankFields, we must write the BankValue to the BankRegister
00552          * (itself a RegionField) before we can access the data.
00553          */
00554         Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
00555                     &ObjDesc->BankField.Value,
00556                     sizeof (ObjDesc->BankField.Value));
00557         if (ACPI_FAILURE (Status))
00558         {
00559             return_ACPI_STATUS (Status);
00560         }
00561 
00562         /*
00563          * Now that the Bank has been selected, fall through to the
00564          * RegionField case and write the datum to the Operation Region
00565          */
00566 
00567         /*lint -fallthrough */
00568 
00569 
00570     case ACPI_TYPE_LOCAL_REGION_FIELD:
00571         /*
00572          * For simple RegionFields, we just directly access the owning
00573          * Operation Region.
00574          */
00575         Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
00576                     ReadWrite);
00577         break;
00578 
00579 
00580     case ACPI_TYPE_LOCAL_INDEX_FIELD:
00581 
00582 
00583         /*
00584          * Ensure that the IndexValue is not beyond the capacity of
00585          * the register
00586          */
00587         if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
00588                 (UINT64) ObjDesc->IndexField.Value))
00589         {
00590             return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
00591         }
00592 
00593         /* Write the index value to the IndexRegister (itself a RegionField) */
00594 
00595         FieldDatumByteOffset += ObjDesc->IndexField.Value;
00596 
00597         ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
00598             "Write to Index Register: Value %8.8X\n",
00599             FieldDatumByteOffset));
00600 
00601         Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
00602                     &FieldDatumByteOffset,
00603                     sizeof (FieldDatumByteOffset));
00604         if (ACPI_FAILURE (Status))
00605         {
00606             return_ACPI_STATUS (Status);
00607         }
00608 
00609         if (ReadWrite == ACPI_READ)
00610         {
00611             /* Read the datum from the DataRegister */
00612 
00613             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
00614                 "Read from Data Register\n"));
00615 
00616             Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
00617                         Value, sizeof (UINT64));
00618         }
00619         else
00620         {
00621             /* Write the datum to the DataRegister */
00622 
00623             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
00624                 "Write to Data Register: Value %8.8X%8.8X\n",
00625                 ACPI_FORMAT_UINT64 (*Value)));
00626 
00627             Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
00628                         Value, sizeof (UINT64));
00629         }
00630         break;
00631 
00632 
00633     default:
00634 
00635         ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
00636             ObjDesc->Common.Type));
00637         Status = AE_AML_INTERNAL;
00638         break;
00639     }
00640 
00641     if (ACPI_SUCCESS (Status))
00642     {
00643         if (ReadWrite == ACPI_READ)
00644         {
00645             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
00646                 "Value Read %8.8X%8.8X, Width %u\n",
00647                 ACPI_FORMAT_UINT64 (*Value),
00648                 ObjDesc->CommonField.AccessByteWidth));
00649         }
00650         else
00651         {
00652             ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
00653                 "Value Written %8.8X%8.8X, Width %u\n",
00654                 ACPI_FORMAT_UINT64 (*Value),
00655                 ObjDesc->CommonField.AccessByteWidth));
00656         }
00657     }
00658 
00659     return_ACPI_STATUS (Status);
00660 }
00661 
00662 
00663 /*******************************************************************************
00664  *
00665  * FUNCTION:    AcpiExWriteWithUpdateRule
00666  *
00667  * PARAMETERS:  ObjDesc                 - Field to be written
00668  *              Mask                    - bitmask within field datum
00669  *              FieldValue              - Value to write
00670  *              FieldDatumByteOffset    - Offset of datum within field
00671  *
00672  * RETURN:      Status
00673  *
00674  * DESCRIPTION: Apply the field update rule to a field write
00675  *
00676  ******************************************************************************/
00677 
00678 ACPI_STATUS
00679 AcpiExWriteWithUpdateRule (
00680     ACPI_OPERAND_OBJECT     *ObjDesc,
00681     UINT64                  Mask,
00682     UINT64                  FieldValue,
00683     UINT32                  FieldDatumByteOffset)
00684 {
00685     ACPI_STATUS             Status = AE_OK;
00686     UINT64                  MergedValue;
00687     UINT64                  CurrentValue;
00688 
00689 
00690     ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
00691 
00692 
00693     /* Start with the new bits  */
00694 
00695     MergedValue = FieldValue;
00696 
00697     /* If the mask is all ones, we don't need to worry about the update rule */
00698 
00699     if (Mask != ACPI_UINT64_MAX)
00700     {
00701         /* Decode the update rule */
00702 
00703         switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
00704         {
00705         case AML_FIELD_UPDATE_PRESERVE:
00706             /*
00707              * Check if update rule needs to be applied (not if mask is all
00708              * ones)  The left shift drops the bits we want to ignore.
00709              */
00710             if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
00711                            ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
00712             {
00713                 /*
00714                  * Read the current contents of the byte/word/dword containing
00715                  * the field, and merge with the new field value.
00716                  */
00717                 Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
00718                             &CurrentValue, ACPI_READ);
00719                 if (ACPI_FAILURE (Status))
00720                 {
00721                     return_ACPI_STATUS (Status);
00722                 }
00723 
00724                 MergedValue |= (CurrentValue & ~Mask);
00725             }
00726             break;
00727 
00728         case AML_FIELD_UPDATE_WRITE_AS_ONES:
00729 
00730             /* Set positions outside the field to all ones */
00731 
00732             MergedValue |= ~Mask;
00733             break;
00734 
00735         case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
00736 
00737             /* Set positions outside the field to all zeros */
00738 
00739             MergedValue &= Mask;
00740             break;
00741 
00742         default:
00743 
00744             ACPI_ERROR ((AE_INFO,
00745                 "Unknown UpdateRule value: 0x%X",
00746                 (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
00747             return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
00748         }
00749     }
00750 
00751     ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
00752         "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
00753         ACPI_FORMAT_UINT64 (Mask),
00754         FieldDatumByteOffset,
00755         ObjDesc->CommonField.AccessByteWidth,
00756         ACPI_FORMAT_UINT64 (FieldValue),
00757         ACPI_FORMAT_UINT64 (MergedValue)));
00758 
00759     /* Write the merged value */
00760 
00761     Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
00762                 &MergedValue, ACPI_WRITE);
00763 
00764     return_ACPI_STATUS (Status);
00765 }
00766 
00767 
00768 /*******************************************************************************
00769  *
00770  * FUNCTION:    AcpiExExtractFromField
00771  *
00772  * PARAMETERS:  ObjDesc             - Field to be read
00773  *              Buffer              - Where to store the field data
00774  *              BufferLength        - Length of Buffer
00775  *
00776  * RETURN:      Status
00777  *
00778  * DESCRIPTION: Retrieve the current value of the given field
00779  *
00780  ******************************************************************************/
00781 
00782 ACPI_STATUS
00783 AcpiExExtractFromField (
00784     ACPI_OPERAND_OBJECT     *ObjDesc,
00785     void                    *Buffer,
00786     UINT32                  BufferLength)
00787 {
00788     ACPI_STATUS             Status;
00789     UINT64                  RawDatum;
00790     UINT64                  MergedDatum;
00791     UINT32                  FieldOffset = 0;
00792     UINT32                  BufferOffset = 0;
00793     UINT32                  BufferTailBits;
00794     UINT32                  DatumCount;
00795     UINT32                  FieldDatumCount;
00796     UINT32                  AccessBitWidth;
00797     UINT32                  i;
00798 
00799 
00800     ACPI_FUNCTION_TRACE (ExExtractFromField);
00801 
00802 
00803     /* Validate target buffer and clear it */
00804 
00805     if (BufferLength <
00806         ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
00807     {
00808         ACPI_ERROR ((AE_INFO,
00809             "Field size %u (bits) is too large for buffer (%u)",
00810             ObjDesc->CommonField.BitLength, BufferLength));
00811 
00812         return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
00813     }
00814 
00815     ACPI_MEMSET (Buffer, 0, BufferLength);
00816     AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
00817 
00818     /* Handle the simple case here */
00819 
00820     if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
00821         (ObjDesc->CommonField.BitLength == AccessBitWidth))
00822     {
00823         Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
00824         return_ACPI_STATUS (Status);
00825     }
00826 
00827 /* TBD: Move to common setup code */
00828 
00829     /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
00830 
00831     if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
00832     {
00833         ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
00834         AccessBitWidth = sizeof (UINT64) * 8;
00835     }
00836 
00837     /* Compute the number of datums (access width data items) */
00838 
00839     DatumCount = ACPI_ROUND_UP_TO (
00840         ObjDesc->CommonField.BitLength, AccessBitWidth);
00841 
00842     FieldDatumCount = ACPI_ROUND_UP_TO (
00843         ObjDesc->CommonField.BitLength +
00844         ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
00845 
00846     /* Priming read from the field */
00847 
00848     Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
00849     if (ACPI_FAILURE (Status))
00850     {
00851         return_ACPI_STATUS (Status);
00852     }
00853     MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
00854 
00855     /* Read the rest of the field */
00856 
00857     for (i = 1; i < FieldDatumCount; i++)
00858     {
00859         /* Get next input datum from the field */
00860 
00861         FieldOffset += ObjDesc->CommonField.AccessByteWidth;
00862         Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
00863                     &RawDatum, ACPI_READ);
00864         if (ACPI_FAILURE (Status))
00865         {
00866             return_ACPI_STATUS (Status);
00867         }
00868 
00869         /*
00870          * Merge with previous datum if necessary.
00871          *
00872          * Note: Before the shift, check if the shift value will be larger than
00873          * the integer size. If so, there is no need to perform the operation.
00874          * This avoids the differences in behavior between different compilers
00875          * concerning shift values larger than the target data width.
00876          */
00877         if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
00878             ACPI_INTEGER_BIT_SIZE)
00879         {
00880             MergedDatum |= RawDatum <<
00881                 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
00882         }
00883 
00884         if (i == DatumCount)
00885         {
00886             break;
00887         }
00888 
00889         /* Write merged datum to target buffer */
00890 
00891         ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
00892             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
00893                 BufferLength - BufferOffset));
00894 
00895         BufferOffset += ObjDesc->CommonField.AccessByteWidth;
00896         MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
00897     }
00898 
00899     /* Mask off any extra bits in the last datum */
00900 
00901     BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
00902     if (BufferTailBits)
00903     {
00904         MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
00905     }
00906 
00907     /* Write the last datum to the buffer */
00908 
00909     ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
00910         ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
00911             BufferLength - BufferOffset));
00912 
00913     return_ACPI_STATUS (AE_OK);
00914 }
00915 
00916 
00917 /*******************************************************************************
00918  *
00919  * FUNCTION:    AcpiExInsertIntoField
00920  *
00921  * PARAMETERS:  ObjDesc             - Field to be written
00922  *              Buffer              - Data to be written
00923  *              BufferLength        - Length of Buffer
00924  *
00925  * RETURN:      Status
00926  *
00927  * DESCRIPTION: Store the Buffer contents into the given field
00928  *
00929  ******************************************************************************/
00930 
00931 ACPI_STATUS
00932 AcpiExInsertIntoField (
00933     ACPI_OPERAND_OBJECT     *ObjDesc,
00934     void                    *Buffer,
00935     UINT32                  BufferLength)
00936 {
00937     void                    *NewBuffer;
00938     ACPI_STATUS             Status;
00939     UINT64                  Mask;
00940     UINT64                  WidthMask;
00941     UINT64                  MergedDatum;
00942     UINT64                  RawDatum = 0;
00943     UINT32                  FieldOffset = 0;
00944     UINT32                  BufferOffset = 0;
00945     UINT32                  BufferTailBits;
00946     UINT32                  DatumCount;
00947     UINT32                  FieldDatumCount;
00948     UINT32                  AccessBitWidth;
00949     UINT32                  RequiredLength;
00950     UINT32                  i;
00951 
00952 
00953     ACPI_FUNCTION_TRACE (ExInsertIntoField);
00954 
00955 
00956     /* Validate input buffer */
00957 
00958     NewBuffer = NULL;
00959     RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
00960                         ObjDesc->CommonField.BitLength);
00961     /*
00962      * We must have a buffer that is at least as long as the field
00963      * we are writing to.  This is because individual fields are
00964      * indivisible and partial writes are not supported -- as per
00965      * the ACPI specification.
00966      */
00967     if (BufferLength < RequiredLength)
00968     {
00969         /* We need to create a new buffer */
00970 
00971         NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
00972         if (!NewBuffer)
00973         {
00974             return_ACPI_STATUS (AE_NO_MEMORY);
00975         }
00976 
00977         /*
00978          * Copy the original data to the new buffer, starting
00979          * at Byte zero.  All unused (upper) bytes of the
00980          * buffer will be 0.
00981          */
00982         ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength);
00983         Buffer = NewBuffer;
00984         BufferLength = RequiredLength;
00985     }
00986 
00987 /* TBD: Move to common setup code */
00988 
00989     /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
00990     if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
00991     {
00992         ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
00993     }
00994 
00995     AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
00996 
00997     /*
00998      * Create the bitmasks used for bit insertion.
00999      * Note: This if/else is used to bypass compiler differences with the
01000      * shift operator
01001      */
01002     if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE)
01003     {
01004         WidthMask = ACPI_UINT64_MAX;
01005     }
01006     else
01007     {
01008         WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth);
01009     }
01010 
01011     Mask = WidthMask &
01012         ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
01013 
01014     /* Compute the number of datums (access width data items) */
01015 
01016     DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
01017         AccessBitWidth);
01018 
01019     FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
01020         ObjDesc->CommonField.StartFieldBitOffset,
01021         AccessBitWidth);
01022 
01023     /* Get initial Datum from the input buffer */
01024 
01025     ACPI_MEMCPY (&RawDatum, Buffer,
01026         ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
01027             BufferLength - BufferOffset));
01028 
01029     MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
01030 
01031     /* Write the entire field */
01032 
01033     for (i = 1; i < FieldDatumCount; i++)
01034     {
01035         /* Write merged datum to the target field */
01036 
01037         MergedDatum &= Mask;
01038         Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask,
01039                     MergedDatum, FieldOffset);
01040         if (ACPI_FAILURE (Status))
01041         {
01042             goto Exit;
01043         }
01044 
01045         FieldOffset += ObjDesc->CommonField.AccessByteWidth;
01046 
01047         /*
01048          * Start new output datum by merging with previous input datum
01049          * if necessary.
01050          *
01051          * Note: Before the shift, check if the shift value will be larger than
01052          * the integer size. If so, there is no need to perform the operation.
01053          * This avoids the differences in behavior between different compilers
01054          * concerning shift values larger than the target data width.
01055          */
01056         if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
01057             ACPI_INTEGER_BIT_SIZE)
01058         {
01059             MergedDatum = RawDatum >>
01060                 (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
01061         }
01062         else
01063         {
01064             MergedDatum = 0;
01065         }
01066 
01067         Mask = WidthMask;
01068 
01069         if (i == DatumCount)
01070         {
01071             break;
01072         }
01073 
01074         /* Get the next input datum from the buffer */
01075 
01076         BufferOffset += ObjDesc->CommonField.AccessByteWidth;
01077         ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset,
01078             ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
01079                  BufferLength - BufferOffset));
01080 
01081         MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
01082     }
01083 
01084     /* Mask off any extra bits in the last datum */
01085 
01086     BufferTailBits = (ObjDesc->CommonField.BitLength +
01087         ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
01088     if (BufferTailBits)
01089     {
01090         Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
01091     }
01092 
01093     /* Write the last datum to the field */
01094 
01095     MergedDatum &= Mask;
01096     Status = AcpiExWriteWithUpdateRule (ObjDesc,
01097                 Mask, MergedDatum, FieldOffset);
01098 
01099 Exit:
01100     /* Free temporary buffer if we used one */
01101 
01102     if (NewBuffer)
01103     {
01104         ACPI_FREE (NewBuffer);
01105     }
01106     return_ACPI_STATUS (Status);
01107 }
01108 
01109 

Generated on Tue May 22 2012 04:31:07 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.