exfield.c revision 107325
1234353Sdim/****************************************************************************** 2193323Sed * 3193323Sed * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 4193323Sed * $Revision: 115 $ 5193323Sed * 6193323Sed *****************************************************************************/ 7193323Sed 8193323Sed/****************************************************************************** 9193323Sed * 10193323Sed * 1. Copyright Notice 11193323Sed * 12193323Sed * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp. 13193323Sed * All rights reserved. 14193323Sed * 15193323Sed * 2. License 16193323Sed * 17193323Sed * 2.1. This is your license from Intel Corp. under its intellectual property 18193323Sed * rights. You may have additional license terms from the party that provided 19193323Sed * you this software, covering your right to use that party's intellectual 20193323Sed * property rights. 21193323Sed * 22193323Sed * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23193323Sed * copy of the source code appearing in this file ("Covered Code") an 24193323Sed * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25193323Sed * base code distributed originally by Intel ("Original Intel Code") to copy, 26193323Sed * make derivatives, distribute, use and display any portion of the Covered 27193323Sed * Code in any form, with the right to sublicense such rights; and 28193323Sed * 29193323Sed * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30193323Sed * license (with the right to sublicense), under only those claims of Intel 31193323Sed * patents that are infringed by the Original Intel Code, to make, use, sell, 32193323Sed * offer to sell, and import the Covered Code and derivative works thereof 33193323Sed * solely to the minimum extent necessary to exercise the above copyright 34193323Sed * license, and in no event shall the patent license extend to any additions 35193323Sed * to or modifications of the Original Intel Code. No other license or right 36193323Sed * is granted directly or by implication, estoppel or otherwise; 37193323Sed * 38193323Sed * The above copyright and patent license is granted only if the following 39193323Sed * conditions are met: 40193323Sed * 41193323Sed * 3. Conditions 42193323Sed * 43193323Sed * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44193323Sed * Redistribution of source code of any substantial portion of the Covered 45193323Sed * Code or modification with rights to further distribute source must include 46193323Sed * the above Copyright Notice, the above License, this list of Conditions, 47193323Sed * and the following Disclaimer and Export Compliance provision. In addition, 48193323Sed * Licensee must cause all Covered Code to which Licensee contributes to 49193323Sed * contain a file documenting the changes Licensee made to create that Covered 50193323Sed * Code and the date of any change. Licensee must include in that file the 51193323Sed * documentation of any changes made by any predecessor Licensee. Licensee 52193323Sed * must include a prominent statement that the modification is derived, 53193323Sed * directly or indirectly, from Original Intel Code. 54193323Sed * 55193323Sed * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56193323Sed * Redistribution of source code of any substantial portion of the Covered 57193323Sed * Code or modification without rights to further distribute source must 58193323Sed * include the following Disclaimer and Export Compliance provision in the 59193323Sed * documentation and/or other materials provided with distribution. In 60193323Sed * addition, Licensee may not authorize further sublicense of source of any 61193323Sed * portion of the Covered Code, and must include terms to the effect that the 62193323Sed * license from Licensee to its licensee is limited to the intellectual 63193323Sed * property embodied in the software Licensee provides to its licensee, and 64193323Sed * not to intellectual property embodied in modifications its licensee may 65193323Sed * make. 66193323Sed * 67193323Sed * 3.3. Redistribution of Executable. Redistribution in executable form of any 68193323Sed * substantial portion of the Covered Code or modification must reproduce the 69193323Sed * above Copyright Notice, and the following Disclaimer and Export Compliance 70193323Sed * provision in the documentation and/or other materials provided with the 71193323Sed * distribution. 72193323Sed * 73193323Sed * 3.4. Intel retains all right, title, and interest in and to the Original 74193323Sed * Intel Code. 75193323Sed * 76193323Sed * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77193323Sed * Intel shall be used in advertising or otherwise to promote the sale, use or 78193323Sed * other dealings in products derived from or relating to the Covered Code 79193323Sed * without prior written authorization from Intel. 80193323Sed * 81193323Sed * 4. Disclaimer and Export Compliance 82193323Sed * 83193323Sed * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84193323Sed * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85193323Sed * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86193323Sed * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87193323Sed * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89193323Sed * PARTICULAR PURPOSE. 90193323Sed * 91193323Sed * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92193323Sed * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93193323Sed * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94193323Sed * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95193323Sed * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96193323Sed * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97193323Sed * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98193323Sed * LIMITED REMEDY. 99193323Sed * 100193323Sed * 4.3. Licensee shall not export, either directly or indirectly, any of this 101193323Sed * software or system incorporating such software without first obtaining any 102193323Sed * required license or other approval from the U. S. Department of Commerce or 103193323Sed * any other agency or department of the United States Government. In the 104193323Sed * event Licensee exports any such software from the United States or 105193323Sed * re-exports any such software from a foreign destination, Licensee shall 106193323Sed * ensure that the distribution and export/re-export of the software is in 107193323Sed * compliance with all laws, regulations, orders, or other restrictions of the 108193323Sed * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109193323Sed * any of its subsidiaries will export/re-export any technical data, process, 110193323Sed * software, or service, directly or indirectly, to any country for which the 111193323Sed * United States government or any agency thereof requires an export license, 112193323Sed * other governmental approval, or letter of assurance, without first obtaining 113193323Sed * such license, approval or letter. 114193323Sed * 115193323Sed *****************************************************************************/ 116193323Sed 117193323Sed 118193323Sed#define __EXFIELD_C__ 119193323Sed 120193323Sed#include "acpi.h" 121193323Sed#include "acdispat.h" 122193323Sed#include "acinterp.h" 123193323Sed 124193323Sed 125193323Sed#define _COMPONENT ACPI_EXECUTER 126193323Sed ACPI_MODULE_NAME ("exfield") 127193323Sed 128193323Sed 129193323Sed/******************************************************************************* 130193323Sed * 131193323Sed * FUNCTION: AcpiExReadDataFromField 132193323Sed * 133193323Sed * PARAMETERS: WalkState - Current execution state 134193323Sed * ObjDesc - The named field 135193323Sed * RetBufferDesc - Where the return data object is stored 136193323Sed * 137193323Sed * RETURN: Status 138193323Sed * 139193323Sed * DESCRIPTION: Read from a named field. Returns either an Integer or a 140193323Sed * Buffer, depending on the size of the field. 141193323Sed * 142193323Sed ******************************************************************************/ 143193323Sed 144193323SedACPI_STATUS 145193323SedAcpiExReadDataFromField ( 146193323Sed ACPI_WALK_STATE *WalkState, 147193323Sed ACPI_OPERAND_OBJECT *ObjDesc, 148193323Sed ACPI_OPERAND_OBJECT **RetBufferDesc) 149193323Sed{ 150193323Sed ACPI_STATUS Status; 151193323Sed ACPI_OPERAND_OBJECT *BufferDesc; 152193323Sed UINT32 Length; 153193323Sed void *Buffer; 154193323Sed BOOLEAN Locked; 155193323Sed 156193323Sed 157193323Sed ACPI_FUNCTION_TRACE_PTR ("ExReadDataFromField", ObjDesc); 158193323Sed 159193323Sed 160193323Sed /* Parameter validation */ 161193323Sed 162193323Sed if (!ObjDesc) 163193323Sed { 164193323Sed return_ACPI_STATUS (AE_AML_NO_OPERAND); 165193323Sed } 166193323Sed 167193323Sed if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD) 168193323Sed { 169193323Sed /* 170193323Sed * If the BufferField arguments have not been previously evaluated, 171193323Sed * evaluate them now and save the results. 172193323Sed */ 173193323Sed if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 174193323Sed { 175193323Sed Status = AcpiDsGetBufferFieldArguments (ObjDesc); 176193323Sed if (ACPI_FAILURE (Status)) 177193323Sed { 178193323Sed return_ACPI_STATUS (Status); 179193323Sed } 180193323Sed } 181193323Sed } 182193323Sed else if ((ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_LOCAL_REGION_FIELD) && 183193323Sed (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)) 184193323Sed { 185193323Sed /* 186193323Sed * This is an SMBus read. We must create a buffer to hold the data 187193323Sed * and directly access the region handler. 188193323Sed */ 189193323Sed BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE); 190193323Sed if (!BufferDesc) 191193323Sed { 192193323Sed return_ACPI_STATUS (AE_NO_MEMORY); 193193323Sed } 194193323Sed 195193323Sed /* Lock entire transaction if requested */ 196193323Sed 197193323Sed Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 198193323Sed 199193323Sed /* 200193323Sed * Perform the read. 201193323Sed * Note: Smbus protocol value is passed in upper 16-bits of Function 202193323Sed */ 203193323Sed Status = AcpiExAccessRegion (ObjDesc, 0, 204193323Sed ACPI_CAST_PTR (ACPI_INTEGER, BufferDesc->Buffer.Pointer), 205193323Sed ACPI_READ | (ObjDesc->Field.Attribute << 16)); 206193323Sed AcpiExReleaseGlobalLock (Locked); 207193323Sed goto Exit; 208193323Sed } 209193323Sed 210193323Sed /* 211193323Sed * Allocate a buffer for the contents of the field. 212193323Sed * 213193323Sed * If the field is larger than the size of an ACPI_INTEGER, create 214193323Sed * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 215193323Sed * the use of arithmetic operators on the returned value if the 216193323Sed * field size is equal or smaller than an Integer. 217193323Sed * 218193323Sed * Note: Field.length is in bits. 219193323Sed */ 220193323Sed Length = ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->Field.BitLength); 221193323Sed if (Length > AcpiGbl_IntegerByteWidth) 222193323Sed { 223193323Sed /* Field is too large for an Integer, create a Buffer instead */ 224193323Sed 225193323Sed BufferDesc = AcpiUtCreateBufferObject (Length); 226193323Sed if (!BufferDesc) 227193323Sed { 228193323Sed return_ACPI_STATUS (AE_NO_MEMORY); 229193323Sed } 230193323Sed Buffer = BufferDesc->Buffer.Pointer; 231193323Sed } 232193323Sed else 233193323Sed { 234193323Sed /* Field will fit within an Integer (normal case) */ 235193323Sed 236193323Sed BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 237193323Sed if (!BufferDesc) 238193323Sed { 239193323Sed return_ACPI_STATUS (AE_NO_MEMORY); 240193323Sed } 241193323Sed 242193323Sed Length = AcpiGbl_IntegerByteWidth; 243193323Sed BufferDesc->Integer.Value = 0; 244193323Sed Buffer = &BufferDesc->Integer.Value; 245193323Sed } 246193323Sed 247193323Sed ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 248193323Sed "Obj=%p Type=%X Buf=%p Len=%X\n", 249193323Sed ObjDesc, ACPI_GET_OBJECT_TYPE (ObjDesc), Buffer, Length)); 250193323Sed ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 251193323Sed "FieldWrite: BitLen=%X BitOff=%X ByteOff=%X\n", 252193323Sed ObjDesc->CommonField.BitLength, 253193323Sed ObjDesc->CommonField.StartFieldBitOffset, 254193323Sed ObjDesc->CommonField.BaseByteOffset)); 255193323Sed 256193323Sed /* Lock entire transaction if requested */ 257193323Sed 258193323Sed Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 259193323Sed 260193323Sed /* Read from the field */ 261193323Sed 262193323Sed Status = AcpiExExtractFromField (ObjDesc, Buffer, Length); 263193323Sed AcpiExReleaseGlobalLock (Locked); 264193323Sed 265193323Sed 266193323SedExit: 267193323Sed if (ACPI_FAILURE (Status)) 268193323Sed { 269193323Sed AcpiUtRemoveReference (BufferDesc); 270193323Sed } 271193323Sed else if (RetBufferDesc) 272193323Sed { 273193323Sed *RetBufferDesc = BufferDesc; 274193323Sed } 275193323Sed 276193323Sed return_ACPI_STATUS (Status); 277193323Sed} 278193323Sed 279193323Sed 280193323Sed/******************************************************************************* 281193323Sed * 282193323Sed * FUNCTION: AcpiExWriteDataToField 283193323Sed * 284193323Sed * PARAMETERS: SourceDesc - Contains data to write 285193323Sed * ObjDesc - The named field 286193323Sed * 287193323Sed * RETURN: Status 288193323Sed * 289193323Sed * DESCRIPTION: Write to a named field 290193323Sed * 291193323Sed ******************************************************************************/ 292193323Sed 293193323SedACPI_STATUS 294193323SedAcpiExWriteDataToField ( 295193323Sed ACPI_OPERAND_OBJECT *SourceDesc, 296193323Sed ACPI_OPERAND_OBJECT *ObjDesc, 297193323Sed ACPI_OPERAND_OBJECT **ResultDesc) 298193323Sed{ 299193323Sed ACPI_STATUS Status; 300193323Sed UINT32 Length; 301193323Sed UINT32 RequiredLength; 302193323Sed void *Buffer; 303193323Sed void *NewBuffer; 304193323Sed BOOLEAN Locked; 305193323Sed ACPI_OPERAND_OBJECT *BufferDesc; 306193323Sed 307193323Sed 308193323Sed ACPI_FUNCTION_TRACE_PTR ("ExWriteDataToField", ObjDesc); 309193323Sed 310193323Sed 311193323Sed /* Parameter validation */ 312193323Sed 313193323Sed if (!SourceDesc || !ObjDesc) 314193323Sed { 315193323Sed return_ACPI_STATUS (AE_AML_NO_OPERAND); 316193323Sed } 317193323Sed 318193323Sed if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD) 319193323Sed { 320193323Sed /* 321193323Sed * If the BufferField arguments have not been previously evaluated, 322193323Sed * evaluate them now and save the results. 323193323Sed */ 324193323Sed if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 325193323Sed { 326193323Sed Status = AcpiDsGetBufferFieldArguments (ObjDesc); 327193323Sed if (ACPI_FAILURE (Status)) 328193323Sed { 329193323Sed return_ACPI_STATUS (Status); 330193323Sed } 331193323Sed } 332193323Sed } 333193323Sed else if ((ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_LOCAL_REGION_FIELD) && 334193323Sed (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS)) 335193323Sed { 336193323Sed /* 337193323Sed * This is an SMBus write. We will bypass the entire field mechanism 338193323Sed * and handoff the buffer directly to the handler. 339193323Sed * 340193323Sed * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). 341193323Sed */ 342193323Sed if (ACPI_GET_OBJECT_TYPE (SourceDesc) != ACPI_TYPE_BUFFER) 343193323Sed { 344193323Sed ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n", 345193323Sed AcpiUtGetObjectTypeName (SourceDesc))); 346193323Sed return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 347193323Sed } 348193323Sed 349193323Sed if (SourceDesc->Buffer.Length < ACPI_SMBUS_BUFFER_SIZE) 350193323Sed { 351193323Sed ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n", 352193323Sed ACPI_SMBUS_BUFFER_SIZE, SourceDesc->Buffer.Length)); 353193323Sed return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 354193323Sed } 355193323Sed 356193323Sed BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE); 357193323Sed if (!BufferDesc) 358193323Sed { 359193323Sed return_ACPI_STATUS (AE_NO_MEMORY); 360193323Sed } 361193323Sed 362193323Sed Buffer = BufferDesc->Buffer.Pointer; 363193323Sed ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer, ACPI_SMBUS_BUFFER_SIZE); 364193323Sed 365193323Sed /* Lock entire transaction if requested */ 366193323Sed 367193323Sed Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 368193323Sed 369193323Sed /* 370193323Sed * Perform the write (returns status and perhaps data in the same buffer) 371193323Sed * Note: SMBus protocol type is passed in upper 16-bits of Function. 372193323Sed */ 373193323Sed Status = AcpiExAccessRegion (ObjDesc, 0, 374193323Sed (ACPI_INTEGER *) Buffer, 375193323Sed ACPI_WRITE | (ObjDesc->Field.Attribute << 16)); 376193323Sed AcpiExReleaseGlobalLock (Locked); 377193323Sed 378193323Sed *ResultDesc = BufferDesc; 379193323Sed return_ACPI_STATUS (Status); 380193323Sed } 381193323Sed 382193323Sed /* 383193323Sed * Get a pointer to the data to be written 384193323Sed */ 385193323Sed switch (ACPI_GET_OBJECT_TYPE (SourceDesc)) 386193323Sed { 387193323Sed case ACPI_TYPE_INTEGER: 388193323Sed Buffer = &SourceDesc->Integer.Value; 389193323Sed Length = sizeof (SourceDesc->Integer.Value); 390193323Sed break; 391193323Sed 392193323Sed case ACPI_TYPE_BUFFER: 393193323Sed Buffer = SourceDesc->Buffer.Pointer; 394193323Sed Length = SourceDesc->Buffer.Length; 395193323Sed break; 396193323Sed 397193323Sed case ACPI_TYPE_STRING: 398193323Sed Buffer = SourceDesc->String.Pointer; 399193323Sed Length = SourceDesc->String.Length; 400193323Sed break; 401193323Sed 402193323Sed default: 403193323Sed return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 404193323Sed } 405193323Sed 406193323Sed /* 407193323Sed * We must have a buffer that is at least as long as the field 408193323Sed * we are writing to. This is because individual fields are 409193323Sed * indivisible and partial writes are not supported -- as per 410193323Sed * the ACPI specification. 411193323Sed */ 412193323Sed NewBuffer = NULL; 413193323Sed RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength); 414193323Sed 415193323Sed if (Length < RequiredLength) 416193323Sed { 417193323Sed /* We need to create a new buffer */ 418193323Sed 419193323Sed NewBuffer = ACPI_MEM_CALLOCATE (RequiredLength); 420193323Sed if (!NewBuffer) 421193323Sed { 422193323Sed return_ACPI_STATUS (AE_NO_MEMORY); 423193323Sed } 424193323Sed 425193323Sed /* 426193323Sed * Copy the original data to the new buffer, starting 427193323Sed * at Byte zero. All unused (upper) bytes of the 428193323Sed * buffer will be 0. 429193323Sed */ 430193323Sed ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, Length); 431193323Sed Buffer = NewBuffer; 432193323Sed Length = RequiredLength; 433193323Sed } 434193323Sed 435193323Sed ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 436193323Sed "Obj=%p Type=%X Buf=%p Len=%X\n", 437193323Sed ObjDesc, ACPI_GET_OBJECT_TYPE (ObjDesc), Buffer, Length)); 438193323Sed ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 439193323Sed "FieldRead: BitLen=%X BitOff=%X ByteOff=%X\n", 440193323Sed ObjDesc->CommonField.BitLength, 441193323Sed ObjDesc->CommonField.StartFieldBitOffset, 442193323Sed ObjDesc->CommonField.BaseByteOffset)); 443193323Sed 444193323Sed /* Lock entire transaction if requested */ 445193323Sed 446193323Sed Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 447193323Sed 448193323Sed /* Write to the field */ 449193323Sed 450193323Sed Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); 451193323Sed AcpiExReleaseGlobalLock (Locked); 452193323Sed 453193323Sed /* Free temporary buffer if we used one */ 454193323Sed 455193323Sed if (NewBuffer) 456193323Sed { 457193323Sed ACPI_MEM_FREE (NewBuffer); 458193323Sed } 459193323Sed 460193323Sed return_ACPI_STATUS (Status); 461193323Sed} 462193323Sed 463193323Sed 464193323Sed