167754Smsmith/****************************************************************************** 267754Smsmith * 377424Smsmith * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acdispat.h> 47193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 48281075Sdim#include <contrib/dev/acpica/include/amlcode.h> 4967754Smsmith 5067754Smsmith 5177424Smsmith#define _COMPONENT ACPI_EXECUTER 5291116Smsmith ACPI_MODULE_NAME ("exfield") 5367754Smsmith 54281075Sdim/* Local prototypes */ 5567754Smsmith 56281075Sdimstatic UINT32 57281075SdimAcpiExGetSerialAccessLength ( 58281075Sdim UINT32 AccessorType, 59281075Sdim UINT32 AccessLength); 60281075Sdim 61281075Sdim 6267754Smsmith/******************************************************************************* 6367754Smsmith * 64281075Sdim * FUNCTION: AcpiExGetSerialAccessLength 65281075Sdim * 66281075Sdim * PARAMETERS: AccessorType - The type of the protocol indicated by region 67281075Sdim * field access attributes 68281075Sdim * AccessLength - The access length of the region field 69281075Sdim * 70281075Sdim * RETURN: Decoded access length 71281075Sdim * 72281075Sdim * DESCRIPTION: This routine returns the length of the GenericSerialBus 73281075Sdim * protocol bytes 74281075Sdim * 75281075Sdim ******************************************************************************/ 76281075Sdim 77281075Sdimstatic UINT32 78281075SdimAcpiExGetSerialAccessLength ( 79281075Sdim UINT32 AccessorType, 80281075Sdim UINT32 AccessLength) 81281075Sdim{ 82281075Sdim UINT32 Length; 83281075Sdim 84281075Sdim 85281075Sdim switch (AccessorType) 86281075Sdim { 87281075Sdim case AML_FIELD_ATTRIB_QUICK: 88281075Sdim 89281075Sdim Length = 0; 90281075Sdim break; 91281075Sdim 92281075Sdim case AML_FIELD_ATTRIB_SEND_RCV: 93281075Sdim case AML_FIELD_ATTRIB_BYTE: 94281075Sdim 95281075Sdim Length = 1; 96281075Sdim break; 97281075Sdim 98281075Sdim case AML_FIELD_ATTRIB_WORD: 99281075Sdim case AML_FIELD_ATTRIB_WORD_CALL: 100281075Sdim 101281075Sdim Length = 2; 102281075Sdim break; 103281075Sdim 104281075Sdim case AML_FIELD_ATTRIB_MULTIBYTE: 105281075Sdim case AML_FIELD_ATTRIB_RAW_BYTES: 106281075Sdim case AML_FIELD_ATTRIB_RAW_PROCESS: 107281075Sdim 108281075Sdim Length = AccessLength; 109281075Sdim break; 110281075Sdim 111281075Sdim case AML_FIELD_ATTRIB_BLOCK: 112281075Sdim case AML_FIELD_ATTRIB_BLOCK_CALL: 113281075Sdim default: 114281075Sdim 115281075Sdim Length = ACPI_GSBUS_BUFFER_SIZE - 2; 116281075Sdim break; 117281075Sdim } 118281075Sdim 119281075Sdim return (Length); 120281075Sdim} 121281075Sdim 122281075Sdim 123281075Sdim/******************************************************************************* 124281075Sdim * 12577424Smsmith * FUNCTION: AcpiExReadDataFromField 12667754Smsmith * 12799146Siwasaki * PARAMETERS: WalkState - Current execution state 12899146Siwasaki * ObjDesc - The named field 12987031Smsmith * RetBufferDesc - Where the return data object is stored 13067754Smsmith * 13187031Smsmith * RETURN: Status 13267754Smsmith * 133241973Sjkim * DESCRIPTION: Read from a named field. Returns either an Integer or a 13487031Smsmith * Buffer, depending on the size of the field. 13567754Smsmith * 13667754Smsmith ******************************************************************************/ 13767754Smsmith 13867754SmsmithACPI_STATUS 13977424SmsmithAcpiExReadDataFromField ( 14099146Siwasaki ACPI_WALK_STATE *WalkState, 14167754Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 14277424Smsmith ACPI_OPERAND_OBJECT **RetBufferDesc) 14367754Smsmith{ 14477424Smsmith ACPI_STATUS Status; 14577424Smsmith ACPI_OPERAND_OBJECT *BufferDesc; 146114237Snjl ACPI_SIZE Length; 14777424Smsmith void *Buffer; 148197104Sjkim UINT32 Function; 149281075Sdim UINT16 AccessorType; 15067754Smsmith 15167754Smsmith 152167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc); 15367754Smsmith 15467754Smsmith 15567754Smsmith /* Parameter validation */ 15667754Smsmith 15777424Smsmith if (!ObjDesc) 15867754Smsmith { 15967754Smsmith return_ACPI_STATUS (AE_AML_NO_OPERAND); 16067754Smsmith } 161151937Sjkim if (!RetBufferDesc) 162151937Sjkim { 163151937Sjkim return_ACPI_STATUS (AE_BAD_PARAMETER); 164151937Sjkim } 16567754Smsmith 166193267Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 16787031Smsmith { 16887031Smsmith /* 16987031Smsmith * If the BufferField arguments have not been previously evaluated, 17087031Smsmith * evaluate them now and save the results. 17187031Smsmith */ 17287031Smsmith if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 17387031Smsmith { 17487031Smsmith Status = AcpiDsGetBufferFieldArguments (ObjDesc); 17587031Smsmith if (ACPI_FAILURE (Status)) 17687031Smsmith { 17787031Smsmith return_ACPI_STATUS (Status); 17887031Smsmith } 17987031Smsmith } 18087031Smsmith } 181193267Sjkim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 182197104Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 183228110Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 184197104Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 185107325Siwasaki { 186107325Siwasaki /* 187228110Sjkim * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold 188197104Sjkim * the data and then directly access the region handler. 189197104Sjkim * 190228110Sjkim * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function 191107325Siwasaki */ 192197104Sjkim if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS) 193197104Sjkim { 194197104Sjkim Length = ACPI_SMBUS_BUFFER_SIZE; 195197104Sjkim Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); 196197104Sjkim } 197228110Sjkim else if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) 198228110Sjkim { 199281075Sdim AccessorType = ObjDesc->Field.Attribute; 200281075Sdim Length = AcpiExGetSerialAccessLength (AccessorType, 201281075Sdim ObjDesc->Field.AccessLength); 202281075Sdim 203281075Sdim /* 204281075Sdim * Add additional 2 bytes for the GenericSerialBus data buffer: 205281075Sdim * 206281075Sdim * Status; (Byte 0 of the data buffer) 207281075Sdim * Length; (Byte 1 of the data buffer) 208281075Sdim * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) 209281075Sdim */ 210281075Sdim Length += 2; 211281075Sdim Function = ACPI_READ | (AccessorType << 16); 212228110Sjkim } 213197104Sjkim else /* IPMI */ 214197104Sjkim { 215197104Sjkim Length = ACPI_IPMI_BUFFER_SIZE; 216197104Sjkim Function = ACPI_READ; 217197104Sjkim } 218197104Sjkim 219197104Sjkim BufferDesc = AcpiUtCreateBufferObject (Length); 220107325Siwasaki if (!BufferDesc) 221107325Siwasaki { 222107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 223107325Siwasaki } 22487031Smsmith 225107325Siwasaki /* Lock entire transaction if requested */ 226107325Siwasaki 227167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 228107325Siwasaki 229197104Sjkim /* Call the region handler for the read */ 230197104Sjkim 231114237Snjl Status = AcpiExAccessRegion (ObjDesc, 0, 232202771Sjkim ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), 233197104Sjkim Function); 234167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 235107325Siwasaki goto Exit; 236107325Siwasaki } 237107325Siwasaki 23867754Smsmith /* 23977424Smsmith * Allocate a buffer for the contents of the field. 24067754Smsmith * 241202771Sjkim * If the field is larger than the current integer width, create 242241973Sjkim * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 24377424Smsmith * the use of arithmetic operators on the returned value if the 24477424Smsmith * field size is equal or smaller than an Integer. 24577424Smsmith * 24677424Smsmith * Note: Field.length is in bits. 24767754Smsmith */ 248114237Snjl Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->Field.BitLength); 24999679Siwasaki if (Length > AcpiGbl_IntegerByteWidth) 25067754Smsmith { 25177424Smsmith /* Field is too large for an Integer, create a Buffer instead */ 25267754Smsmith 253107325Siwasaki BufferDesc = AcpiUtCreateBufferObject (Length); 25477424Smsmith if (!BufferDesc) 25577424Smsmith { 25677424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 25777424Smsmith } 25877424Smsmith Buffer = BufferDesc->Buffer.Pointer; 25967754Smsmith } 26077424Smsmith else 26177424Smsmith { 26277424Smsmith /* Field will fit within an Integer (normal case) */ 26367754Smsmith 264199337Sjkim BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 26577424Smsmith if (!BufferDesc) 26677424Smsmith { 26777424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 26877424Smsmith } 26977424Smsmith 27099679Siwasaki Length = AcpiGbl_IntegerByteWidth; 27177424Smsmith Buffer = &BufferDesc->Integer.Value; 27267754Smsmith } 27367754Smsmith 274281075Sdim if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 275281075Sdim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 276281075Sdim { 277281075Sdim /* 278281075Sdim * For GPIO (GeneralPurposeIo), the Address will be the bit offset 279281075Sdim * from the previous Connection() operator, making it effectively a 280281075Sdim * pin number index. The BitLength is the length of the field, which 281281075Sdim * is thus the number of pins. 282281075Sdim */ 283281075Sdim ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 284281075Sdim "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 285281075Sdim ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 286281075Sdim 287281075Sdim /* Lock entire transaction if requested */ 288281075Sdim 289281075Sdim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 290281075Sdim 291281075Sdim /* Perform the write */ 292281075Sdim 293281075Sdim Status = AcpiExAccessRegion (ObjDesc, 0, 294281075Sdim (UINT64 *) Buffer, ACPI_READ); 295281075Sdim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 296281075Sdim if (ACPI_FAILURE (Status)) 297281075Sdim { 298281075Sdim AcpiUtRemoveReference (BufferDesc); 299281075Sdim } 300281075Sdim else 301281075Sdim { 302281075Sdim *RetBufferDesc = BufferDesc; 303281075Sdim } 304281075Sdim return_ACPI_STATUS (Status); 305281075Sdim } 306281075Sdim 30799146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 308123315Snjl "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", 309193267Sjkim ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); 31099146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 311123315Snjl "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", 31287031Smsmith ObjDesc->CommonField.BitLength, 31387031Smsmith ObjDesc->CommonField.StartFieldBitOffset, 31487031Smsmith ObjDesc->CommonField.BaseByteOffset)); 31577424Smsmith 316107325Siwasaki /* Lock entire transaction if requested */ 317107325Siwasaki 318167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 31977424Smsmith 32087031Smsmith /* Read from the field */ 32167754Smsmith 322114237Snjl Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); 323167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 32467754Smsmith 325107325Siwasaki 326107325SiwasakiExit: 32777424Smsmith if (ACPI_FAILURE (Status)) 32877424Smsmith { 32977424Smsmith AcpiUtRemoveReference (BufferDesc); 33077424Smsmith } 331151937Sjkim else 33277424Smsmith { 33377424Smsmith *RetBufferDesc = BufferDesc; 33477424Smsmith } 33577424Smsmith 33677424Smsmith return_ACPI_STATUS (Status); 33767754Smsmith} 33867754Smsmith 33967754Smsmith 34067754Smsmith/******************************************************************************* 34167754Smsmith * 34277424Smsmith * FUNCTION: AcpiExWriteDataToField 34367754Smsmith * 34487031Smsmith * PARAMETERS: SourceDesc - Contains data to write 34587031Smsmith * ObjDesc - The named field 346151937Sjkim * ResultDesc - Where the return value is returned, if any 34767754Smsmith * 34867754Smsmith * RETURN: Status 34967754Smsmith * 35087031Smsmith * DESCRIPTION: Write to a named field 35167754Smsmith * 35267754Smsmith ******************************************************************************/ 35367754Smsmith 35467754SmsmithACPI_STATUS 35577424SmsmithAcpiExWriteDataToField ( 35677424Smsmith ACPI_OPERAND_OBJECT *SourceDesc, 357107325Siwasaki ACPI_OPERAND_OBJECT *ObjDesc, 358107325Siwasaki ACPI_OPERAND_OBJECT **ResultDesc) 35967754Smsmith{ 36077424Smsmith ACPI_STATUS Status; 36177424Smsmith UINT32 Length; 36277424Smsmith void *Buffer; 363107325Siwasaki ACPI_OPERAND_OBJECT *BufferDesc; 364197104Sjkim UINT32 Function; 365281075Sdim UINT16 AccessorType; 36667754Smsmith 36767754Smsmith 368167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); 36967754Smsmith 37067754Smsmith 37171867Smsmith /* Parameter validation */ 37271867Smsmith 37377424Smsmith if (!SourceDesc || !ObjDesc) 37467754Smsmith { 37577424Smsmith return_ACPI_STATUS (AE_AML_NO_OPERAND); 37667754Smsmith } 37767754Smsmith 378193267Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 37987031Smsmith { 38087031Smsmith /* 38187031Smsmith * If the BufferField arguments have not been previously evaluated, 38287031Smsmith * evaluate them now and save the results. 38387031Smsmith */ 38487031Smsmith if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 38587031Smsmith { 38687031Smsmith Status = AcpiDsGetBufferFieldArguments (ObjDesc); 38787031Smsmith if (ACPI_FAILURE (Status)) 38887031Smsmith { 38987031Smsmith return_ACPI_STATUS (Status); 39087031Smsmith } 39187031Smsmith } 39287031Smsmith } 393193267Sjkim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 394197104Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 395228110Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 396197104Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 397107325Siwasaki { 398107325Siwasaki /* 399228110Sjkim * This is an SMBus, GSBus or IPMI write. We will bypass the entire field 400197104Sjkim * mechanism and handoff the buffer directly to the handler. For 401197104Sjkim * these address spaces, the buffer is bi-directional; on a write, 402197104Sjkim * return data is returned in the same buffer. 403107325Siwasaki * 404197104Sjkim * Source must be a buffer of sufficient size: 405228110Sjkim * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. 406197104Sjkim * 407228110Sjkim * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function 408107325Siwasaki */ 409193267Sjkim if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) 410107325Siwasaki { 411197104Sjkim ACPI_ERROR ((AE_INFO, 412228110Sjkim "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s", 413107325Siwasaki AcpiUtGetObjectTypeName (SourceDesc))); 414151937Sjkim 415107325Siwasaki return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 416107325Siwasaki } 41767754Smsmith 418197104Sjkim if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS) 419107325Siwasaki { 420197104Sjkim Length = ACPI_SMBUS_BUFFER_SIZE; 421197104Sjkim Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); 422197104Sjkim } 423228110Sjkim else if (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) 424228110Sjkim { 425281075Sdim AccessorType = ObjDesc->Field.Attribute; 426281075Sdim Length = AcpiExGetSerialAccessLength (AccessorType, 427281075Sdim ObjDesc->Field.AccessLength); 428281075Sdim 429281075Sdim /* 430281075Sdim * Add additional 2 bytes for the GenericSerialBus data buffer: 431281075Sdim * 432281075Sdim * Status; (Byte 0 of the data buffer) 433281075Sdim * Length; (Byte 1 of the data buffer) 434281075Sdim * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) 435281075Sdim */ 436281075Sdim Length += 2; 437281075Sdim Function = ACPI_WRITE | (AccessorType << 16); 438228110Sjkim } 439197104Sjkim else /* IPMI */ 440197104Sjkim { 441197104Sjkim Length = ACPI_IPMI_BUFFER_SIZE; 442197104Sjkim Function = ACPI_WRITE; 443197104Sjkim } 444197104Sjkim 445197104Sjkim if (SourceDesc->Buffer.Length < Length) 446197104Sjkim { 447167802Sjkim ACPI_ERROR ((AE_INFO, 448228110Sjkim "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u", 449197104Sjkim Length, SourceDesc->Buffer.Length)); 450151937Sjkim 451107325Siwasaki return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 452107325Siwasaki } 453107325Siwasaki 454197104Sjkim /* Create the bi-directional buffer */ 455197104Sjkim 456197104Sjkim BufferDesc = AcpiUtCreateBufferObject (Length); 457107325Siwasaki if (!BufferDesc) 458107325Siwasaki { 459107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 460107325Siwasaki } 461107325Siwasaki 462107325Siwasaki Buffer = BufferDesc->Buffer.Pointer; 463197104Sjkim ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer, Length); 464107325Siwasaki 465107325Siwasaki /* Lock entire transaction if requested */ 466107325Siwasaki 467167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 468107325Siwasaki 469114237Snjl /* 470151937Sjkim * Perform the write (returns status and perhaps data in the 471151937Sjkim * same buffer) 472107325Siwasaki */ 473114237Snjl Status = AcpiExAccessRegion (ObjDesc, 0, 474202771Sjkim (UINT64 *) Buffer, Function); 475167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 476107325Siwasaki 477107325Siwasaki *ResultDesc = BufferDesc; 478107325Siwasaki return_ACPI_STATUS (Status); 479107325Siwasaki } 480281075Sdim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 481281075Sdim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 482281075Sdim { 483281075Sdim /* 484281075Sdim * For GPIO (GeneralPurposeIo), we will bypass the entire field 485281075Sdim * mechanism and handoff the bit address and bit width directly to 486281075Sdim * the handler. The Address will be the bit offset 487281075Sdim * from the previous Connection() operator, making it effectively a 488281075Sdim * pin number index. The BitLength is the length of the field, which 489281075Sdim * is thus the number of pins. 490281075Sdim */ 491281075Sdim if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) 492281075Sdim { 493281075Sdim return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 494281075Sdim } 495107325Siwasaki 496281075Sdim ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 497281075Sdim "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", 498281075Sdim AcpiUtGetTypeName (SourceDesc->Common.Type), 499281075Sdim SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, 500281075Sdim ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 501281075Sdim 502281075Sdim Buffer = &SourceDesc->Integer.Value; 503281075Sdim 504281075Sdim /* Lock entire transaction if requested */ 505281075Sdim 506281075Sdim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 507281075Sdim 508281075Sdim /* Perform the write */ 509281075Sdim 510281075Sdim Status = AcpiExAccessRegion (ObjDesc, 0, 511281075Sdim (UINT64 *) Buffer, ACPI_WRITE); 512281075Sdim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 513281075Sdim return_ACPI_STATUS (Status); 514281075Sdim } 515281075Sdim 516151937Sjkim /* Get a pointer to the data to be written */ 517151937Sjkim 518193267Sjkim switch (SourceDesc->Common.Type) 51967754Smsmith { 52077424Smsmith case ACPI_TYPE_INTEGER: 521250838Sjkim 52277424Smsmith Buffer = &SourceDesc->Integer.Value; 52377424Smsmith Length = sizeof (SourceDesc->Integer.Value); 52477424Smsmith break; 52577424Smsmith 52677424Smsmith case ACPI_TYPE_BUFFER: 527250838Sjkim 52877424Smsmith Buffer = SourceDesc->Buffer.Pointer; 52977424Smsmith Length = SourceDesc->Buffer.Length; 53077424Smsmith break; 53177424Smsmith 53277424Smsmith case ACPI_TYPE_STRING: 533250838Sjkim 53477424Smsmith Buffer = SourceDesc->String.Pointer; 53577424Smsmith Length = SourceDesc->String.Length; 53677424Smsmith break; 53777424Smsmith 53877424Smsmith default: 539250838Sjkim 54077424Smsmith return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 54167754Smsmith } 54267754Smsmith 54399146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 544123315Snjl "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", 545193267Sjkim SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), 546193267Sjkim SourceDesc->Common.Type, Buffer, Length)); 547151937Sjkim 54899146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 549123315Snjl "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", 550193267Sjkim ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type), 551193267Sjkim ObjDesc->Common.Type, 55287031Smsmith ObjDesc->CommonField.BitLength, 55387031Smsmith ObjDesc->CommonField.StartFieldBitOffset, 55487031Smsmith ObjDesc->CommonField.BaseByteOffset)); 55567754Smsmith 556107325Siwasaki /* Lock entire transaction if requested */ 557107325Siwasaki 558167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 55977424Smsmith 560107325Siwasaki /* Write to the field */ 561107325Siwasaki 56287031Smsmith Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); 563167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 56467754Smsmith 56577424Smsmith return_ACPI_STATUS (Status); 56677424Smsmith} 567