167754Smsmith/****************************************************************************** 267754Smsmith * 377424Smsmith * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7316303Sjkim/****************************************************************************** 8316303Sjkim * 9316303Sjkim * 1. Copyright Notice 10316303Sjkim * 11316303Sjkim * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 1270243Smsmith * All rights reserved. 1367754Smsmith * 14316303Sjkim * 2. License 15316303Sjkim * 16316303Sjkim * 2.1. This is your license from Intel Corp. under its intellectual property 17316303Sjkim * rights. You may have additional license terms from the party that provided 18316303Sjkim * you this software, covering your right to use that party's intellectual 19316303Sjkim * property rights. 20316303Sjkim * 21316303Sjkim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22316303Sjkim * copy of the source code appearing in this file ("Covered Code") an 23316303Sjkim * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24316303Sjkim * base code distributed originally by Intel ("Original Intel Code") to copy, 25316303Sjkim * make derivatives, distribute, use and display any portion of the Covered 26316303Sjkim * Code in any form, with the right to sublicense such rights; and 27316303Sjkim * 28316303Sjkim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29316303Sjkim * license (with the right to sublicense), under only those claims of Intel 30316303Sjkim * patents that are infringed by the Original Intel Code, to make, use, sell, 31316303Sjkim * offer to sell, and import the Covered Code and derivative works thereof 32316303Sjkim * solely to the minimum extent necessary to exercise the above copyright 33316303Sjkim * license, and in no event shall the patent license extend to any additions 34316303Sjkim * to or modifications of the Original Intel Code. No other license or right 35316303Sjkim * is granted directly or by implication, estoppel or otherwise; 36316303Sjkim * 37316303Sjkim * The above copyright and patent license is granted only if the following 38316303Sjkim * conditions are met: 39316303Sjkim * 40316303Sjkim * 3. Conditions 41316303Sjkim * 42316303Sjkim * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43316303Sjkim * Redistribution of source code of any substantial portion of the Covered 44316303Sjkim * Code or modification with rights to further distribute source must include 45316303Sjkim * the above Copyright Notice, the above License, this list of Conditions, 46316303Sjkim * and the following Disclaimer and Export Compliance provision. In addition, 47316303Sjkim * Licensee must cause all Covered Code to which Licensee contributes to 48316303Sjkim * contain a file documenting the changes Licensee made to create that Covered 49316303Sjkim * Code and the date of any change. Licensee must include in that file the 50316303Sjkim * documentation of any changes made by any predecessor Licensee. Licensee 51316303Sjkim * must include a prominent statement that the modification is derived, 52316303Sjkim * directly or indirectly, from Original Intel Code. 53316303Sjkim * 54316303Sjkim * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55316303Sjkim * Redistribution of source code of any substantial portion of the Covered 56316303Sjkim * Code or modification without rights to further distribute source must 57316303Sjkim * include the following Disclaimer and Export Compliance provision in the 58316303Sjkim * documentation and/or other materials provided with distribution. In 59316303Sjkim * addition, Licensee may not authorize further sublicense of source of any 60316303Sjkim * portion of the Covered Code, and must include terms to the effect that the 61316303Sjkim * license from Licensee to its licensee is limited to the intellectual 62316303Sjkim * property embodied in the software Licensee provides to its licensee, and 63316303Sjkim * not to intellectual property embodied in modifications its licensee may 64316303Sjkim * make. 65316303Sjkim * 66316303Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any 67316303Sjkim * substantial portion of the Covered Code or modification must reproduce the 68316303Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance 69316303Sjkim * provision in the documentation and/or other materials provided with the 70316303Sjkim * distribution. 71316303Sjkim * 72316303Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original 73316303Sjkim * Intel Code. 74316303Sjkim * 75316303Sjkim * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76316303Sjkim * Intel shall be used in advertising or otherwise to promote the sale, use or 77316303Sjkim * other dealings in products derived from or relating to the Covered Code 78316303Sjkim * without prior written authorization from Intel. 79316303Sjkim * 80316303Sjkim * 4. Disclaimer and Export Compliance 81316303Sjkim * 82316303Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83316303Sjkim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84316303Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85316303Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86316303Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87316303Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88316303Sjkim * PARTICULAR PURPOSE. 89316303Sjkim * 90316303Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91316303Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92316303Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93316303Sjkim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94316303Sjkim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95316303Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96316303Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97316303Sjkim * LIMITED REMEDY. 98316303Sjkim * 99316303Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this 100316303Sjkim * software or system incorporating such software without first obtaining any 101316303Sjkim * required license or other approval from the U. S. Department of Commerce or 102316303Sjkim * any other agency or department of the United States Government. In the 103316303Sjkim * event Licensee exports any such software from the United States or 104316303Sjkim * re-exports any such software from a foreign destination, Licensee shall 105316303Sjkim * ensure that the distribution and export/re-export of the software is in 106316303Sjkim * compliance with all laws, regulations, orders, or other restrictions of the 107316303Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108316303Sjkim * any of its subsidiaries will export/re-export any technical data, process, 109316303Sjkim * software, or service, directly or indirectly, to any country for which the 110316303Sjkim * United States government or any agency thereof requires an export license, 111316303Sjkim * other governmental approval, or letter of assurance, without first obtaining 112316303Sjkim * such license, approval or letter. 113316303Sjkim * 114316303Sjkim ***************************************************************************** 115316303Sjkim * 116316303Sjkim * Alternatively, you may choose to be licensed under the terms of the 117316303Sjkim * following license: 118316303Sjkim * 119217365Sjkim * Redistribution and use in source and binary forms, with or without 120217365Sjkim * modification, are permitted provided that the following conditions 121217365Sjkim * are met: 122217365Sjkim * 1. Redistributions of source code must retain the above copyright 123217365Sjkim * notice, this list of conditions, and the following disclaimer, 124217365Sjkim * without modification. 125217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 127217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 128217365Sjkim * including a substantially similar Disclaimer requirement for further 129217365Sjkim * binary redistribution. 130217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 131217365Sjkim * of any contributors may be used to endorse or promote products derived 132217365Sjkim * from this software without specific prior written permission. 13367754Smsmith * 134316303Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135316303Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136316303Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137316303Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138316303Sjkim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139316303Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140316303Sjkim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141316303Sjkim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142316303Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143316303Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144316303Sjkim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145316303Sjkim * 146316303Sjkim * Alternatively, you may choose to be licensed under the terms of the 147217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 148217365Sjkim * Software Foundation. 14967754Smsmith * 150316303Sjkim *****************************************************************************/ 15167754Smsmith 152193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 153193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 154193341Sjkim#include <contrib/dev/acpica/include/acdispat.h> 155193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 156272444Sjkim#include <contrib/dev/acpica/include/amlcode.h> 15767754Smsmith 15867754Smsmith 15977424Smsmith#define _COMPONENT ACPI_EXECUTER 16091116Smsmith ACPI_MODULE_NAME ("exfield") 16167754Smsmith 162272444Sjkim/* Local prototypes */ 16367754Smsmith 164272444Sjkimstatic UINT32 165272444SjkimAcpiExGetSerialAccessLength ( 166272444Sjkim UINT32 AccessorType, 167272444Sjkim UINT32 AccessLength); 168272444Sjkim 169272444Sjkim 17067754Smsmith/******************************************************************************* 17167754Smsmith * 172272444Sjkim * FUNCTION: AcpiExGetSerialAccessLength 173272444Sjkim * 174272444Sjkim * PARAMETERS: AccessorType - The type of the protocol indicated by region 175272444Sjkim * field access attributes 176272444Sjkim * AccessLength - The access length of the region field 177272444Sjkim * 178272444Sjkim * RETURN: Decoded access length 179272444Sjkim * 180272444Sjkim * DESCRIPTION: This routine returns the length of the GenericSerialBus 181272444Sjkim * protocol bytes 182272444Sjkim * 183272444Sjkim ******************************************************************************/ 184272444Sjkim 185272444Sjkimstatic UINT32 186272444SjkimAcpiExGetSerialAccessLength ( 187272444Sjkim UINT32 AccessorType, 188272444Sjkim UINT32 AccessLength) 189272444Sjkim{ 190272444Sjkim UINT32 Length; 191272444Sjkim 192272444Sjkim 193272444Sjkim switch (AccessorType) 194272444Sjkim { 195272444Sjkim case AML_FIELD_ATTRIB_QUICK: 196272444Sjkim 197272444Sjkim Length = 0; 198272444Sjkim break; 199272444Sjkim 200272444Sjkim case AML_FIELD_ATTRIB_SEND_RCV: 201272444Sjkim case AML_FIELD_ATTRIB_BYTE: 202272444Sjkim 203272444Sjkim Length = 1; 204272444Sjkim break; 205272444Sjkim 206272444Sjkim case AML_FIELD_ATTRIB_WORD: 207272444Sjkim case AML_FIELD_ATTRIB_WORD_CALL: 208272444Sjkim 209272444Sjkim Length = 2; 210272444Sjkim break; 211272444Sjkim 212272444Sjkim case AML_FIELD_ATTRIB_MULTIBYTE: 213272444Sjkim case AML_FIELD_ATTRIB_RAW_BYTES: 214272444Sjkim case AML_FIELD_ATTRIB_RAW_PROCESS: 215272444Sjkim 216272444Sjkim Length = AccessLength; 217272444Sjkim break; 218272444Sjkim 219272444Sjkim case AML_FIELD_ATTRIB_BLOCK: 220272444Sjkim case AML_FIELD_ATTRIB_BLOCK_CALL: 221272444Sjkim default: 222272444Sjkim 223272444Sjkim Length = ACPI_GSBUS_BUFFER_SIZE - 2; 224272444Sjkim break; 225272444Sjkim } 226272444Sjkim 227272444Sjkim return (Length); 228272444Sjkim} 229272444Sjkim 230272444Sjkim 231272444Sjkim/******************************************************************************* 232272444Sjkim * 23377424Smsmith * FUNCTION: AcpiExReadDataFromField 23467754Smsmith * 23599146Siwasaki * PARAMETERS: WalkState - Current execution state 23699146Siwasaki * ObjDesc - The named field 23787031Smsmith * RetBufferDesc - Where the return data object is stored 23867754Smsmith * 23987031Smsmith * RETURN: Status 24067754Smsmith * 241241973Sjkim * DESCRIPTION: Read from a named field. Returns either an Integer or a 24287031Smsmith * Buffer, depending on the size of the field. 24367754Smsmith * 24467754Smsmith ******************************************************************************/ 24567754Smsmith 24667754SmsmithACPI_STATUS 24777424SmsmithAcpiExReadDataFromField ( 24899146Siwasaki ACPI_WALK_STATE *WalkState, 24967754Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 25077424Smsmith ACPI_OPERAND_OBJECT **RetBufferDesc) 25167754Smsmith{ 25277424Smsmith ACPI_STATUS Status; 25377424Smsmith ACPI_OPERAND_OBJECT *BufferDesc; 254114237Snjl ACPI_SIZE Length; 25577424Smsmith void *Buffer; 256197104Sjkim UINT32 Function; 257272444Sjkim UINT16 AccessorType; 25867754Smsmith 25967754Smsmith 260167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc); 26167754Smsmith 26267754Smsmith 26367754Smsmith /* Parameter validation */ 26467754Smsmith 26577424Smsmith if (!ObjDesc) 26667754Smsmith { 26767754Smsmith return_ACPI_STATUS (AE_AML_NO_OPERAND); 26867754Smsmith } 269151937Sjkim if (!RetBufferDesc) 270151937Sjkim { 271151937Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 272151937Sjkim } 27367754Smsmith 274193267Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 27587031Smsmith { 27687031Smsmith /* 27787031Smsmith * If the BufferField arguments have not been previously evaluated, 27887031Smsmith * evaluate them now and save the results. 27987031Smsmith */ 28087031Smsmith if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 28187031Smsmith { 28287031Smsmith Status = AcpiDsGetBufferFieldArguments (ObjDesc); 28387031Smsmith if (ACPI_FAILURE (Status)) 28487031Smsmith { 28587031Smsmith return_ACPI_STATUS (Status); 28687031Smsmith } 28787031Smsmith } 28887031Smsmith } 289193267Sjkim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 290197104Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 291228110Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 292197104Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 293107325Siwasaki { 294107325Siwasaki /* 295298714Sjkim * This is an SMBus, GSBus or IPMI read. We must create a buffer to 296298714Sjkim * hold the data and then directly access the region handler. 297197104Sjkim * 298298714Sjkim * Note: SMBus and GSBus protocol value is passed in upper 16-bits 299298714Sjkim * of Function 300107325Siwasaki */ 301298714Sjkim if (ObjDesc->Field.RegionObj->Region.SpaceId == 302298714Sjkim ACPI_ADR_SPACE_SMBUS) 303197104Sjkim { 304197104Sjkim Length = ACPI_SMBUS_BUFFER_SIZE; 305197104Sjkim Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); 306197104Sjkim } 307298714Sjkim else if (ObjDesc->Field.RegionObj->Region.SpaceId == 308298714Sjkim ACPI_ADR_SPACE_GSBUS) 309228110Sjkim { 310272444Sjkim AccessorType = ObjDesc->Field.Attribute; 311298714Sjkim Length = AcpiExGetSerialAccessLength ( 312298714Sjkim AccessorType, ObjDesc->Field.AccessLength); 313272444Sjkim 314272444Sjkim /* 315272444Sjkim * Add additional 2 bytes for the GenericSerialBus data buffer: 316272444Sjkim * 317298714Sjkim * Status; (Byte 0 of the data buffer) 318298714Sjkim * Length; (Byte 1 of the data buffer) 319298714Sjkim * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 320272444Sjkim */ 321272444Sjkim Length += 2; 322272444Sjkim Function = ACPI_READ | (AccessorType << 16); 323228110Sjkim } 324197104Sjkim else /* IPMI */ 325197104Sjkim { 326197104Sjkim Length = ACPI_IPMI_BUFFER_SIZE; 327197104Sjkim Function = ACPI_READ; 328197104Sjkim } 329197104Sjkim 330197104Sjkim BufferDesc = AcpiUtCreateBufferObject (Length); 331107325Siwasaki if (!BufferDesc) 332107325Siwasaki { 333107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 334107325Siwasaki } 33587031Smsmith 336107325Siwasaki /* Lock entire transaction if requested */ 337107325Siwasaki 338167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 339107325Siwasaki 340197104Sjkim /* Call the region handler for the read */ 341197104Sjkim 342114237Snjl Status = AcpiExAccessRegion (ObjDesc, 0, 343298714Sjkim ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); 344298714Sjkim 345167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 346107325Siwasaki goto Exit; 347107325Siwasaki } 348107325Siwasaki 34967754Smsmith /* 35077424Smsmith * Allocate a buffer for the contents of the field. 35167754Smsmith * 352202771Sjkim * If the field is larger than the current integer width, create 353241973Sjkim * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 35477424Smsmith * the use of arithmetic operators on the returned value if the 35577424Smsmith * field size is equal or smaller than an Integer. 35677424Smsmith * 35777424Smsmith * Note: Field.length is in bits. 35867754Smsmith */ 359298714Sjkim Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( 360298714Sjkim ObjDesc->Field.BitLength); 361298714Sjkim 36299679Siwasaki if (Length > AcpiGbl_IntegerByteWidth) 36367754Smsmith { 36477424Smsmith /* Field is too large for an Integer, create a Buffer instead */ 36567754Smsmith 366107325Siwasaki BufferDesc = AcpiUtCreateBufferObject (Length); 36777424Smsmith if (!BufferDesc) 36877424Smsmith { 36977424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 37077424Smsmith } 37177424Smsmith Buffer = BufferDesc->Buffer.Pointer; 37267754Smsmith } 37377424Smsmith else 37477424Smsmith { 37577424Smsmith /* Field will fit within an Integer (normal case) */ 37667754Smsmith 377199337Sjkim BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 37877424Smsmith if (!BufferDesc) 37977424Smsmith { 38077424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 38177424Smsmith } 38277424Smsmith 38399679Siwasaki Length = AcpiGbl_IntegerByteWidth; 38477424Smsmith Buffer = &BufferDesc->Integer.Value; 38567754Smsmith } 38667754Smsmith 387272444Sjkim if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 388272444Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 389272444Sjkim { 390272444Sjkim /* 391272444Sjkim * For GPIO (GeneralPurposeIo), the Address will be the bit offset 392272444Sjkim * from the previous Connection() operator, making it effectively a 393272444Sjkim * pin number index. The BitLength is the length of the field, which 394272444Sjkim * is thus the number of pins. 395272444Sjkim */ 396272444Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 397272444Sjkim "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 398272444Sjkim ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 399272444Sjkim 400272444Sjkim /* Lock entire transaction if requested */ 401272444Sjkim 402272444Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 403272444Sjkim 404272444Sjkim /* Perform the write */ 405272444Sjkim 406298714Sjkim Status = AcpiExAccessRegion ( 407298714Sjkim ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); 408298714Sjkim 409272444Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 410272444Sjkim if (ACPI_FAILURE (Status)) 411272444Sjkim { 412272444Sjkim AcpiUtRemoveReference (BufferDesc); 413272444Sjkim } 414272444Sjkim else 415272444Sjkim { 416272444Sjkim *RetBufferDesc = BufferDesc; 417272444Sjkim } 418272444Sjkim return_ACPI_STATUS (Status); 419272444Sjkim } 420272444Sjkim 42199146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 422123315Snjl "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", 423193267Sjkim ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); 42499146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 425123315Snjl "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", 42687031Smsmith ObjDesc->CommonField.BitLength, 42787031Smsmith ObjDesc->CommonField.StartFieldBitOffset, 42887031Smsmith ObjDesc->CommonField.BaseByteOffset)); 42977424Smsmith 430107325Siwasaki /* Lock entire transaction if requested */ 431107325Siwasaki 432167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 43377424Smsmith 43487031Smsmith /* Read from the field */ 43567754Smsmith 436114237Snjl Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); 437167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 43867754Smsmith 439107325Siwasaki 440107325SiwasakiExit: 44177424Smsmith if (ACPI_FAILURE (Status)) 44277424Smsmith { 44377424Smsmith AcpiUtRemoveReference (BufferDesc); 44477424Smsmith } 445151937Sjkim else 44677424Smsmith { 44777424Smsmith *RetBufferDesc = BufferDesc; 44877424Smsmith } 44977424Smsmith 45077424Smsmith return_ACPI_STATUS (Status); 45167754Smsmith} 45267754Smsmith 45367754Smsmith 45467754Smsmith/******************************************************************************* 45567754Smsmith * 45677424Smsmith * FUNCTION: AcpiExWriteDataToField 45767754Smsmith * 45887031Smsmith * PARAMETERS: SourceDesc - Contains data to write 45987031Smsmith * ObjDesc - The named field 460151937Sjkim * ResultDesc - Where the return value is returned, if any 46167754Smsmith * 46267754Smsmith * RETURN: Status 46367754Smsmith * 46487031Smsmith * DESCRIPTION: Write to a named field 46567754Smsmith * 46667754Smsmith ******************************************************************************/ 46767754Smsmith 46867754SmsmithACPI_STATUS 46977424SmsmithAcpiExWriteDataToField ( 47077424Smsmith ACPI_OPERAND_OBJECT *SourceDesc, 471107325Siwasaki ACPI_OPERAND_OBJECT *ObjDesc, 472107325Siwasaki ACPI_OPERAND_OBJECT **ResultDesc) 47367754Smsmith{ 47477424Smsmith ACPI_STATUS Status; 47577424Smsmith UINT32 Length; 47677424Smsmith void *Buffer; 477107325Siwasaki ACPI_OPERAND_OBJECT *BufferDesc; 478197104Sjkim UINT32 Function; 479272444Sjkim UINT16 AccessorType; 48067754Smsmith 48167754Smsmith 482167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); 48367754Smsmith 48467754Smsmith 48571867Smsmith /* Parameter validation */ 48671867Smsmith 48777424Smsmith if (!SourceDesc || !ObjDesc) 48867754Smsmith { 48977424Smsmith return_ACPI_STATUS (AE_AML_NO_OPERAND); 49067754Smsmith } 49167754Smsmith 492193267Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 49387031Smsmith { 49487031Smsmith /* 49587031Smsmith * If the BufferField arguments have not been previously evaluated, 49687031Smsmith * evaluate them now and save the results. 49787031Smsmith */ 49887031Smsmith if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 49987031Smsmith { 50087031Smsmith Status = AcpiDsGetBufferFieldArguments (ObjDesc); 50187031Smsmith if (ACPI_FAILURE (Status)) 50287031Smsmith { 50387031Smsmith return_ACPI_STATUS (Status); 50487031Smsmith } 50587031Smsmith } 50687031Smsmith } 507193267Sjkim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 508197104Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 509228110Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 510197104Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 511107325Siwasaki { 512107325Siwasaki /* 513298714Sjkim * This is an SMBus, GSBus or IPMI write. We will bypass the entire 514298714Sjkim * field mechanism and handoff the buffer directly to the handler. 515298714Sjkim * For these address spaces, the buffer is bi-directional; on a 516298714Sjkim * write, return data is returned in the same buffer. 517107325Siwasaki * 518197104Sjkim * Source must be a buffer of sufficient size: 519298714Sjkim * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or 520298714Sjkim * ACPI_IPMI_BUFFER_SIZE. 521197104Sjkim * 522298714Sjkim * Note: SMBus and GSBus protocol type is passed in upper 16-bits 523298714Sjkim * of Function 524107325Siwasaki */ 525193267Sjkim if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) 526107325Siwasaki { 527197104Sjkim ACPI_ERROR ((AE_INFO, 528298714Sjkim "SMBus/IPMI/GenericSerialBus write requires " 529298714Sjkim "Buffer, found type %s", 530107325Siwasaki AcpiUtGetObjectTypeName (SourceDesc))); 531151937Sjkim 532107325Siwasaki return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 533107325Siwasaki } 53467754Smsmith 535298714Sjkim if (ObjDesc->Field.RegionObj->Region.SpaceId == 536298714Sjkim ACPI_ADR_SPACE_SMBUS) 537107325Siwasaki { 538197104Sjkim Length = ACPI_SMBUS_BUFFER_SIZE; 539197104Sjkim Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); 540197104Sjkim } 541298714Sjkim else if (ObjDesc->Field.RegionObj->Region.SpaceId == 542298714Sjkim ACPI_ADR_SPACE_GSBUS) 543228110Sjkim { 544272444Sjkim AccessorType = ObjDesc->Field.Attribute; 545298714Sjkim Length = AcpiExGetSerialAccessLength ( 546298714Sjkim AccessorType, ObjDesc->Field.AccessLength); 547272444Sjkim 548272444Sjkim /* 549272444Sjkim * Add additional 2 bytes for the GenericSerialBus data buffer: 550272444Sjkim * 551298714Sjkim * Status; (Byte 0 of the data buffer) 552298714Sjkim * Length; (Byte 1 of the data buffer) 553298714Sjkim * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 554272444Sjkim */ 555272444Sjkim Length += 2; 556272444Sjkim Function = ACPI_WRITE | (AccessorType << 16); 557228110Sjkim } 558197104Sjkim else /* IPMI */ 559197104Sjkim { 560197104Sjkim Length = ACPI_IPMI_BUFFER_SIZE; 561197104Sjkim Function = ACPI_WRITE; 562197104Sjkim } 563197104Sjkim 564197104Sjkim if (SourceDesc->Buffer.Length < Length) 565197104Sjkim { 566167802Sjkim ACPI_ERROR ((AE_INFO, 567298714Sjkim "SMBus/IPMI/GenericSerialBus write requires " 568298714Sjkim "Buffer of length %u, found length %u", 569197104Sjkim Length, SourceDesc->Buffer.Length)); 570151937Sjkim 571107325Siwasaki return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 572107325Siwasaki } 573107325Siwasaki 574197104Sjkim /* Create the bi-directional buffer */ 575197104Sjkim 576197104Sjkim BufferDesc = AcpiUtCreateBufferObject (Length); 577107325Siwasaki if (!BufferDesc) 578107325Siwasaki { 579107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 580107325Siwasaki } 581107325Siwasaki 582107325Siwasaki Buffer = BufferDesc->Buffer.Pointer; 583284583Sjkim memcpy (Buffer, SourceDesc->Buffer.Pointer, Length); 584107325Siwasaki 585107325Siwasaki /* Lock entire transaction if requested */ 586107325Siwasaki 587167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 588107325Siwasaki 589114237Snjl /* 590151937Sjkim * Perform the write (returns status and perhaps data in the 591151937Sjkim * same buffer) 592107325Siwasaki */ 593298714Sjkim Status = AcpiExAccessRegion ( 594298714Sjkim ObjDesc, 0, (UINT64 *) Buffer, Function); 595167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 596107325Siwasaki 597107325Siwasaki *ResultDesc = BufferDesc; 598107325Siwasaki return_ACPI_STATUS (Status); 599107325Siwasaki } 600272444Sjkim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 601272444Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 602272444Sjkim { 603272444Sjkim /* 604272444Sjkim * For GPIO (GeneralPurposeIo), we will bypass the entire field 605272444Sjkim * mechanism and handoff the bit address and bit width directly to 606272444Sjkim * the handler. The Address will be the bit offset 607272444Sjkim * from the previous Connection() operator, making it effectively a 608272444Sjkim * pin number index. The BitLength is the length of the field, which 609272444Sjkim * is thus the number of pins. 610272444Sjkim */ 611272444Sjkim if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) 612272444Sjkim { 613272444Sjkim return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 614272444Sjkim } 615107325Siwasaki 616272444Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 617298714Sjkim "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", 618272444Sjkim AcpiUtGetTypeName (SourceDesc->Common.Type), 619272444Sjkim SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, 620272444Sjkim ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 621272444Sjkim 622272444Sjkim Buffer = &SourceDesc->Integer.Value; 623272444Sjkim 624272444Sjkim /* Lock entire transaction if requested */ 625272444Sjkim 626272444Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 627272444Sjkim 628272444Sjkim /* Perform the write */ 629272444Sjkim 630298714Sjkim Status = AcpiExAccessRegion ( 631298714Sjkim ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); 632272444Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 633272444Sjkim return_ACPI_STATUS (Status); 634272444Sjkim } 635272444Sjkim 636151937Sjkim /* Get a pointer to the data to be written */ 637151937Sjkim 638193267Sjkim switch (SourceDesc->Common.Type) 63967754Smsmith { 64077424Smsmith case ACPI_TYPE_INTEGER: 641250838Sjkim 64277424Smsmith Buffer = &SourceDesc->Integer.Value; 64377424Smsmith Length = sizeof (SourceDesc->Integer.Value); 64477424Smsmith break; 64577424Smsmith 64677424Smsmith case ACPI_TYPE_BUFFER: 647250838Sjkim 64877424Smsmith Buffer = SourceDesc->Buffer.Pointer; 64977424Smsmith Length = SourceDesc->Buffer.Length; 65077424Smsmith break; 65177424Smsmith 65277424Smsmith case ACPI_TYPE_STRING: 653250838Sjkim 65477424Smsmith Buffer = SourceDesc->String.Pointer; 65577424Smsmith Length = SourceDesc->String.Length; 65677424Smsmith break; 65777424Smsmith 65877424Smsmith default: 659250838Sjkim 66077424Smsmith return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 66167754Smsmith } 66267754Smsmith 66399146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 664123315Snjl "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", 665193267Sjkim SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), 666193267Sjkim SourceDesc->Common.Type, Buffer, Length)); 667151937Sjkim 66899146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 669123315Snjl "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", 670193267Sjkim ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type), 671193267Sjkim ObjDesc->Common.Type, 67287031Smsmith ObjDesc->CommonField.BitLength, 67387031Smsmith ObjDesc->CommonField.StartFieldBitOffset, 67487031Smsmith ObjDesc->CommonField.BaseByteOffset)); 67567754Smsmith 676107325Siwasaki /* Lock entire transaction if requested */ 677107325Siwasaki 678167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 67977424Smsmith 680107325Siwasaki /* Write to the field */ 681107325Siwasaki 68287031Smsmith Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); 683167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 68467754Smsmith 68577424Smsmith return_ACPI_STATUS (Status); 68677424Smsmith} 687