exfldio.c revision 70243
167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: amfldio - Aml Field I/O 467754Smsmith * $Revision: 33 $ 570243Smsmith * 667754Smsmith *****************************************************************************/ 767754Smsmith 867754Smsmith/****************************************************************************** 967754Smsmith * 1067754Smsmith * 1. Copyright Notice 1167754Smsmith * 1267754Smsmith * Some or all of this work - Copyright (c) 1999, 2000, Intel Corp. 1370243Smsmith * All rights reserved. 1470243Smsmith * 1567754Smsmith * 2. License 1667754Smsmith * 1767754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property 1867754Smsmith * rights. You may have additional license terms from the party that provided 1967754Smsmith * you this software, covering your right to use that party's intellectual 2067754Smsmith * property rights. 2167754Smsmith * 2267754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 2367754Smsmith * copy of the source code appearing in this file ("Covered Code") an 2467754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the 2567754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy, 2667754Smsmith * make derivatives, distribute, use and display any portion of the Covered 2767754Smsmith * Code in any form, with the right to sublicense such rights; and 2867754Smsmith * 2967754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 3067754Smsmith * license (with the right to sublicense), under only those claims of Intel 3167754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell, 3267754Smsmith * offer to sell, and import the Covered Code and derivative works thereof 3367754Smsmith * solely to the minimum extent necessary to exercise the above copyright 3467754Smsmith * license, and in no event shall the patent license extend to any additions 3567754Smsmith * to or modifications of the Original Intel Code. No other license or right 3667754Smsmith * is granted directly or by implication, estoppel or otherwise; 3767754Smsmith * 3867754Smsmith * The above copyright and patent license is granted only if the following 3967754Smsmith * conditions are met: 4067754Smsmith * 4167754Smsmith * 3. Conditions 4267754Smsmith * 4367754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source. 4467754Smsmith * Redistribution of source code of any substantial portion of the Covered 4567754Smsmith * Code or modification with rights to further distribute source must include 4667754Smsmith * the above Copyright Notice, the above License, this list of Conditions, 4767754Smsmith * and the following Disclaimer and Export Compliance provision. In addition, 4867754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to 4967754Smsmith * contain a file documenting the changes Licensee made to create that Covered 5067754Smsmith * Code and the date of any change. Licensee must include in that file the 5167754Smsmith * documentation of any changes made by any predecessor Licensee. Licensee 5267754Smsmith * must include a prominent statement that the modification is derived, 5367754Smsmith * directly or indirectly, from Original Intel Code. 5467754Smsmith * 5567754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 5667754Smsmith * Redistribution of source code of any substantial portion of the Covered 5767754Smsmith * Code or modification without rights to further distribute source must 5867754Smsmith * include the following Disclaimer and Export Compliance provision in the 5967754Smsmith * documentation and/or other materials provided with distribution. In 6067754Smsmith * addition, Licensee may not authorize further sublicense of source of any 6167754Smsmith * portion of the Covered Code, and must include terms to the effect that the 6267754Smsmith * license from Licensee to its licensee is limited to the intellectual 6367754Smsmith * property embodied in the software Licensee provides to its licensee, and 6467754Smsmith * not to intellectual property embodied in modifications its licensee may 6567754Smsmith * make. 6667754Smsmith * 6767754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any 6867754Smsmith * substantial portion of the Covered Code or modification must reproduce the 6967754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance 7067754Smsmith * provision in the documentation and/or other materials provided with the 7167754Smsmith * distribution. 7267754Smsmith * 7367754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original 7467754Smsmith * Intel Code. 7567754Smsmith * 7667754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by 7767754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or 7867754Smsmith * other dealings in products derived from or relating to the Covered Code 7967754Smsmith * without prior written authorization from Intel. 8067754Smsmith * 8167754Smsmith * 4. Disclaimer and Export Compliance 8267754Smsmith * 8367754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 8467754Smsmith * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 8567754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 8667754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 8767754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 8867754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 8967754Smsmith * PARTICULAR PURPOSE. 9067754Smsmith * 9167754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 9267754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 9367754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 9467754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 9567754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 9667754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 9767754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 9867754Smsmith * LIMITED REMEDY. 9967754Smsmith * 10067754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this 10167754Smsmith * software or system incorporating such software without first obtaining any 10267754Smsmith * required license or other approval from the U. S. Department of Commerce or 10367754Smsmith * any other agency or department of the United States Government. In the 10467754Smsmith * event Licensee exports any such software from the United States or 10567754Smsmith * re-exports any such software from a foreign destination, Licensee shall 10667754Smsmith * ensure that the distribution and export/re-export of the software is in 10767754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the 10867754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor 10967754Smsmith * any of its subsidiaries will export/re-export any technical data, process, 11067754Smsmith * software, or service, directly or indirectly, to any country for which the 11167754Smsmith * United States government or any agency thereof requires an export license, 11267754Smsmith * other governmental approval, or letter of assurance, without first obtaining 11367754Smsmith * such license, approval or letter. 11467754Smsmith * 11567754Smsmith *****************************************************************************/ 11667754Smsmith 11767754Smsmith 11867754Smsmith#define __AMFLDIO_C__ 11967754Smsmith 12067754Smsmith#include "acpi.h" 12167754Smsmith#include "acinterp.h" 12267754Smsmith#include "amlcode.h" 12367754Smsmith#include "acnamesp.h" 12467754Smsmith#include "achware.h" 12567754Smsmith#include "acevents.h" 12667754Smsmith 12767754Smsmith 12867754Smsmith#define _COMPONENT INTERPRETER 12967754Smsmith MODULE_NAME ("amfldio") 13067754Smsmith 13167754Smsmith 13267754Smsmith/******************************************************************************* 13367754Smsmith * 13467754Smsmith * FUNCTION: AcpiAmlReadFieldData 13567754Smsmith * 13667754Smsmith * PARAMETERS: *ObjDesc - Field to be read 13767754Smsmith * *Value - Where to store value 13867754Smsmith * FieldBitWidth - Field Width in bits (8, 16, or 32) 13967754Smsmith * 14067754Smsmith * RETURN: Status 14167754Smsmith * 14267754Smsmith * DESCRIPTION: Retrieve the value of the given field 14367754Smsmith * 14467754Smsmith ******************************************************************************/ 14569450Smsmith 14667754SmsmithACPI_STATUS 14767754SmsmithAcpiAmlReadFieldData ( 14867754Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 14967754Smsmith UINT32 FieldByteOffset, 15067754Smsmith UINT32 FieldBitWidth, 15167754Smsmith UINT32 *Value) 15267754Smsmith{ 15367754Smsmith ACPI_STATUS Status; 15467754Smsmith ACPI_OPERAND_OBJECT *RgnDesc = NULL; 15567754Smsmith ACPI_PHYSICAL_ADDRESS Address; 15667754Smsmith UINT32 LocalValue = 0; 15767754Smsmith UINT32 FieldByteWidth; 15867754Smsmith 15969450Smsmith 16069450Smsmith FUNCTION_TRACE ("AmlReadFieldData"); 16167754Smsmith 16267754Smsmith 16367754Smsmith /* ObjDesc is validated by callers */ 16467754Smsmith 16567754Smsmith if (ObjDesc) 16667754Smsmith { 16767754Smsmith RgnDesc = ObjDesc->Field.Container; 16867754Smsmith } 16969450Smsmith 17069450Smsmith 17167754Smsmith FieldByteWidth = DIV_8 (FieldBitWidth); 17267754Smsmith Status = AcpiAmlSetupField (ObjDesc, RgnDesc, FieldBitWidth); 17367754Smsmith if (ACPI_FAILURE (Status)) 17467754Smsmith { 17567754Smsmith return_ACPI_STATUS (Status); 17667754Smsmith } 17767754Smsmith 17867754Smsmith /* SetupField validated RgnDesc and FieldBitWidth */ 17969450Smsmith 18069450Smsmith if (!Value) 18167754Smsmith { 18267754Smsmith Value = &LocalValue; /* support reads without saving value */ 18367754Smsmith } 18467754Smsmith 18567754Smsmith 18667754Smsmith /* 18767754Smsmith * Set offset to next multiple of field width, 18867754Smsmith * add region base address and offset within the field 18967754Smsmith */ 19067754Smsmith Address = RgnDesc->Region.Address + 19167754Smsmith (ObjDesc->Field.Offset * FieldByteWidth) + 19269450Smsmith FieldByteOffset; 19369450Smsmith 19467754Smsmith DEBUG_PRINT (TRACE_OPREGION, 19567754Smsmith ("AmlReadFieldData: Region %s(%X) at %08lx width %X\n", 19667754Smsmith AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 19767754Smsmith RgnDesc->Region.SpaceId, Address, 19867754Smsmith FieldBitWidth)); 19967754Smsmith 20067754Smsmith 20167754Smsmith /* Invoke the appropriate AddressSpace/OpRegion handler */ 20267754Smsmith 20367754Smsmith Status = AcpiEvAddressSpaceDispatch (RgnDesc, ADDRESS_SPACE_READ, 20467754Smsmith Address, FieldBitWidth, Value); 20567754Smsmith 20667754Smsmith if (Status == AE_NOT_IMPLEMENTED) 20767754Smsmith { 20867754Smsmith DEBUG_PRINT (ACPI_ERROR, 20967754Smsmith ("AmlReadFieldData: **** Region %s(%X) not implemented\n", 21067754Smsmith AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 21167754Smsmith RgnDesc->Region.SpaceId)); 21267754Smsmith } 21367754Smsmith 21467754Smsmith else if (Status == AE_NOT_EXIST) 21567754Smsmith { 21667754Smsmith DEBUG_PRINT (ACPI_ERROR, 21767754Smsmith ("AmlReadFieldData: **** Region %s(%X) has no handler\n", 21867754Smsmith AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 21967754Smsmith RgnDesc->Region.SpaceId)); 22067754Smsmith } 22167754Smsmith 22267754Smsmith DEBUG_PRINT (TRACE_OPREGION, 22367754Smsmith ("AmlReadField: Returned value=%08lx \n", *Value)); 22467754Smsmith 22567754Smsmith return_ACPI_STATUS (Status); 22667754Smsmith} 22767754Smsmith 22867754Smsmith 22967754Smsmith/******************************************************************************* 23067754Smsmith * 23167754Smsmith * FUNCTION: AcpiAmlReadField 23267754Smsmith * 23367754Smsmith * PARAMETERS: *ObjDesc - Field to be read 23467754Smsmith * *Value - Where to store value 23567754Smsmith * FieldBitWidth - Field Width in bits (8, 16, or 32) 23667754Smsmith * 23767754Smsmith * RETURN: Status 23867754Smsmith * 23967754Smsmith * DESCRIPTION: Retrieve the value of the given field 24067754Smsmith * 24167754Smsmith ******************************************************************************/ 24267754Smsmith 24369450SmsmithACPI_STATUS 24467754SmsmithAcpiAmlReadField ( 24567754Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 24667754Smsmith void *Buffer, 24767754Smsmith UINT32 BufferLength, 24867754Smsmith UINT32 ByteLength, 24967754Smsmith UINT32 DatumLength, 25067754Smsmith UINT32 BitGranularity, 25167754Smsmith UINT32 ByteGranularity) 25267754Smsmith{ 25367754Smsmith ACPI_STATUS Status; 25467754Smsmith UINT32 ThisFieldByteOffset; 25567754Smsmith UINT32 ThisFieldDatumOffset; 25667754Smsmith UINT32 PreviousRawDatum; 25767754Smsmith UINT32 ThisRawDatum; 25867754Smsmith UINT32 ValidFieldBits; 25967754Smsmith UINT32 Mask; 26067754Smsmith UINT32 MergedDatum = 0; 26167754Smsmith 26267754Smsmith 26367754Smsmith FUNCTION_TRACE ("AmlReadField"); 26467754Smsmith 26567754Smsmith /* 26667754Smsmith * Clear the caller's buffer (the whole buffer length as given) 26767754Smsmith * This is very important, especially in the cases where a byte is read, 26867754Smsmith * but the buffer is really a UINT32 (4 bytes). 26967754Smsmith */ 27067754Smsmith 27167754Smsmith MEMSET (Buffer, 0, BufferLength); 27267754Smsmith 27367754Smsmith /* Read the first raw datum to prime the loop */ 27467754Smsmith 27567754Smsmith ThisFieldByteOffset = 0; 27667754Smsmith ThisFieldDatumOffset= 0; 27767754Smsmith 27867754Smsmith Status = AcpiAmlReadFieldData (ObjDesc, ThisFieldByteOffset, BitGranularity, 27967754Smsmith &PreviousRawDatum); 28067754Smsmith if (ACPI_FAILURE (Status)) 28167754Smsmith { 28267754Smsmith goto Cleanup; 28367754Smsmith } 28467754Smsmith 28567754Smsmith /* We might actually be done if the request fits in one datum */ 28667754Smsmith 28767754Smsmith if ((DatumLength == 1) && 28867754Smsmith ((ObjDesc->Field.BitOffset + ObjDesc->FieldUnit.Length) <= 28967754Smsmith (UINT16) BitGranularity)) 29067754Smsmith { 29167754Smsmith MergedDatum = PreviousRawDatum; 29267754Smsmith 29367754Smsmith MergedDatum = (MergedDatum >> ObjDesc->Field.BitOffset); 29467754Smsmith 29567754Smsmith ValidFieldBits = ObjDesc->FieldUnit.Length % BitGranularity; 29667754Smsmith if (ValidFieldBits) 29767754Smsmith { 29867754Smsmith Mask = (((UINT32) 1 << ValidFieldBits) - (UINT32) 1); 29967754Smsmith MergedDatum &= Mask; 30067754Smsmith } 30167754Smsmith 30267754Smsmith 30367754Smsmith /* 30467754Smsmith * Place the MergedDatum into the proper format and return buffer 30567754Smsmith * field 30667754Smsmith */ 30767754Smsmith 30867754Smsmith switch (ByteGranularity) 30967754Smsmith { 31067754Smsmith case 1: 31167754Smsmith ((UINT8 *) Buffer) [ThisFieldDatumOffset] = (UINT8) MergedDatum; 31267754Smsmith break; 31367754Smsmith 31467754Smsmith case 2: 31567754Smsmith MOVE_UNALIGNED16_TO_16 (&(((UINT16 *) Buffer)[ThisFieldDatumOffset]), &MergedDatum); 31667754Smsmith break; 31767754Smsmith 31867754Smsmith case 4: 31967754Smsmith MOVE_UNALIGNED32_TO_32 (&(((UINT32 *) Buffer)[ThisFieldDatumOffset]), &MergedDatum); 32067754Smsmith break; 32167754Smsmith } 32267754Smsmith 32367754Smsmith ThisFieldByteOffset = 1; 32467754Smsmith ThisFieldDatumOffset = 1; 32567754Smsmith } 32667754Smsmith 32767754Smsmith else 32867754Smsmith { 32967754Smsmith /* We need to get more raw data to complete one or more field data */ 33067754Smsmith 33167754Smsmith while (ThisFieldDatumOffset < DatumLength) 33267754Smsmith { 33367754Smsmith /* 33467754Smsmith * Get the next raw datum, it contains bits of the current 33567754Smsmith * field datum 33667754Smsmith */ 33767754Smsmith 33867754Smsmith Status = AcpiAmlReadFieldData (ObjDesc, 33967754Smsmith ThisFieldByteOffset + ByteGranularity, 34067754Smsmith BitGranularity, &ThisRawDatum); 34167754Smsmith if (ACPI_FAILURE (Status)) 34267754Smsmith { 34367754Smsmith goto Cleanup; 34467754Smsmith } 34567754Smsmith 34667754Smsmith /* Before merging the data, make sure the unused bits are clear */ 34767754Smsmith 34867754Smsmith switch (ByteGranularity) 34967754Smsmith { 35067754Smsmith case 1: 35167754Smsmith ThisRawDatum &= 0x000000FF; 35267754Smsmith PreviousRawDatum &= 0x000000FF; 35367754Smsmith break; 35467754Smsmith 35567754Smsmith case 2: 35667754Smsmith ThisRawDatum &= 0x0000FFFF; 35767754Smsmith PreviousRawDatum &= 0x0000FFFF; 35867754Smsmith break; 35967754Smsmith } 36067754Smsmith 36167754Smsmith /* 36267754Smsmith * Put together bits of the two raw data to make a complete 36367754Smsmith * field datum 36467754Smsmith */ 36567754Smsmith 36667754Smsmith 36767754Smsmith if (ObjDesc->Field.BitOffset != 0) 36867754Smsmith { 36967754Smsmith MergedDatum = 37067754Smsmith (PreviousRawDatum >> ObjDesc->Field.BitOffset) | 37167754Smsmith (ThisRawDatum << (BitGranularity - ObjDesc->Field.BitOffset)); 37267754Smsmith } 37367754Smsmith 37467754Smsmith else 37567754Smsmith { 37667754Smsmith MergedDatum = PreviousRawDatum; 37767754Smsmith } 37867754Smsmith 37967754Smsmith /* 38067754Smsmith * Prepare the merged datum for storing into the caller's 38167754Smsmith * buffer. It is possible to have a 32-bit buffer 38267754Smsmith * (ByteGranularity == 4), but a ObjDesc->Field.Length 38367754Smsmith * of 8 or 16, meaning that the upper bytes of merged data 38467754Smsmith * are undesired. This section fixes that. 38567754Smsmith */ 38667754Smsmith switch (ObjDesc->Field.Length) 38767754Smsmith { 38867754Smsmith case 8: 38967754Smsmith MergedDatum &= 0x000000FF; 39067754Smsmith break; 39167754Smsmith 39267754Smsmith case 16: 39367754Smsmith MergedDatum &= 0x0000FFFF; 39467754Smsmith break; 39567754Smsmith } 39667754Smsmith 39767754Smsmith /* 39867754Smsmith * Now store the datum in the caller's buffer, according to 39967754Smsmith * the data type 40067754Smsmith */ 40167754Smsmith switch (ByteGranularity) 40267754Smsmith { 40367754Smsmith case 1: 40467754Smsmith ((UINT8 *) Buffer) [ThisFieldDatumOffset] = (UINT8) MergedDatum; 40567754Smsmith break; 40667754Smsmith 40767754Smsmith case 2: 40867754Smsmith MOVE_UNALIGNED16_TO_16 (&(((UINT16 *) Buffer) [ThisFieldDatumOffset]), &MergedDatum); 40967754Smsmith break; 41067754Smsmith 41167754Smsmith case 4: 41267754Smsmith MOVE_UNALIGNED32_TO_32 (&(((UINT32 *) Buffer) [ThisFieldDatumOffset]), &MergedDatum); 41367754Smsmith break; 41467754Smsmith } 41567754Smsmith 41667754Smsmith /* 41767754Smsmith * Save the most recent datum since it contains bits of 41867754Smsmith * the *next* field datum 41967754Smsmith */ 42067754Smsmith 42167754Smsmith PreviousRawDatum = ThisRawDatum; 42267754Smsmith 42367754Smsmith ThisFieldByteOffset += ByteGranularity; 42467754Smsmith ThisFieldDatumOffset++; 42567754Smsmith 42667754Smsmith } /* while */ 42767754Smsmith } 42867754Smsmith 42967754SmsmithCleanup: 43067754Smsmith 43167754Smsmith return_ACPI_STATUS (Status); 43267754Smsmith} 43367754Smsmith 43467754Smsmith 43567754Smsmith/******************************************************************************* 43667754Smsmith * 43767754Smsmith * FUNCTION: AcpiAmlWriteFieldData 43867754Smsmith * 43967754Smsmith * PARAMETERS: *ObjDesc - Field to be set 44067754Smsmith * Value - Value to store 44167754Smsmith * FieldBitWidth - Field Width in bits (8, 16, or 32) 44267754Smsmith * 44367754Smsmith * RETURN: Status 44467754Smsmith * 44567754Smsmith * DESCRIPTION: Store the value into the given field 44667754Smsmith * 44767754Smsmith ******************************************************************************/ 44867754Smsmith 44967754Smsmithstatic ACPI_STATUS 45067754SmsmithAcpiAmlWriteFieldData ( 45167754Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 45267754Smsmith UINT32 FieldByteOffset, 45367754Smsmith UINT32 FieldBitWidth, 45467754Smsmith UINT32 Value) 45567754Smsmith{ 45667754Smsmith ACPI_STATUS Status = AE_OK; 45767754Smsmith ACPI_OPERAND_OBJECT *RgnDesc = NULL; 45867754Smsmith ACPI_PHYSICAL_ADDRESS Address; 45967754Smsmith UINT32 FieldByteWidth; 46067754Smsmith 46167754Smsmith 46267754Smsmith FUNCTION_TRACE ("AmlWriteFieldData"); 46367754Smsmith 46467754Smsmith 46567754Smsmith /* ObjDesc is validated by callers */ 46667754Smsmith 46767754Smsmith if (ObjDesc) 46867754Smsmith { 46967754Smsmith RgnDesc = ObjDesc->Field.Container; 47067754Smsmith } 47167754Smsmith 47267754Smsmith FieldByteWidth = DIV_8 (FieldBitWidth); 47367754Smsmith Status = AcpiAmlSetupField (ObjDesc, RgnDesc, FieldBitWidth); 47467754Smsmith if (ACPI_FAILURE (Status)) 47567754Smsmith { 47667754Smsmith return_ACPI_STATUS (Status); 47767754Smsmith } 47867754Smsmith 47967754Smsmith 48067754Smsmith /* 48167754Smsmith * Set offset to next multiple of field width, 48267754Smsmith * add region base address and offset within the field 48367754Smsmith */ 48467754Smsmith Address = RgnDesc->Region.Address + 48567754Smsmith (ObjDesc->Field.Offset * FieldByteWidth) + 48667754Smsmith FieldByteOffset; 48767754Smsmith 48867754Smsmith DEBUG_PRINT (TRACE_OPREGION, 48967754Smsmith ("AmlWriteField: Store %lx in Region %s(%X) at %p width %X\n", 49067754Smsmith Value, AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 49167754Smsmith RgnDesc->Region.SpaceId, Address, 49269450Smsmith FieldBitWidth)); 49367754Smsmith 49467754Smsmith /* Invoke the appropriate AddressSpace/OpRegion handler */ 49567754Smsmith 49667754Smsmith Status = AcpiEvAddressSpaceDispatch (RgnDesc, ADDRESS_SPACE_WRITE, 49767754Smsmith Address, FieldBitWidth, &Value); 49867754Smsmith 49967754Smsmith if (Status == AE_NOT_IMPLEMENTED) 50067754Smsmith { 50167754Smsmith DEBUG_PRINT (ACPI_ERROR, 50267754Smsmith ("AmlWriteField: **** Region type %s(%X) not implemented\n", 50367754Smsmith AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 50467754Smsmith RgnDesc->Region.SpaceId)); 50567754Smsmith } 50667754Smsmith 50767754Smsmith else if (Status == AE_NOT_EXIST) 50867754Smsmith { 50967754Smsmith DEBUG_PRINT (ACPI_ERROR, 51067754Smsmith ("AmlWriteField: **** Region type %s(%X) does not have a handler\n", 51167754Smsmith AcpiCmGetRegionName (RgnDesc->Region.SpaceId), 51267754Smsmith RgnDesc->Region.SpaceId)); 51367754Smsmith } 51467754Smsmith 515 return_ACPI_STATUS (Status); 516} 517 518 519/***************************************************************************** 520 * 521 * FUNCTION: AcpiAmlWriteFieldDataWithUpdateRule 522 * 523 * PARAMETERS: *ObjDesc - Field to be set 524 * Value - Value to store 525 * FieldBitWidth - Field Width in bits (8, 16, or 32) 526 * 527 * RETURN: Status 528 * 529 * DESCRIPTION: Apply the field update rule to a field write 530 * 531 ****************************************************************************/ 532 533static ACPI_STATUS 534AcpiAmlWriteFieldDataWithUpdateRule ( 535 ACPI_OPERAND_OBJECT *ObjDesc, 536 UINT32 Mask, 537 UINT32 FieldValue, 538 UINT32 ThisFieldByteOffset, 539 UINT32 BitGranularity) 540{ 541 ACPI_STATUS Status = AE_OK; 542 UINT32 MergedValue; 543 UINT32 CurrentValue; 544 545 546 /* Start with the new bits */ 547 548 MergedValue = FieldValue; 549 550 /* Check if update rule needs to be applied (not if mask is all ones) */ 551 552 553 /* Decode the update rule */ 554 555 switch (ObjDesc->Field.UpdateRule) 556 { 557 558 case UPDATE_PRESERVE: 559 560 /* 561 * Read the current contents of the byte/word/dword containing 562 * the field, and merge with the new field value. 563 */ 564 Status = AcpiAmlReadFieldData (ObjDesc, ThisFieldByteOffset, 565 BitGranularity, &CurrentValue); 566 MergedValue |= (CurrentValue & ~Mask); 567 break; 568 569 570 case UPDATE_WRITE_AS_ONES: 571 572 /* Set positions outside the field to all ones */ 573 574 MergedValue |= ~Mask; 575 break; 576 577 578 case UPDATE_WRITE_AS_ZEROS: 579 580 /* Set positions outside the field to all zeros */ 581 582 MergedValue &= Mask; 583 break; 584 585 586 default: 587 DEBUG_PRINT (ACPI_ERROR, 588 ("WriteFieldDataWithUpdateRule: Unknown UpdateRule setting: %x\n", 589 ObjDesc->Field.UpdateRule)); 590 Status = AE_AML_OPERAND_VALUE; 591 } 592 593 594 /* Write the merged value */ 595 596 if (ACPI_SUCCESS (Status)) 597 { 598 Status = AcpiAmlWriteFieldData (ObjDesc, ThisFieldByteOffset, 599 BitGranularity, MergedValue); 600 } 601 602 return (Status); 603} 604 605 606/***************************************************************************** 607 * 608 * FUNCTION: AcpiAmlWriteField 609 * 610 * PARAMETERS: *ObjDesc - Field to be set 611 * Value - Value to store 612 * FieldBitWidth - Field Width in bits (8, 16, or 32) 613 * 614 * RETURN: Status 615 * 616 * DESCRIPTION: Store the value into the given field 617 * 618 ****************************************************************************/ 619 620ACPI_STATUS 621AcpiAmlWriteField ( 622 ACPI_OPERAND_OBJECT *ObjDesc, 623 void *Buffer, 624 UINT32 BufferLength, 625 UINT32 ByteLength, 626 UINT32 DatumLength, 627 UINT32 BitGranularity, 628 UINT32 ByteGranularity) 629{ 630 ACPI_STATUS Status; 631 UINT32 ThisFieldByteOffset; 632 UINT32 ThisFieldDatumOffset; 633 UINT32 Mask; 634 UINT32 MergedDatum; 635 UINT32 PreviousRawDatum; 636 UINT32 ThisRawDatum; 637 UINT32 FieldValue; 638 UINT32 ValidFieldBits; 639 640 641 FUNCTION_TRACE ("AmlWriteField"); 642 643 644 /* 645 * Break the request into up to three parts: 646 * non-aligned part at start, aligned part in middle, non-aligned part 647 * at end --- Just like an I/O request --- 648 */ 649 650 ThisFieldByteOffset = 0; 651 ThisFieldDatumOffset= 0; 652 653 /* Get a datum */ 654 655 switch (ByteGranularity) 656 { 657 case 1: 658 PreviousRawDatum = ((UINT8 *) Buffer) [ThisFieldDatumOffset]; 659 break; 660 661 case 2: 662 MOVE_UNALIGNED16_TO_32 (&PreviousRawDatum, &(((UINT16 *) Buffer) [ThisFieldDatumOffset])); 663 break; 664 665 case 4: 666 MOVE_UNALIGNED32_TO_32 (&PreviousRawDatum, &(((UINT32 *) Buffer) [ThisFieldDatumOffset])); 667 break; 668 669 default: 670 DEBUG_PRINT (ACPI_ERROR, ("AmlWriteField: Invalid granularity: %x\n", 671 ByteGranularity)); 672 Status = AE_AML_OPERAND_VALUE; 673 goto Cleanup; 674 } 675 676 677 /* 678 * Write a partial field datum if field does not begin on a datum boundary 679 * 680 * Construct Mask with 1 bits where the field is, 0 bits elsewhere 681 * 682 * 1) Bits above the field 683 */ 684 685 Mask = (((UINT32)(-1)) << (UINT32)ObjDesc->Field.BitOffset); 686 687 /* 2) Only the bottom 5 bits are valid for a shift operation. */ 688 689 if ((ObjDesc->Field.BitOffset + ObjDesc->FieldUnit.Length) < 32) 690 { 691 /* Bits above the field */ 692 693 Mask &= (~(((UINT32)(-1)) << ((UINT32)ObjDesc->Field.BitOffset + 694 (UINT32)ObjDesc->FieldUnit.Length))); 695 } 696 697 /* 3) Shift and mask the value into the field position */ 698 699 FieldValue = (PreviousRawDatum << ObjDesc->Field.BitOffset) & Mask; 700 701 Status = AcpiAmlWriteFieldDataWithUpdateRule (ObjDesc, Mask, FieldValue, 702 ThisFieldByteOffset, 703 BitGranularity); 704 if (ACPI_FAILURE (Status)) 705 { 706 goto Cleanup; 707 } 708 709 710 /* If the field fits within one datum, we are done. */ 711 712 if ((DatumLength == 1) && 713 ((ObjDesc->Field.BitOffset + ObjDesc->FieldUnit.Length) <= 714 (UINT16) BitGranularity)) 715 { 716 goto Cleanup; 717 } 718 719 /* 720 * We don't need to worry about the update rule for these data, because 721 * all of the bits are part of the field. 722 * 723 * Can't write the last datum, however, because it might contain bits that 724 * are not part of the field -- the update rule must be applied. 725 */ 726 727 while (ThisFieldDatumOffset < (DatumLength - 1)) 728 { 729 ThisFieldDatumOffset++; 730 731 /* Get the next raw datum, it contains bits of the current field datum... */ 732 733 switch (ByteGranularity) 734 { 735 case 1: 736 ThisRawDatum = ((UINT8 *) Buffer) [ThisFieldDatumOffset]; 737 break; 738 739 case 2: 740 MOVE_UNALIGNED16_TO_32 (&ThisRawDatum, &(((UINT16 *) Buffer) [ThisFieldDatumOffset])); 741 break; 742 743 case 4: 744 MOVE_UNALIGNED32_TO_32 (&ThisRawDatum, &(((UINT32 *) Buffer) [ThisFieldDatumOffset])); 745 break; 746 747 default: 748 DEBUG_PRINT (ACPI_ERROR, ("AmlWriteField: Invalid Byte Granularity: %x\n", 749 ByteGranularity)); 750 Status = AE_AML_OPERAND_VALUE; 751 goto Cleanup; 752 } 753 754 /* 755 * Put together bits of the two raw data to make a complete field 756 * datum 757 */ 758 759 if (ObjDesc->Field.BitOffset != 0) 760 { 761 MergedDatum = 762 (PreviousRawDatum >> (BitGranularity - ObjDesc->Field.BitOffset)) | 763 (ThisRawDatum << ObjDesc->Field.BitOffset); 764 } 765 766 else 767 { 768 MergedDatum = ThisRawDatum; 769 } 770 771 /* Now write the completed datum */ 772 773 774 Status = AcpiAmlWriteFieldData (ObjDesc, 775 ThisFieldByteOffset + ByteGranularity, 776 BitGranularity, MergedDatum); 777 if (ACPI_FAILURE (Status)) 778 { 779 goto Cleanup; 780 } 781 782 783 /* 784 * Save the most recent datum since it contains bits of 785 * the *next* field datum 786 */ 787 788 PreviousRawDatum = ThisRawDatum; 789 790 ThisFieldByteOffset += ByteGranularity; 791 792 } /* while */ 793 794 795 /* Write a partial field datum if field does not end on a datum boundary */ 796 797 if ((ObjDesc->FieldUnit.Length + ObjDesc->FieldUnit.BitOffset) % 798 BitGranularity) 799 { 800 switch (ByteGranularity) 801 { 802 case 1: 803 ThisRawDatum = ((UINT8 *) Buffer) [ThisFieldDatumOffset]; 804 break; 805 806 case 2: 807 MOVE_UNALIGNED16_TO_32 (&ThisRawDatum, &(((UINT16 *) Buffer) [ThisFieldDatumOffset])); 808 break; 809 810 case 4: 811 MOVE_UNALIGNED32_TO_32 (&ThisRawDatum, &(((UINT32 *) Buffer) [ThisFieldDatumOffset])); 812 break; 813 } 814 815 /* Construct Mask with 1 bits where the field is, 0 bits elsewhere */ 816 817 ValidFieldBits = ((ObjDesc->FieldUnit.Length % BitGranularity) + 818 ObjDesc->Field.BitOffset); 819 820 Mask = (((UINT32) 1 << ValidFieldBits) - (UINT32) 1); 821 822 /* Shift and mask the value into the field position */ 823 824 FieldValue = (PreviousRawDatum >> 825 (BitGranularity - ObjDesc->Field.BitOffset)) & Mask; 826 827 Status = AcpiAmlWriteFieldDataWithUpdateRule (ObjDesc, Mask, FieldValue, 828 ThisFieldByteOffset + ByteGranularity, 829 BitGranularity); 830 if (ACPI_FAILURE (Status)) 831 { 832 goto Cleanup; 833 } 834 } 835 836 837Cleanup: 838 839 return_ACPI_STATUS (Status); 840} 841 842 843