exfield.c revision 1.1.1.4.2.3
11.1Sjruoho/****************************************************************************** 21.1Sjruoho * 31.1Sjruoho * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 41.1Sjruoho * 51.1Sjruoho *****************************************************************************/ 61.1Sjruoho 71.1.1.2Sjruoho/* 81.1.1.4.2.3Sskrll * Copyright (C) 2000 - 2016, Intel Corp. 91.1Sjruoho * All rights reserved. 101.1Sjruoho * 111.1.1.2Sjruoho * Redistribution and use in source and binary forms, with or without 121.1.1.2Sjruoho * modification, are permitted provided that the following conditions 131.1.1.2Sjruoho * are met: 141.1.1.2Sjruoho * 1. Redistributions of source code must retain the above copyright 151.1.1.2Sjruoho * notice, this list of conditions, and the following disclaimer, 161.1.1.2Sjruoho * without modification. 171.1.1.2Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer 181.1.1.2Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below 191.1.1.2Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon 201.1.1.2Sjruoho * including a substantially similar Disclaimer requirement for further 211.1.1.2Sjruoho * binary redistribution. 221.1.1.2Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names 231.1.1.2Sjruoho * of any contributors may be used to endorse or promote products derived 241.1.1.2Sjruoho * from this software without specific prior written permission. 251.1.1.2Sjruoho * 261.1.1.2Sjruoho * Alternatively, this software may be distributed under the terms of the 271.1.1.2Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free 281.1.1.2Sjruoho * Software Foundation. 291.1.1.2Sjruoho * 301.1.1.2Sjruoho * NO WARRANTY 311.1.1.2Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 321.1.1.2Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 331.1.1.2Sjruoho * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 341.1.1.2Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 351.1.1.2Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 361.1.1.2Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 371.1.1.2Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 381.1.1.2Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 391.1.1.2Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 401.1.1.2Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 411.1.1.2Sjruoho * POSSIBILITY OF SUCH DAMAGES. 421.1.1.2Sjruoho */ 431.1Sjruoho 441.1Sjruoho#include "acpi.h" 451.1Sjruoho#include "accommon.h" 461.1Sjruoho#include "acdispat.h" 471.1Sjruoho#include "acinterp.h" 481.1.1.4Schristos#include "amlcode.h" 491.1Sjruoho 501.1Sjruoho 511.1Sjruoho#define _COMPONENT ACPI_EXECUTER 521.1Sjruoho ACPI_MODULE_NAME ("exfield") 531.1Sjruoho 541.1.1.4Schristos/* Local prototypes */ 551.1.1.4Schristos 561.1.1.4Schristosstatic UINT32 571.1.1.4SchristosAcpiExGetSerialAccessLength ( 581.1.1.4Schristos UINT32 AccessorType, 591.1.1.4Schristos UINT32 AccessLength); 601.1.1.4Schristos 611.1.1.4Schristos 621.1.1.4Schristos/******************************************************************************* 631.1.1.4Schristos * 641.1.1.4Schristos * FUNCTION: AcpiExGetSerialAccessLength 651.1.1.4Schristos * 661.1.1.4Schristos * PARAMETERS: AccessorType - The type of the protocol indicated by region 671.1.1.4Schristos * field access attributes 681.1.1.4Schristos * AccessLength - The access length of the region field 691.1.1.4Schristos * 701.1.1.4Schristos * RETURN: Decoded access length 711.1.1.4Schristos * 721.1.1.4Schristos * DESCRIPTION: This routine returns the length of the GenericSerialBus 731.1.1.4Schristos * protocol bytes 741.1.1.4Schristos * 751.1.1.4Schristos ******************************************************************************/ 761.1.1.4Schristos 771.1.1.4Schristosstatic UINT32 781.1.1.4SchristosAcpiExGetSerialAccessLength ( 791.1.1.4Schristos UINT32 AccessorType, 801.1.1.4Schristos UINT32 AccessLength) 811.1.1.4Schristos{ 821.1.1.4Schristos UINT32 Length; 831.1.1.4Schristos 841.1.1.4Schristos 851.1.1.4Schristos switch (AccessorType) 861.1.1.4Schristos { 871.1.1.4Schristos case AML_FIELD_ATTRIB_QUICK: 881.1.1.4Schristos 891.1.1.4Schristos Length = 0; 901.1.1.4Schristos break; 911.1.1.4Schristos 921.1.1.4Schristos case AML_FIELD_ATTRIB_SEND_RCV: 931.1.1.4Schristos case AML_FIELD_ATTRIB_BYTE: 941.1.1.4Schristos 951.1.1.4Schristos Length = 1; 961.1.1.4Schristos break; 971.1.1.4Schristos 981.1.1.4Schristos case AML_FIELD_ATTRIB_WORD: 991.1.1.4Schristos case AML_FIELD_ATTRIB_WORD_CALL: 1001.1.1.4Schristos 1011.1.1.4Schristos Length = 2; 1021.1.1.4Schristos break; 1031.1.1.4Schristos 1041.1.1.4Schristos case AML_FIELD_ATTRIB_MULTIBYTE: 1051.1.1.4Schristos case AML_FIELD_ATTRIB_RAW_BYTES: 1061.1.1.4Schristos case AML_FIELD_ATTRIB_RAW_PROCESS: 1071.1.1.4Schristos 1081.1.1.4Schristos Length = AccessLength; 1091.1.1.4Schristos break; 1101.1.1.4Schristos 1111.1.1.4Schristos case AML_FIELD_ATTRIB_BLOCK: 1121.1.1.4Schristos case AML_FIELD_ATTRIB_BLOCK_CALL: 1131.1.1.4Schristos default: 1141.1.1.4Schristos 1151.1.1.4Schristos Length = ACPI_GSBUS_BUFFER_SIZE - 2; 1161.1.1.4Schristos break; 1171.1.1.4Schristos } 1181.1.1.4Schristos 1191.1.1.4Schristos return (Length); 1201.1.1.4Schristos} 1211.1.1.4Schristos 1221.1Sjruoho 1231.1Sjruoho/******************************************************************************* 1241.1Sjruoho * 1251.1Sjruoho * FUNCTION: AcpiExReadDataFromField 1261.1Sjruoho * 1271.1Sjruoho * PARAMETERS: WalkState - Current execution state 1281.1Sjruoho * ObjDesc - The named field 1291.1Sjruoho * RetBufferDesc - Where the return data object is stored 1301.1Sjruoho * 1311.1Sjruoho * RETURN: Status 1321.1Sjruoho * 1331.1.1.3Schristos * DESCRIPTION: Read from a named field. Returns either an Integer or a 1341.1Sjruoho * Buffer, depending on the size of the field. 1351.1Sjruoho * 1361.1Sjruoho ******************************************************************************/ 1371.1Sjruoho 1381.1SjruohoACPI_STATUS 1391.1SjruohoAcpiExReadDataFromField ( 1401.1Sjruoho ACPI_WALK_STATE *WalkState, 1411.1Sjruoho ACPI_OPERAND_OBJECT *ObjDesc, 1421.1Sjruoho ACPI_OPERAND_OBJECT **RetBufferDesc) 1431.1Sjruoho{ 1441.1Sjruoho ACPI_STATUS Status; 1451.1Sjruoho ACPI_OPERAND_OBJECT *BufferDesc; 1461.1Sjruoho ACPI_SIZE Length; 1471.1Sjruoho void *Buffer; 1481.1Sjruoho UINT32 Function; 1491.1.1.4Schristos UINT16 AccessorType; 1501.1Sjruoho 1511.1Sjruoho 1521.1Sjruoho ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc); 1531.1Sjruoho 1541.1Sjruoho 1551.1Sjruoho /* Parameter validation */ 1561.1Sjruoho 1571.1Sjruoho if (!ObjDesc) 1581.1Sjruoho { 1591.1Sjruoho return_ACPI_STATUS (AE_AML_NO_OPERAND); 1601.1Sjruoho } 1611.1Sjruoho if (!RetBufferDesc) 1621.1Sjruoho { 1631.1Sjruoho return_ACPI_STATUS (AE_BAD_PARAMETER); 1641.1Sjruoho } 1651.1Sjruoho 1661.1Sjruoho if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 1671.1Sjruoho { 1681.1Sjruoho /* 1691.1Sjruoho * If the BufferField arguments have not been previously evaluated, 1701.1Sjruoho * evaluate them now and save the results. 1711.1Sjruoho */ 1721.1Sjruoho if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 1731.1Sjruoho { 1741.1Sjruoho Status = AcpiDsGetBufferFieldArguments (ObjDesc); 1751.1Sjruoho if (ACPI_FAILURE (Status)) 1761.1Sjruoho { 1771.1Sjruoho return_ACPI_STATUS (Status); 1781.1Sjruoho } 1791.1Sjruoho } 1801.1Sjruoho } 1811.1Sjruoho else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 1821.1Sjruoho (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 1831.1.1.3Schristos ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 1841.1Sjruoho ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 1851.1Sjruoho { 1861.1Sjruoho /* 1871.1.1.4.2.3Sskrll * This is an SMBus, GSBus or IPMI read. We must create a buffer to 1881.1.1.4.2.3Sskrll * hold the data and then directly access the region handler. 1891.1Sjruoho * 1901.1.1.4.2.3Sskrll * Note: SMBus and GSBus protocol value is passed in upper 16-bits 1911.1.1.4.2.3Sskrll * of Function 1921.1Sjruoho */ 1931.1.1.4.2.3Sskrll if (ObjDesc->Field.RegionObj->Region.SpaceId == 1941.1.1.4.2.3Sskrll ACPI_ADR_SPACE_SMBUS) 1951.1Sjruoho { 1961.1Sjruoho Length = ACPI_SMBUS_BUFFER_SIZE; 1971.1Sjruoho Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); 1981.1Sjruoho } 1991.1.1.4.2.3Sskrll else if (ObjDesc->Field.RegionObj->Region.SpaceId == 2001.1.1.4.2.3Sskrll ACPI_ADR_SPACE_GSBUS) 2011.1.1.3Schristos { 2021.1.1.4Schristos AccessorType = ObjDesc->Field.Attribute; 2031.1.1.4.2.3Sskrll Length = AcpiExGetSerialAccessLength ( 2041.1.1.4.2.3Sskrll AccessorType, ObjDesc->Field.AccessLength); 2051.1.1.4Schristos 2061.1.1.4Schristos /* 2071.1.1.4Schristos * Add additional 2 bytes for the GenericSerialBus data buffer: 2081.1.1.4Schristos * 2091.1.1.4.2.3Sskrll * Status; (Byte 0 of the data buffer) 2101.1.1.4.2.3Sskrll * Length; (Byte 1 of the data buffer) 2111.1.1.4.2.3Sskrll * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 2121.1.1.4Schristos */ 2131.1.1.4Schristos Length += 2; 2141.1.1.4Schristos Function = ACPI_READ | (AccessorType << 16); 2151.1.1.3Schristos } 2161.1Sjruoho else /* IPMI */ 2171.1Sjruoho { 2181.1Sjruoho Length = ACPI_IPMI_BUFFER_SIZE; 2191.1Sjruoho Function = ACPI_READ; 2201.1Sjruoho } 2211.1Sjruoho 2221.1Sjruoho BufferDesc = AcpiUtCreateBufferObject (Length); 2231.1Sjruoho if (!BufferDesc) 2241.1Sjruoho { 2251.1Sjruoho return_ACPI_STATUS (AE_NO_MEMORY); 2261.1Sjruoho } 2271.1Sjruoho 2281.1Sjruoho /* Lock entire transaction if requested */ 2291.1Sjruoho 2301.1Sjruoho AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 2311.1Sjruoho 2321.1Sjruoho /* Call the region handler for the read */ 2331.1Sjruoho 2341.1Sjruoho Status = AcpiExAccessRegion (ObjDesc, 0, 2351.1.1.4.2.3Sskrll ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); 2361.1.1.4.2.3Sskrll 2371.1Sjruoho AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 2381.1Sjruoho goto Exit; 2391.1Sjruoho } 2401.1Sjruoho 2411.1Sjruoho /* 2421.1Sjruoho * Allocate a buffer for the contents of the field. 2431.1Sjruoho * 2441.1Sjruoho * If the field is larger than the current integer width, create 2451.1.1.3Schristos * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 2461.1Sjruoho * the use of arithmetic operators on the returned value if the 2471.1Sjruoho * field size is equal or smaller than an Integer. 2481.1Sjruoho * 2491.1Sjruoho * Note: Field.length is in bits. 2501.1Sjruoho */ 2511.1.1.4.2.3Sskrll Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( 2521.1.1.4.2.3Sskrll ObjDesc->Field.BitLength); 2531.1.1.4.2.3Sskrll 2541.1Sjruoho if (Length > AcpiGbl_IntegerByteWidth) 2551.1Sjruoho { 2561.1Sjruoho /* Field is too large for an Integer, create a Buffer instead */ 2571.1Sjruoho 2581.1Sjruoho BufferDesc = AcpiUtCreateBufferObject (Length); 2591.1Sjruoho if (!BufferDesc) 2601.1Sjruoho { 2611.1Sjruoho return_ACPI_STATUS (AE_NO_MEMORY); 2621.1Sjruoho } 2631.1Sjruoho Buffer = BufferDesc->Buffer.Pointer; 2641.1Sjruoho } 2651.1Sjruoho else 2661.1Sjruoho { 2671.1Sjruoho /* Field will fit within an Integer (normal case) */ 2681.1Sjruoho 2691.1Sjruoho BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 2701.1Sjruoho if (!BufferDesc) 2711.1Sjruoho { 2721.1Sjruoho return_ACPI_STATUS (AE_NO_MEMORY); 2731.1Sjruoho } 2741.1Sjruoho 2751.1Sjruoho Length = AcpiGbl_IntegerByteWidth; 2761.1Sjruoho Buffer = &BufferDesc->Integer.Value; 2771.1Sjruoho } 2781.1Sjruoho 2791.1.1.4Schristos if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 2801.1.1.4Schristos (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 2811.1.1.4Schristos { 2821.1.1.4Schristos /* 2831.1.1.4Schristos * For GPIO (GeneralPurposeIo), the Address will be the bit offset 2841.1.1.4Schristos * from the previous Connection() operator, making it effectively a 2851.1.1.4Schristos * pin number index. The BitLength is the length of the field, which 2861.1.1.4Schristos * is thus the number of pins. 2871.1.1.4Schristos */ 2881.1.1.4Schristos ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 2891.1.1.4Schristos "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 2901.1.1.4Schristos ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 2911.1.1.4Schristos 2921.1.1.4Schristos /* Lock entire transaction if requested */ 2931.1.1.4Schristos 2941.1.1.4Schristos AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 2951.1.1.4Schristos 2961.1.1.4Schristos /* Perform the write */ 2971.1.1.4Schristos 2981.1.1.4.2.3Sskrll Status = AcpiExAccessRegion ( 2991.1.1.4.2.3Sskrll ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); 3001.1.1.4.2.3Sskrll 3011.1.1.4Schristos AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 3021.1.1.4Schristos if (ACPI_FAILURE (Status)) 3031.1.1.4Schristos { 3041.1.1.4Schristos AcpiUtRemoveReference (BufferDesc); 3051.1.1.4Schristos } 3061.1.1.4Schristos else 3071.1.1.4Schristos { 3081.1.1.4Schristos *RetBufferDesc = BufferDesc; 3091.1.1.4Schristos } 3101.1.1.4Schristos return_ACPI_STATUS (Status); 3111.1.1.4Schristos } 3121.1.1.4Schristos 3131.1Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 3141.1Sjruoho "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", 3151.1Sjruoho ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); 3161.1Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 3171.1Sjruoho "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", 3181.1Sjruoho ObjDesc->CommonField.BitLength, 3191.1Sjruoho ObjDesc->CommonField.StartFieldBitOffset, 3201.1Sjruoho ObjDesc->CommonField.BaseByteOffset)); 3211.1Sjruoho 3221.1Sjruoho /* Lock entire transaction if requested */ 3231.1Sjruoho 3241.1Sjruoho AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 3251.1Sjruoho 3261.1Sjruoho /* Read from the field */ 3271.1Sjruoho 3281.1Sjruoho Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); 3291.1Sjruoho AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 3301.1Sjruoho 3311.1Sjruoho 3321.1SjruohoExit: 3331.1Sjruoho if (ACPI_FAILURE (Status)) 3341.1Sjruoho { 3351.1Sjruoho AcpiUtRemoveReference (BufferDesc); 3361.1Sjruoho } 3371.1Sjruoho else 3381.1Sjruoho { 3391.1Sjruoho *RetBufferDesc = BufferDesc; 3401.1Sjruoho } 3411.1Sjruoho 3421.1Sjruoho return_ACPI_STATUS (Status); 3431.1Sjruoho} 3441.1Sjruoho 3451.1Sjruoho 3461.1Sjruoho/******************************************************************************* 3471.1Sjruoho * 3481.1Sjruoho * FUNCTION: AcpiExWriteDataToField 3491.1Sjruoho * 3501.1Sjruoho * PARAMETERS: SourceDesc - Contains data to write 3511.1Sjruoho * ObjDesc - The named field 3521.1Sjruoho * ResultDesc - Where the return value is returned, if any 3531.1Sjruoho * 3541.1Sjruoho * RETURN: Status 3551.1Sjruoho * 3561.1Sjruoho * DESCRIPTION: Write to a named field 3571.1Sjruoho * 3581.1Sjruoho ******************************************************************************/ 3591.1Sjruoho 3601.1SjruohoACPI_STATUS 3611.1SjruohoAcpiExWriteDataToField ( 3621.1Sjruoho ACPI_OPERAND_OBJECT *SourceDesc, 3631.1Sjruoho ACPI_OPERAND_OBJECT *ObjDesc, 3641.1Sjruoho ACPI_OPERAND_OBJECT **ResultDesc) 3651.1Sjruoho{ 3661.1Sjruoho ACPI_STATUS Status; 3671.1Sjruoho UINT32 Length; 3681.1Sjruoho void *Buffer; 3691.1Sjruoho ACPI_OPERAND_OBJECT *BufferDesc; 3701.1Sjruoho UINT32 Function; 3711.1.1.4Schristos UINT16 AccessorType; 3721.1Sjruoho 3731.1Sjruoho 3741.1Sjruoho ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); 3751.1Sjruoho 3761.1Sjruoho 3771.1Sjruoho /* Parameter validation */ 3781.1Sjruoho 3791.1Sjruoho if (!SourceDesc || !ObjDesc) 3801.1Sjruoho { 3811.1Sjruoho return_ACPI_STATUS (AE_AML_NO_OPERAND); 3821.1Sjruoho } 3831.1Sjruoho 3841.1Sjruoho if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 3851.1Sjruoho { 3861.1Sjruoho /* 3871.1Sjruoho * If the BufferField arguments have not been previously evaluated, 3881.1Sjruoho * evaluate them now and save the results. 3891.1Sjruoho */ 3901.1Sjruoho if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 3911.1Sjruoho { 3921.1Sjruoho Status = AcpiDsGetBufferFieldArguments (ObjDesc); 3931.1Sjruoho if (ACPI_FAILURE (Status)) 3941.1Sjruoho { 3951.1Sjruoho return_ACPI_STATUS (Status); 3961.1Sjruoho } 3971.1Sjruoho } 3981.1Sjruoho } 3991.1Sjruoho else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 4001.1Sjruoho (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 4011.1.1.3Schristos ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 4021.1Sjruoho ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 4031.1Sjruoho { 4041.1Sjruoho /* 4051.1.1.4.2.3Sskrll * This is an SMBus, GSBus or IPMI write. We will bypass the entire 4061.1.1.4.2.3Sskrll * field mechanism and handoff the buffer directly to the handler. 4071.1.1.4.2.3Sskrll * For these address spaces, the buffer is bi-directional; on a 4081.1.1.4.2.3Sskrll * write, return data is returned in the same buffer. 4091.1Sjruoho * 4101.1Sjruoho * Source must be a buffer of sufficient size: 4111.1.1.4.2.3Sskrll * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or 4121.1.1.4.2.3Sskrll * ACPI_IPMI_BUFFER_SIZE. 4131.1Sjruoho * 4141.1.1.4.2.3Sskrll * Note: SMBus and GSBus protocol type is passed in upper 16-bits 4151.1.1.4.2.3Sskrll * of Function 4161.1Sjruoho */ 4171.1Sjruoho if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) 4181.1Sjruoho { 4191.1Sjruoho ACPI_ERROR ((AE_INFO, 4201.1.1.4.2.3Sskrll "SMBus/IPMI/GenericSerialBus write requires " 4211.1.1.4.2.3Sskrll "Buffer, found type %s", 4221.1Sjruoho AcpiUtGetObjectTypeName (SourceDesc))); 4231.1Sjruoho 4241.1Sjruoho return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 4251.1Sjruoho } 4261.1Sjruoho 4271.1.1.4.2.3Sskrll if (ObjDesc->Field.RegionObj->Region.SpaceId == 4281.1.1.4.2.3Sskrll ACPI_ADR_SPACE_SMBUS) 4291.1Sjruoho { 4301.1Sjruoho Length = ACPI_SMBUS_BUFFER_SIZE; 4311.1Sjruoho Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); 4321.1Sjruoho } 4331.1.1.4.2.3Sskrll else if (ObjDesc->Field.RegionObj->Region.SpaceId == 4341.1.1.4.2.3Sskrll ACPI_ADR_SPACE_GSBUS) 4351.1.1.3Schristos { 4361.1.1.4Schristos AccessorType = ObjDesc->Field.Attribute; 4371.1.1.4.2.3Sskrll Length = AcpiExGetSerialAccessLength ( 4381.1.1.4.2.3Sskrll AccessorType, ObjDesc->Field.AccessLength); 4391.1.1.4Schristos 4401.1.1.4Schristos /* 4411.1.1.4Schristos * Add additional 2 bytes for the GenericSerialBus data buffer: 4421.1.1.4Schristos * 4431.1.1.4.2.3Sskrll * Status; (Byte 0 of the data buffer) 4441.1.1.4.2.3Sskrll * Length; (Byte 1 of the data buffer) 4451.1.1.4.2.3Sskrll * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 4461.1.1.4Schristos */ 4471.1.1.4Schristos Length += 2; 4481.1.1.4Schristos Function = ACPI_WRITE | (AccessorType << 16); 4491.1.1.3Schristos } 4501.1Sjruoho else /* IPMI */ 4511.1Sjruoho { 4521.1Sjruoho Length = ACPI_IPMI_BUFFER_SIZE; 4531.1Sjruoho Function = ACPI_WRITE; 4541.1Sjruoho } 4551.1Sjruoho 4561.1Sjruoho if (SourceDesc->Buffer.Length < Length) 4571.1Sjruoho { 4581.1Sjruoho ACPI_ERROR ((AE_INFO, 4591.1.1.4.2.3Sskrll "SMBus/IPMI/GenericSerialBus write requires " 4601.1.1.4.2.3Sskrll "Buffer of length %u, found length %u", 4611.1Sjruoho Length, SourceDesc->Buffer.Length)); 4621.1Sjruoho 4631.1Sjruoho return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 4641.1Sjruoho } 4651.1Sjruoho 4661.1Sjruoho /* Create the bi-directional buffer */ 4671.1Sjruoho 4681.1Sjruoho BufferDesc = AcpiUtCreateBufferObject (Length); 4691.1Sjruoho if (!BufferDesc) 4701.1Sjruoho { 4711.1Sjruoho return_ACPI_STATUS (AE_NO_MEMORY); 4721.1Sjruoho } 4731.1Sjruoho 4741.1Sjruoho Buffer = BufferDesc->Buffer.Pointer; 4751.1.1.4.2.2Sskrll memcpy (Buffer, SourceDesc->Buffer.Pointer, Length); 4761.1Sjruoho 4771.1Sjruoho /* Lock entire transaction if requested */ 4781.1Sjruoho 4791.1Sjruoho AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 4801.1Sjruoho 4811.1Sjruoho /* 4821.1Sjruoho * Perform the write (returns status and perhaps data in the 4831.1Sjruoho * same buffer) 4841.1Sjruoho */ 4851.1.1.4.2.3Sskrll Status = AcpiExAccessRegion ( 4861.1.1.4.2.3Sskrll ObjDesc, 0, (UINT64 *) Buffer, Function); 4871.1Sjruoho AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 4881.1Sjruoho 4891.1Sjruoho *ResultDesc = BufferDesc; 4901.1Sjruoho return_ACPI_STATUS (Status); 4911.1Sjruoho } 4921.1.1.4Schristos else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 4931.1.1.4Schristos (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 4941.1.1.4Schristos { 4951.1.1.4Schristos /* 4961.1.1.4Schristos * For GPIO (GeneralPurposeIo), we will bypass the entire field 4971.1.1.4Schristos * mechanism and handoff the bit address and bit width directly to 4981.1.1.4Schristos * the handler. The Address will be the bit offset 4991.1.1.4Schristos * from the previous Connection() operator, making it effectively a 5001.1.1.4Schristos * pin number index. The BitLength is the length of the field, which 5011.1.1.4Schristos * is thus the number of pins. 5021.1.1.4Schristos */ 5031.1.1.4Schristos if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) 5041.1.1.4Schristos { 5051.1.1.4Schristos return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 5061.1.1.4Schristos } 5071.1.1.4Schristos 5081.1.1.4Schristos ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 5091.1.1.4.2.3Sskrll "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", 5101.1.1.4Schristos AcpiUtGetTypeName (SourceDesc->Common.Type), 5111.1.1.4Schristos SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, 5121.1.1.4Schristos ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 5131.1.1.4Schristos 5141.1.1.4Schristos Buffer = &SourceDesc->Integer.Value; 5151.1.1.4Schristos 5161.1.1.4Schristos /* Lock entire transaction if requested */ 5171.1.1.4Schristos 5181.1.1.4Schristos AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 5191.1.1.4Schristos 5201.1.1.4Schristos /* Perform the write */ 5211.1.1.4Schristos 5221.1.1.4.2.3Sskrll Status = AcpiExAccessRegion ( 5231.1.1.4.2.3Sskrll ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); 5241.1.1.4Schristos AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 5251.1.1.4Schristos return_ACPI_STATUS (Status); 5261.1.1.4Schristos } 5271.1Sjruoho 5281.1Sjruoho /* Get a pointer to the data to be written */ 5291.1Sjruoho 5301.1Sjruoho switch (SourceDesc->Common.Type) 5311.1Sjruoho { 5321.1Sjruoho case ACPI_TYPE_INTEGER: 5331.1.1.3Schristos 5341.1Sjruoho Buffer = &SourceDesc->Integer.Value; 5351.1Sjruoho Length = sizeof (SourceDesc->Integer.Value); 5361.1Sjruoho break; 5371.1Sjruoho 5381.1Sjruoho case ACPI_TYPE_BUFFER: 5391.1.1.3Schristos 5401.1Sjruoho Buffer = SourceDesc->Buffer.Pointer; 5411.1Sjruoho Length = SourceDesc->Buffer.Length; 5421.1Sjruoho break; 5431.1Sjruoho 5441.1Sjruoho case ACPI_TYPE_STRING: 5451.1.1.3Schristos 5461.1Sjruoho Buffer = SourceDesc->String.Pointer; 5471.1Sjruoho Length = SourceDesc->String.Length; 5481.1Sjruoho break; 5491.1Sjruoho 5501.1Sjruoho default: 5511.1.1.3Schristos 5521.1Sjruoho return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 5531.1Sjruoho } 5541.1Sjruoho 5551.1Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 5561.1Sjruoho "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", 5571.1Sjruoho SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), 5581.1Sjruoho SourceDesc->Common.Type, Buffer, Length)); 5591.1Sjruoho 5601.1Sjruoho ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 5611.1Sjruoho "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", 5621.1Sjruoho ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type), 5631.1Sjruoho ObjDesc->Common.Type, 5641.1Sjruoho ObjDesc->CommonField.BitLength, 5651.1Sjruoho ObjDesc->CommonField.StartFieldBitOffset, 5661.1Sjruoho ObjDesc->CommonField.BaseByteOffset)); 5671.1Sjruoho 5681.1Sjruoho /* Lock entire transaction if requested */ 5691.1Sjruoho 5701.1Sjruoho AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 5711.1Sjruoho 5721.1Sjruoho /* Write to the field */ 5731.1Sjruoho 5741.1Sjruoho Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); 5751.1Sjruoho AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 5761.1Sjruoho 5771.1Sjruoho return_ACPI_STATUS (Status); 5781.1Sjruoho} 579