1db2bae30SDana Myers /****************************************************************************** 2db2bae30SDana Myers * 3db2bae30SDana Myers * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 4db2bae30SDana Myers * 5db2bae30SDana Myers *****************************************************************************/ 6db2bae30SDana Myers 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9db2bae30SDana Myers * All rights reserved. 10db2bae30SDana Myers * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25db2bae30SDana Myers * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29db2bae30SDana Myers * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43db2bae30SDana Myers 44db2bae30SDana Myers #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46db2bae30SDana Myers #include "acdispat.h" 47db2bae30SDana Myers #include "acinterp.h" 48*385cc6b4SJerry Jelinek #include "amlcode.h" 49db2bae30SDana Myers 50db2bae30SDana Myers 51db2bae30SDana Myers #define _COMPONENT ACPI_EXECUTER 52db2bae30SDana Myers ACPI_MODULE_NAME ("exfield") 53db2bae30SDana Myers 54*385cc6b4SJerry Jelinek /* Local prototypes */ 55*385cc6b4SJerry Jelinek 56*385cc6b4SJerry Jelinek static UINT32 57*385cc6b4SJerry Jelinek AcpiExGetSerialAccessLength ( 58*385cc6b4SJerry Jelinek UINT32 AccessorType, 59*385cc6b4SJerry Jelinek UINT32 AccessLength); 60*385cc6b4SJerry Jelinek 61*385cc6b4SJerry Jelinek 62*385cc6b4SJerry Jelinek /******************************************************************************* 63*385cc6b4SJerry Jelinek * 64*385cc6b4SJerry Jelinek * FUNCTION: AcpiExGetSerialAccessLength 65*385cc6b4SJerry Jelinek * 66*385cc6b4SJerry Jelinek * PARAMETERS: AccessorType - The type of the protocol indicated by region 67*385cc6b4SJerry Jelinek * field access attributes 68*385cc6b4SJerry Jelinek * AccessLength - The access length of the region field 69*385cc6b4SJerry Jelinek * 70*385cc6b4SJerry Jelinek * RETURN: Decoded access length 71*385cc6b4SJerry Jelinek * 72*385cc6b4SJerry Jelinek * DESCRIPTION: This routine returns the length of the GenericSerialBus 73*385cc6b4SJerry Jelinek * protocol bytes 74*385cc6b4SJerry Jelinek * 75*385cc6b4SJerry Jelinek ******************************************************************************/ 76*385cc6b4SJerry Jelinek 77*385cc6b4SJerry Jelinek static UINT32 78*385cc6b4SJerry Jelinek AcpiExGetSerialAccessLength ( 79*385cc6b4SJerry Jelinek UINT32 AccessorType, 80*385cc6b4SJerry Jelinek UINT32 AccessLength) 81*385cc6b4SJerry Jelinek { 82*385cc6b4SJerry Jelinek UINT32 Length; 83*385cc6b4SJerry Jelinek 84*385cc6b4SJerry Jelinek 85*385cc6b4SJerry Jelinek switch (AccessorType) 86*385cc6b4SJerry Jelinek { 87*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_QUICK: 88*385cc6b4SJerry Jelinek 89*385cc6b4SJerry Jelinek Length = 0; 90*385cc6b4SJerry Jelinek break; 91*385cc6b4SJerry Jelinek 92*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_SEND_RCV: 93*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_BYTE: 94*385cc6b4SJerry Jelinek 95*385cc6b4SJerry Jelinek Length = 1; 96*385cc6b4SJerry Jelinek break; 97*385cc6b4SJerry Jelinek 98*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_WORD: 99*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_WORD_CALL: 100*385cc6b4SJerry Jelinek 101*385cc6b4SJerry Jelinek Length = 2; 102*385cc6b4SJerry Jelinek break; 103*385cc6b4SJerry Jelinek 104*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_MULTIBYTE: 105*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_RAW_BYTES: 106*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_RAW_PROCESS: 107*385cc6b4SJerry Jelinek 108*385cc6b4SJerry Jelinek Length = AccessLength; 109*385cc6b4SJerry Jelinek break; 110*385cc6b4SJerry Jelinek 111*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_BLOCK: 112*385cc6b4SJerry Jelinek case AML_FIELD_ATTRIB_BLOCK_CALL: 113*385cc6b4SJerry Jelinek default: 114*385cc6b4SJerry Jelinek 115*385cc6b4SJerry Jelinek Length = ACPI_GSBUS_BUFFER_SIZE - 2; 116*385cc6b4SJerry Jelinek break; 117*385cc6b4SJerry Jelinek } 118*385cc6b4SJerry Jelinek 119*385cc6b4SJerry Jelinek return (Length); 120*385cc6b4SJerry Jelinek } 121*385cc6b4SJerry Jelinek 122db2bae30SDana Myers 123db2bae30SDana Myers /******************************************************************************* 124db2bae30SDana Myers * 125db2bae30SDana Myers * FUNCTION: AcpiExReadDataFromField 126db2bae30SDana Myers * 127db2bae30SDana Myers * PARAMETERS: WalkState - Current execution state 128db2bae30SDana Myers * ObjDesc - The named field 129db2bae30SDana Myers * RetBufferDesc - Where the return data object is stored 130db2bae30SDana Myers * 131db2bae30SDana Myers * RETURN: Status 132db2bae30SDana Myers * 133db2bae30SDana Myers * DESCRIPTION: Read from a named field. Returns either an Integer or a 134db2bae30SDana Myers * Buffer, depending on the size of the field. 135db2bae30SDana Myers * 136db2bae30SDana Myers ******************************************************************************/ 137db2bae30SDana Myers 138db2bae30SDana Myers ACPI_STATUS 139db2bae30SDana Myers AcpiExReadDataFromField ( 140db2bae30SDana Myers ACPI_WALK_STATE *WalkState, 141db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc, 142db2bae30SDana Myers ACPI_OPERAND_OBJECT **RetBufferDesc) 143db2bae30SDana Myers { 144db2bae30SDana Myers ACPI_STATUS Status; 145db2bae30SDana Myers ACPI_OPERAND_OBJECT *BufferDesc; 146db2bae30SDana Myers ACPI_SIZE Length; 147db2bae30SDana Myers void *Buffer; 14857190917SDana Myers UINT32 Function; 149*385cc6b4SJerry Jelinek UINT16 AccessorType; 150db2bae30SDana Myers 151db2bae30SDana Myers 152db2bae30SDana Myers ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc); 153db2bae30SDana Myers 154db2bae30SDana Myers 155db2bae30SDana Myers /* Parameter validation */ 156db2bae30SDana Myers 157db2bae30SDana Myers if (!ObjDesc) 158db2bae30SDana Myers { 159db2bae30SDana Myers return_ACPI_STATUS (AE_AML_NO_OPERAND); 160db2bae30SDana Myers } 161db2bae30SDana Myers if (!RetBufferDesc) 162db2bae30SDana Myers { 163db2bae30SDana Myers return_ACPI_STATUS (AE_BAD_PARAMETER); 164db2bae30SDana Myers } 165db2bae30SDana Myers 166aa2aa9a6SDana Myers if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 167db2bae30SDana Myers { 168db2bae30SDana Myers /* 169db2bae30SDana Myers * If the BufferField arguments have not been previously evaluated, 170db2bae30SDana Myers * evaluate them now and save the results. 171db2bae30SDana Myers */ 172db2bae30SDana Myers if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 173db2bae30SDana Myers { 174db2bae30SDana Myers Status = AcpiDsGetBufferFieldArguments (ObjDesc); 175db2bae30SDana Myers if (ACPI_FAILURE (Status)) 176db2bae30SDana Myers { 177db2bae30SDana Myers return_ACPI_STATUS (Status); 178db2bae30SDana Myers } 179db2bae30SDana Myers } 180db2bae30SDana Myers } 181aa2aa9a6SDana Myers else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 18257190917SDana Myers (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 183*385cc6b4SJerry Jelinek ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 18457190917SDana Myers ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 185db2bae30SDana Myers { 186db2bae30SDana Myers /* 187*385cc6b4SJerry Jelinek * This is an SMBus, GSBus or IPMI read. We must create a buffer to 188*385cc6b4SJerry Jelinek * hold the data and then directly access the region handler. 18957190917SDana Myers * 190*385cc6b4SJerry Jelinek * Note: SMBus and GSBus protocol value is passed in upper 16-bits 191*385cc6b4SJerry Jelinek * of Function 192db2bae30SDana Myers */ 193*385cc6b4SJerry Jelinek if (ObjDesc->Field.RegionObj->Region.SpaceId == 194*385cc6b4SJerry Jelinek ACPI_ADR_SPACE_SMBUS) 19557190917SDana Myers { 19657190917SDana Myers Length = ACPI_SMBUS_BUFFER_SIZE; 19757190917SDana Myers Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); 19857190917SDana Myers } 199*385cc6b4SJerry Jelinek else if (ObjDesc->Field.RegionObj->Region.SpaceId == 200*385cc6b4SJerry Jelinek ACPI_ADR_SPACE_GSBUS) 201*385cc6b4SJerry Jelinek { 202*385cc6b4SJerry Jelinek AccessorType = ObjDesc->Field.Attribute; 203*385cc6b4SJerry Jelinek Length = AcpiExGetSerialAccessLength ( 204*385cc6b4SJerry Jelinek AccessorType, ObjDesc->Field.AccessLength); 205*385cc6b4SJerry Jelinek 206*385cc6b4SJerry Jelinek /* 207*385cc6b4SJerry Jelinek * Add additional 2 bytes for the GenericSerialBus data buffer: 208*385cc6b4SJerry Jelinek * 209*385cc6b4SJerry Jelinek * Status; (Byte 0 of the data buffer) 210*385cc6b4SJerry Jelinek * Length; (Byte 1 of the data buffer) 211*385cc6b4SJerry Jelinek * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 212*385cc6b4SJerry Jelinek */ 213*385cc6b4SJerry Jelinek Length += 2; 214*385cc6b4SJerry Jelinek Function = ACPI_READ | (AccessorType << 16); 215*385cc6b4SJerry Jelinek } 21657190917SDana Myers else /* IPMI */ 21757190917SDana Myers { 21857190917SDana Myers Length = ACPI_IPMI_BUFFER_SIZE; 21957190917SDana Myers Function = ACPI_READ; 22057190917SDana Myers } 22157190917SDana Myers 22257190917SDana Myers BufferDesc = AcpiUtCreateBufferObject (Length); 223db2bae30SDana Myers if (!BufferDesc) 224db2bae30SDana Myers { 225db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 226db2bae30SDana Myers } 227db2bae30SDana Myers 228db2bae30SDana Myers /* Lock entire transaction if requested */ 229db2bae30SDana Myers 230db2bae30SDana Myers AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 231db2bae30SDana Myers 23257190917SDana Myers /* Call the region handler for the read */ 23357190917SDana Myers 234db2bae30SDana Myers Status = AcpiExAccessRegion (ObjDesc, 0, 235*385cc6b4SJerry Jelinek ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); 236*385cc6b4SJerry Jelinek 237db2bae30SDana Myers AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 238db2bae30SDana Myers goto Exit; 239db2bae30SDana Myers } 240db2bae30SDana Myers 241db2bae30SDana Myers /* 242db2bae30SDana Myers * Allocate a buffer for the contents of the field. 243db2bae30SDana Myers * 24426f3cdf0SGordon Ross * If the field is larger than the current integer width, create 245db2bae30SDana Myers * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 246db2bae30SDana Myers * the use of arithmetic operators on the returned value if the 247db2bae30SDana Myers * field size is equal or smaller than an Integer. 248db2bae30SDana Myers * 249db2bae30SDana Myers * Note: Field.length is in bits. 250db2bae30SDana Myers */ 251*385cc6b4SJerry Jelinek Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( 252*385cc6b4SJerry Jelinek ObjDesc->Field.BitLength); 253*385cc6b4SJerry Jelinek 254db2bae30SDana Myers if (Length > AcpiGbl_IntegerByteWidth) 255db2bae30SDana Myers { 256db2bae30SDana Myers /* Field is too large for an Integer, create a Buffer instead */ 257db2bae30SDana Myers 258db2bae30SDana Myers BufferDesc = AcpiUtCreateBufferObject (Length); 259db2bae30SDana Myers if (!BufferDesc) 260db2bae30SDana Myers { 261db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 262db2bae30SDana Myers } 263db2bae30SDana Myers Buffer = BufferDesc->Buffer.Pointer; 264db2bae30SDana Myers } 265db2bae30SDana Myers else 266db2bae30SDana Myers { 267db2bae30SDana Myers /* Field will fit within an Integer (normal case) */ 268db2bae30SDana Myers 26957190917SDana Myers BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 270db2bae30SDana Myers if (!BufferDesc) 271db2bae30SDana Myers { 272db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 273db2bae30SDana Myers } 274db2bae30SDana Myers 275db2bae30SDana Myers Length = AcpiGbl_IntegerByteWidth; 276db2bae30SDana Myers Buffer = &BufferDesc->Integer.Value; 277db2bae30SDana Myers } 278db2bae30SDana Myers 279*385cc6b4SJerry Jelinek if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 280*385cc6b4SJerry Jelinek (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 281*385cc6b4SJerry Jelinek { 282*385cc6b4SJerry Jelinek /* 283*385cc6b4SJerry Jelinek * For GPIO (GeneralPurposeIo), the Address will be the bit offset 284*385cc6b4SJerry Jelinek * from the previous Connection() operator, making it effectively a 285*385cc6b4SJerry Jelinek * pin number index. The BitLength is the length of the field, which 286*385cc6b4SJerry Jelinek * is thus the number of pins. 287*385cc6b4SJerry Jelinek */ 288*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 289*385cc6b4SJerry Jelinek "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 290*385cc6b4SJerry Jelinek ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 291*385cc6b4SJerry Jelinek 292*385cc6b4SJerry Jelinek /* Lock entire transaction if requested */ 293*385cc6b4SJerry Jelinek 294*385cc6b4SJerry Jelinek AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 295*385cc6b4SJerry Jelinek 296*385cc6b4SJerry Jelinek /* Perform the write */ 297*385cc6b4SJerry Jelinek 298*385cc6b4SJerry Jelinek Status = AcpiExAccessRegion ( 299*385cc6b4SJerry Jelinek ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); 300*385cc6b4SJerry Jelinek 301*385cc6b4SJerry Jelinek AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 302*385cc6b4SJerry Jelinek if (ACPI_FAILURE (Status)) 303*385cc6b4SJerry Jelinek { 304*385cc6b4SJerry Jelinek AcpiUtRemoveReference (BufferDesc); 305*385cc6b4SJerry Jelinek } 306*385cc6b4SJerry Jelinek else 307*385cc6b4SJerry Jelinek { 308*385cc6b4SJerry Jelinek *RetBufferDesc = BufferDesc; 309*385cc6b4SJerry Jelinek } 310*385cc6b4SJerry Jelinek return_ACPI_STATUS (Status); 311*385cc6b4SJerry Jelinek } 312*385cc6b4SJerry Jelinek 313db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 314db2bae30SDana Myers "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", 315aa2aa9a6SDana Myers ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); 316db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 317db2bae30SDana Myers "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", 318db2bae30SDana Myers ObjDesc->CommonField.BitLength, 319db2bae30SDana Myers ObjDesc->CommonField.StartFieldBitOffset, 320db2bae30SDana Myers ObjDesc->CommonField.BaseByteOffset)); 321db2bae30SDana Myers 322db2bae30SDana Myers /* Lock entire transaction if requested */ 323db2bae30SDana Myers 324db2bae30SDana Myers AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 325db2bae30SDana Myers 326db2bae30SDana Myers /* Read from the field */ 327db2bae30SDana Myers 328db2bae30SDana Myers Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); 329db2bae30SDana Myers AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 330db2bae30SDana Myers 331db2bae30SDana Myers 332db2bae30SDana Myers Exit: 333db2bae30SDana Myers if (ACPI_FAILURE (Status)) 334db2bae30SDana Myers { 335db2bae30SDana Myers AcpiUtRemoveReference (BufferDesc); 336db2bae30SDana Myers } 337db2bae30SDana Myers else 338db2bae30SDana Myers { 339db2bae30SDana Myers *RetBufferDesc = BufferDesc; 340db2bae30SDana Myers } 341db2bae30SDana Myers 342db2bae30SDana Myers return_ACPI_STATUS (Status); 343db2bae30SDana Myers } 344db2bae30SDana Myers 345db2bae30SDana Myers 346db2bae30SDana Myers /******************************************************************************* 347db2bae30SDana Myers * 348db2bae30SDana Myers * FUNCTION: AcpiExWriteDataToField 349db2bae30SDana Myers * 350db2bae30SDana Myers * PARAMETERS: SourceDesc - Contains data to write 351db2bae30SDana Myers * ObjDesc - The named field 352db2bae30SDana Myers * ResultDesc - Where the return value is returned, if any 353db2bae30SDana Myers * 354db2bae30SDana Myers * RETURN: Status 355db2bae30SDana Myers * 356db2bae30SDana Myers * DESCRIPTION: Write to a named field 357db2bae30SDana Myers * 358db2bae30SDana Myers ******************************************************************************/ 359db2bae30SDana Myers 360db2bae30SDana Myers ACPI_STATUS 361db2bae30SDana Myers AcpiExWriteDataToField ( 362db2bae30SDana Myers ACPI_OPERAND_OBJECT *SourceDesc, 363db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc, 364db2bae30SDana Myers ACPI_OPERAND_OBJECT **ResultDesc) 365db2bae30SDana Myers { 366db2bae30SDana Myers ACPI_STATUS Status; 367db2bae30SDana Myers UINT32 Length; 368db2bae30SDana Myers void *Buffer; 369db2bae30SDana Myers ACPI_OPERAND_OBJECT *BufferDesc; 37057190917SDana Myers UINT32 Function; 371*385cc6b4SJerry Jelinek UINT16 AccessorType; 372db2bae30SDana Myers 373db2bae30SDana Myers 374db2bae30SDana Myers ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); 375db2bae30SDana Myers 376db2bae30SDana Myers 377db2bae30SDana Myers /* Parameter validation */ 378db2bae30SDana Myers 379db2bae30SDana Myers if (!SourceDesc || !ObjDesc) 380db2bae30SDana Myers { 381db2bae30SDana Myers return_ACPI_STATUS (AE_AML_NO_OPERAND); 382db2bae30SDana Myers } 383db2bae30SDana Myers 384aa2aa9a6SDana Myers if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 385db2bae30SDana Myers { 386db2bae30SDana Myers /* 387db2bae30SDana Myers * If the BufferField arguments have not been previously evaluated, 388db2bae30SDana Myers * evaluate them now and save the results. 389db2bae30SDana Myers */ 390db2bae30SDana Myers if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 391db2bae30SDana Myers { 392db2bae30SDana Myers Status = AcpiDsGetBufferFieldArguments (ObjDesc); 393db2bae30SDana Myers if (ACPI_FAILURE (Status)) 394db2bae30SDana Myers { 395db2bae30SDana Myers return_ACPI_STATUS (Status); 396db2bae30SDana Myers } 397db2bae30SDana Myers } 398db2bae30SDana Myers } 399aa2aa9a6SDana Myers else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 40057190917SDana Myers (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 401*385cc6b4SJerry Jelinek ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 40257190917SDana Myers ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 403db2bae30SDana Myers { 404db2bae30SDana Myers /* 405*385cc6b4SJerry Jelinek * This is an SMBus, GSBus or IPMI write. We will bypass the entire 406*385cc6b4SJerry Jelinek * field mechanism and handoff the buffer directly to the handler. 407*385cc6b4SJerry Jelinek * For these address spaces, the buffer is bi-directional; on a 408*385cc6b4SJerry Jelinek * write, return data is returned in the same buffer. 409db2bae30SDana Myers * 41057190917SDana Myers * Source must be a buffer of sufficient size: 411*385cc6b4SJerry Jelinek * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or 412*385cc6b4SJerry Jelinek * ACPI_IPMI_BUFFER_SIZE. 41357190917SDana Myers * 414*385cc6b4SJerry Jelinek * Note: SMBus and GSBus protocol type is passed in upper 16-bits 415*385cc6b4SJerry Jelinek * of Function 416db2bae30SDana Myers */ 417aa2aa9a6SDana Myers if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) 418db2bae30SDana Myers { 41957190917SDana Myers ACPI_ERROR ((AE_INFO, 420*385cc6b4SJerry Jelinek "SMBus/IPMI/GenericSerialBus write requires " 421*385cc6b4SJerry Jelinek "Buffer, found type %s", 422db2bae30SDana Myers AcpiUtGetObjectTypeName (SourceDesc))); 423db2bae30SDana Myers 424db2bae30SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 425db2bae30SDana Myers } 426db2bae30SDana Myers 427*385cc6b4SJerry Jelinek if (ObjDesc->Field.RegionObj->Region.SpaceId == 428*385cc6b4SJerry Jelinek ACPI_ADR_SPACE_SMBUS) 42957190917SDana Myers { 43057190917SDana Myers Length = ACPI_SMBUS_BUFFER_SIZE; 43157190917SDana Myers Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); 43257190917SDana Myers } 433*385cc6b4SJerry Jelinek else if (ObjDesc->Field.RegionObj->Region.SpaceId == 434*385cc6b4SJerry Jelinek ACPI_ADR_SPACE_GSBUS) 435*385cc6b4SJerry Jelinek { 436*385cc6b4SJerry Jelinek AccessorType = ObjDesc->Field.Attribute; 437*385cc6b4SJerry Jelinek Length = AcpiExGetSerialAccessLength ( 438*385cc6b4SJerry Jelinek AccessorType, ObjDesc->Field.AccessLength); 439*385cc6b4SJerry Jelinek 440*385cc6b4SJerry Jelinek /* 441*385cc6b4SJerry Jelinek * Add additional 2 bytes for the GenericSerialBus data buffer: 442*385cc6b4SJerry Jelinek * 443*385cc6b4SJerry Jelinek * Status; (Byte 0 of the data buffer) 444*385cc6b4SJerry Jelinek * Length; (Byte 1 of the data buffer) 445*385cc6b4SJerry Jelinek * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 446*385cc6b4SJerry Jelinek */ 447*385cc6b4SJerry Jelinek Length += 2; 448*385cc6b4SJerry Jelinek Function = ACPI_WRITE | (AccessorType << 16); 449*385cc6b4SJerry Jelinek } 45057190917SDana Myers else /* IPMI */ 45157190917SDana Myers { 45257190917SDana Myers Length = ACPI_IPMI_BUFFER_SIZE; 45357190917SDana Myers Function = ACPI_WRITE; 45457190917SDana Myers } 45557190917SDana Myers 45657190917SDana Myers if (SourceDesc->Buffer.Length < Length) 457db2bae30SDana Myers { 458db2bae30SDana Myers ACPI_ERROR ((AE_INFO, 459*385cc6b4SJerry Jelinek "SMBus/IPMI/GenericSerialBus write requires " 460*385cc6b4SJerry Jelinek "Buffer of length %u, found length %u", 46157190917SDana Myers Length, SourceDesc->Buffer.Length)); 462db2bae30SDana Myers 463db2bae30SDana Myers return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 464db2bae30SDana Myers } 465db2bae30SDana Myers 46657190917SDana Myers /* Create the bi-directional buffer */ 46757190917SDana Myers 46857190917SDana Myers BufferDesc = AcpiUtCreateBufferObject (Length); 469db2bae30SDana Myers if (!BufferDesc) 470db2bae30SDana Myers { 471db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 472db2bae30SDana Myers } 473db2bae30SDana Myers 474db2bae30SDana Myers Buffer = BufferDesc->Buffer.Pointer; 475*385cc6b4SJerry Jelinek memcpy (Buffer, SourceDesc->Buffer.Pointer, Length); 476db2bae30SDana Myers 477db2bae30SDana Myers /* Lock entire transaction if requested */ 478db2bae30SDana Myers 479db2bae30SDana Myers AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 480db2bae30SDana Myers 481db2bae30SDana Myers /* 482db2bae30SDana Myers * Perform the write (returns status and perhaps data in the 483db2bae30SDana Myers * same buffer) 484db2bae30SDana Myers */ 485*385cc6b4SJerry Jelinek Status = AcpiExAccessRegion ( 486*385cc6b4SJerry Jelinek ObjDesc, 0, (UINT64 *) Buffer, Function); 487db2bae30SDana Myers AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 488db2bae30SDana Myers 489db2bae30SDana Myers *ResultDesc = BufferDesc; 490db2bae30SDana Myers return_ACPI_STATUS (Status); 491db2bae30SDana Myers } 492*385cc6b4SJerry Jelinek else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 493*385cc6b4SJerry Jelinek (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 494*385cc6b4SJerry Jelinek { 495*385cc6b4SJerry Jelinek /* 496*385cc6b4SJerry Jelinek * For GPIO (GeneralPurposeIo), we will bypass the entire field 497*385cc6b4SJerry Jelinek * mechanism and handoff the bit address and bit width directly to 498*385cc6b4SJerry Jelinek * the handler. The Address will be the bit offset 499*385cc6b4SJerry Jelinek * from the previous Connection() operator, making it effectively a 500*385cc6b4SJerry Jelinek * pin number index. The BitLength is the length of the field, which 501*385cc6b4SJerry Jelinek * is thus the number of pins. 502*385cc6b4SJerry Jelinek */ 503*385cc6b4SJerry Jelinek if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) 504*385cc6b4SJerry Jelinek { 505*385cc6b4SJerry Jelinek return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 506*385cc6b4SJerry Jelinek } 507*385cc6b4SJerry Jelinek 508*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 509*385cc6b4SJerry Jelinek "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", 510*385cc6b4SJerry Jelinek AcpiUtGetTypeName (SourceDesc->Common.Type), 511*385cc6b4SJerry Jelinek SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, 512*385cc6b4SJerry Jelinek ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 513*385cc6b4SJerry Jelinek 514*385cc6b4SJerry Jelinek Buffer = &SourceDesc->Integer.Value; 515*385cc6b4SJerry Jelinek 516*385cc6b4SJerry Jelinek /* Lock entire transaction if requested */ 517*385cc6b4SJerry Jelinek 518*385cc6b4SJerry Jelinek AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 519*385cc6b4SJerry Jelinek 520*385cc6b4SJerry Jelinek /* Perform the write */ 521*385cc6b4SJerry Jelinek 522*385cc6b4SJerry Jelinek Status = AcpiExAccessRegion ( 523*385cc6b4SJerry Jelinek ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); 524*385cc6b4SJerry Jelinek AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 525*385cc6b4SJerry Jelinek return_ACPI_STATUS (Status); 526*385cc6b4SJerry Jelinek } 527db2bae30SDana Myers 528db2bae30SDana Myers /* Get a pointer to the data to be written */ 529db2bae30SDana Myers 530aa2aa9a6SDana Myers switch (SourceDesc->Common.Type) 531db2bae30SDana Myers { 532db2bae30SDana Myers case ACPI_TYPE_INTEGER: 533*385cc6b4SJerry Jelinek 534db2bae30SDana Myers Buffer = &SourceDesc->Integer.Value; 535db2bae30SDana Myers Length = sizeof (SourceDesc->Integer.Value); 536db2bae30SDana Myers break; 537db2bae30SDana Myers 538db2bae30SDana Myers case ACPI_TYPE_BUFFER: 539*385cc6b4SJerry Jelinek 540db2bae30SDana Myers Buffer = SourceDesc->Buffer.Pointer; 541db2bae30SDana Myers Length = SourceDesc->Buffer.Length; 542db2bae30SDana Myers break; 543db2bae30SDana Myers 544db2bae30SDana Myers case ACPI_TYPE_STRING: 545*385cc6b4SJerry Jelinek 546db2bae30SDana Myers Buffer = SourceDesc->String.Pointer; 547db2bae30SDana Myers Length = SourceDesc->String.Length; 548db2bae30SDana Myers break; 549db2bae30SDana Myers 550db2bae30SDana Myers default: 551*385cc6b4SJerry Jelinek 552db2bae30SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 553db2bae30SDana Myers } 554db2bae30SDana Myers 555db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 556db2bae30SDana Myers "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", 557aa2aa9a6SDana Myers SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), 558aa2aa9a6SDana Myers SourceDesc->Common.Type, Buffer, Length)); 559db2bae30SDana Myers 560db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 561db2bae30SDana Myers "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", 562aa2aa9a6SDana Myers ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type), 563aa2aa9a6SDana Myers ObjDesc->Common.Type, 564db2bae30SDana Myers ObjDesc->CommonField.BitLength, 565db2bae30SDana Myers ObjDesc->CommonField.StartFieldBitOffset, 566db2bae30SDana Myers ObjDesc->CommonField.BaseByteOffset)); 567db2bae30SDana Myers 568db2bae30SDana Myers /* Lock entire transaction if requested */ 569db2bae30SDana Myers 570db2bae30SDana Myers AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 571db2bae30SDana Myers 572db2bae30SDana Myers /* Write to the field */ 573db2bae30SDana Myers 574db2bae30SDana Myers Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); 575db2bae30SDana Myers AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 576db2bae30SDana Myers 577db2bae30SDana Myers return_ACPI_STATUS (Status); 578db2bae30SDana Myers } 579