167754Smsmith/****************************************************************************** 267754Smsmith * 377424Smsmith * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, 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 /* 187306536Sjkim * This is an SMBus, GSBus or IPMI read. We must create a buffer to 188306536Sjkim * hold the data and then directly access the region handler. 189197104Sjkim * 190306536Sjkim * Note: SMBus and GSBus protocol value is passed in upper 16-bits 191306536Sjkim * of Function 192107325Siwasaki */ 193306536Sjkim if (ObjDesc->Field.RegionObj->Region.SpaceId == 194306536Sjkim ACPI_ADR_SPACE_SMBUS) 195197104Sjkim { 196197104Sjkim Length = ACPI_SMBUS_BUFFER_SIZE; 197197104Sjkim Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); 198197104Sjkim } 199306536Sjkim else if (ObjDesc->Field.RegionObj->Region.SpaceId == 200306536Sjkim ACPI_ADR_SPACE_GSBUS) 201228110Sjkim { 202281075Sdim AccessorType = ObjDesc->Field.Attribute; 203306536Sjkim Length = AcpiExGetSerialAccessLength ( 204306536Sjkim AccessorType, ObjDesc->Field.AccessLength); 205281075Sdim 206281075Sdim /* 207281075Sdim * Add additional 2 bytes for the GenericSerialBus data buffer: 208281075Sdim * 209306536Sjkim * Status; (Byte 0 of the data buffer) 210306536Sjkim * Length; (Byte 1 of the data buffer) 211306536Sjkim * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 212281075Sdim */ 213281075Sdim Length += 2; 214281075Sdim Function = ACPI_READ | (AccessorType << 16); 215228110Sjkim } 216197104Sjkim else /* IPMI */ 217197104Sjkim { 218197104Sjkim Length = ACPI_IPMI_BUFFER_SIZE; 219197104Sjkim Function = ACPI_READ; 220197104Sjkim } 221197104Sjkim 222197104Sjkim BufferDesc = AcpiUtCreateBufferObject (Length); 223107325Siwasaki if (!BufferDesc) 224107325Siwasaki { 225107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 226107325Siwasaki } 22787031Smsmith 228107325Siwasaki /* Lock entire transaction if requested */ 229107325Siwasaki 230167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 231107325Siwasaki 232197104Sjkim /* Call the region handler for the read */ 233197104Sjkim 234114237Snjl Status = AcpiExAccessRegion (ObjDesc, 0, 235306536Sjkim ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); 236306536Sjkim 237167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 238107325Siwasaki goto Exit; 239107325Siwasaki } 240107325Siwasaki 24167754Smsmith /* 24277424Smsmith * Allocate a buffer for the contents of the field. 24367754Smsmith * 244202771Sjkim * If the field is larger than the current integer width, create 245241973Sjkim * a BUFFER to hold it. Otherwise, use an INTEGER. This allows 24677424Smsmith * the use of arithmetic operators on the returned value if the 24777424Smsmith * field size is equal or smaller than an Integer. 24877424Smsmith * 24977424Smsmith * Note: Field.length is in bits. 25067754Smsmith */ 251306536Sjkim Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( 252306536Sjkim ObjDesc->Field.BitLength); 253306536Sjkim 25499679Siwasaki if (Length > AcpiGbl_IntegerByteWidth) 25567754Smsmith { 25677424Smsmith /* Field is too large for an Integer, create a Buffer instead */ 25767754Smsmith 258107325Siwasaki BufferDesc = AcpiUtCreateBufferObject (Length); 25977424Smsmith if (!BufferDesc) 26077424Smsmith { 26177424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 26277424Smsmith } 26377424Smsmith Buffer = BufferDesc->Buffer.Pointer; 26467754Smsmith } 26577424Smsmith else 26677424Smsmith { 26777424Smsmith /* Field will fit within an Integer (normal case) */ 26867754Smsmith 269199337Sjkim BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 27077424Smsmith if (!BufferDesc) 27177424Smsmith { 27277424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 27377424Smsmith } 27477424Smsmith 27599679Siwasaki Length = AcpiGbl_IntegerByteWidth; 27677424Smsmith Buffer = &BufferDesc->Integer.Value; 27767754Smsmith } 27867754Smsmith 279281075Sdim if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 280281075Sdim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 281281075Sdim { 282281075Sdim /* 283281075Sdim * For GPIO (GeneralPurposeIo), the Address will be the bit offset 284281075Sdim * from the previous Connection() operator, making it effectively a 285281075Sdim * pin number index. The BitLength is the length of the field, which 286281075Sdim * is thus the number of pins. 287281075Sdim */ 288281075Sdim ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 289281075Sdim "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 290281075Sdim ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 291281075Sdim 292281075Sdim /* Lock entire transaction if requested */ 293281075Sdim 294281075Sdim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 295281075Sdim 296281075Sdim /* Perform the write */ 297281075Sdim 298306536Sjkim Status = AcpiExAccessRegion ( 299306536Sjkim ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); 300306536Sjkim 301281075Sdim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 302281075Sdim if (ACPI_FAILURE (Status)) 303281075Sdim { 304281075Sdim AcpiUtRemoveReference (BufferDesc); 305281075Sdim } 306281075Sdim else 307281075Sdim { 308281075Sdim *RetBufferDesc = BufferDesc; 309281075Sdim } 310281075Sdim return_ACPI_STATUS (Status); 311281075Sdim } 312281075Sdim 31399146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 314123315Snjl "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", 315193267Sjkim ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length)); 31699146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 317123315Snjl "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", 31887031Smsmith ObjDesc->CommonField.BitLength, 31987031Smsmith ObjDesc->CommonField.StartFieldBitOffset, 32087031Smsmith ObjDesc->CommonField.BaseByteOffset)); 32177424Smsmith 322107325Siwasaki /* Lock entire transaction if requested */ 323107325Siwasaki 324167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 32577424Smsmith 32687031Smsmith /* Read from the field */ 32767754Smsmith 328114237Snjl Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length); 329167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 33067754Smsmith 331107325Siwasaki 332107325SiwasakiExit: 33377424Smsmith if (ACPI_FAILURE (Status)) 33477424Smsmith { 33577424Smsmith AcpiUtRemoveReference (BufferDesc); 33677424Smsmith } 337151937Sjkim else 33877424Smsmith { 33977424Smsmith *RetBufferDesc = BufferDesc; 34077424Smsmith } 34177424Smsmith 34277424Smsmith return_ACPI_STATUS (Status); 34367754Smsmith} 34467754Smsmith 34567754Smsmith 34667754Smsmith/******************************************************************************* 34767754Smsmith * 34877424Smsmith * FUNCTION: AcpiExWriteDataToField 34967754Smsmith * 35087031Smsmith * PARAMETERS: SourceDesc - Contains data to write 35187031Smsmith * ObjDesc - The named field 352151937Sjkim * ResultDesc - Where the return value is returned, if any 35367754Smsmith * 35467754Smsmith * RETURN: Status 35567754Smsmith * 35687031Smsmith * DESCRIPTION: Write to a named field 35767754Smsmith * 35867754Smsmith ******************************************************************************/ 35967754Smsmith 36067754SmsmithACPI_STATUS 36177424SmsmithAcpiExWriteDataToField ( 36277424Smsmith ACPI_OPERAND_OBJECT *SourceDesc, 363107325Siwasaki ACPI_OPERAND_OBJECT *ObjDesc, 364107325Siwasaki ACPI_OPERAND_OBJECT **ResultDesc) 36567754Smsmith{ 36677424Smsmith ACPI_STATUS Status; 36777424Smsmith UINT32 Length; 36877424Smsmith void *Buffer; 369107325Siwasaki ACPI_OPERAND_OBJECT *BufferDesc; 370197104Sjkim UINT32 Function; 371281075Sdim UINT16 AccessorType; 37267754Smsmith 37367754Smsmith 374167802Sjkim ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc); 37567754Smsmith 37667754Smsmith 37771867Smsmith /* Parameter validation */ 37871867Smsmith 37977424Smsmith if (!SourceDesc || !ObjDesc) 38067754Smsmith { 38177424Smsmith return_ACPI_STATUS (AE_AML_NO_OPERAND); 38267754Smsmith } 38367754Smsmith 384193267Sjkim if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) 38587031Smsmith { 38687031Smsmith /* 38787031Smsmith * If the BufferField arguments have not been previously evaluated, 38887031Smsmith * evaluate them now and save the results. 38987031Smsmith */ 39087031Smsmith if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 39187031Smsmith { 39287031Smsmith Status = AcpiDsGetBufferFieldArguments (ObjDesc); 39387031Smsmith if (ACPI_FAILURE (Status)) 39487031Smsmith { 39587031Smsmith return_ACPI_STATUS (Status); 39687031Smsmith } 39787031Smsmith } 39887031Smsmith } 399193267Sjkim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 400197104Sjkim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS || 401228110Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 402197104Sjkim ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI)) 403107325Siwasaki { 404107325Siwasaki /* 405306536Sjkim * This is an SMBus, GSBus or IPMI write. We will bypass the entire 406306536Sjkim * field mechanism and handoff the buffer directly to the handler. 407306536Sjkim * For these address spaces, the buffer is bi-directional; on a 408306536Sjkim * write, return data is returned in the same buffer. 409107325Siwasaki * 410197104Sjkim * Source must be a buffer of sufficient size: 411306536Sjkim * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or 412306536Sjkim * ACPI_IPMI_BUFFER_SIZE. 413197104Sjkim * 414306536Sjkim * Note: SMBus and GSBus protocol type is passed in upper 16-bits 415306536Sjkim * of Function 416107325Siwasaki */ 417193267Sjkim if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) 418107325Siwasaki { 419197104Sjkim ACPI_ERROR ((AE_INFO, 420306536Sjkim "SMBus/IPMI/GenericSerialBus write requires " 421306536Sjkim "Buffer, found type %s", 422107325Siwasaki AcpiUtGetObjectTypeName (SourceDesc))); 423151937Sjkim 424107325Siwasaki return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 425107325Siwasaki } 42667754Smsmith 427306536Sjkim if (ObjDesc->Field.RegionObj->Region.SpaceId == 428306536Sjkim ACPI_ADR_SPACE_SMBUS) 429107325Siwasaki { 430197104Sjkim Length = ACPI_SMBUS_BUFFER_SIZE; 431197104Sjkim Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); 432197104Sjkim } 433306536Sjkim else if (ObjDesc->Field.RegionObj->Region.SpaceId == 434306536Sjkim ACPI_ADR_SPACE_GSBUS) 435228110Sjkim { 436281075Sdim AccessorType = ObjDesc->Field.Attribute; 437306536Sjkim Length = AcpiExGetSerialAccessLength ( 438306536Sjkim AccessorType, ObjDesc->Field.AccessLength); 439281075Sdim 440281075Sdim /* 441281075Sdim * Add additional 2 bytes for the GenericSerialBus data buffer: 442281075Sdim * 443306536Sjkim * Status; (Byte 0 of the data buffer) 444306536Sjkim * Length; (Byte 1 of the data buffer) 445306536Sjkim * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 446281075Sdim */ 447281075Sdim Length += 2; 448281075Sdim Function = ACPI_WRITE | (AccessorType << 16); 449228110Sjkim } 450197104Sjkim else /* IPMI */ 451197104Sjkim { 452197104Sjkim Length = ACPI_IPMI_BUFFER_SIZE; 453197104Sjkim Function = ACPI_WRITE; 454197104Sjkim } 455197104Sjkim 456197104Sjkim if (SourceDesc->Buffer.Length < Length) 457197104Sjkim { 458167802Sjkim ACPI_ERROR ((AE_INFO, 459306536Sjkim "SMBus/IPMI/GenericSerialBus write requires " 460306536Sjkim "Buffer of length %u, found length %u", 461197104Sjkim Length, SourceDesc->Buffer.Length)); 462151937Sjkim 463107325Siwasaki return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 464107325Siwasaki } 465107325Siwasaki 466197104Sjkim /* Create the bi-directional buffer */ 467197104Sjkim 468197104Sjkim BufferDesc = AcpiUtCreateBufferObject (Length); 469107325Siwasaki if (!BufferDesc) 470107325Siwasaki { 471107325Siwasaki return_ACPI_STATUS (AE_NO_MEMORY); 472107325Siwasaki } 473107325Siwasaki 474107325Siwasaki Buffer = BufferDesc->Buffer.Pointer; 475306536Sjkim memcpy (Buffer, SourceDesc->Buffer.Pointer, Length); 476107325Siwasaki 477107325Siwasaki /* Lock entire transaction if requested */ 478107325Siwasaki 479167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 480107325Siwasaki 481114237Snjl /* 482151937Sjkim * Perform the write (returns status and perhaps data in the 483151937Sjkim * same buffer) 484107325Siwasaki */ 485306536Sjkim Status = AcpiExAccessRegion ( 486306536Sjkim ObjDesc, 0, (UINT64 *) Buffer, Function); 487167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 488107325Siwasaki 489107325Siwasaki *ResultDesc = BufferDesc; 490107325Siwasaki return_ACPI_STATUS (Status); 491107325Siwasaki } 492281075Sdim else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && 493281075Sdim (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) 494281075Sdim { 495281075Sdim /* 496281075Sdim * For GPIO (GeneralPurposeIo), we will bypass the entire field 497281075Sdim * mechanism and handoff the bit address and bit width directly to 498281075Sdim * the handler. The Address will be the bit offset 499281075Sdim * from the previous Connection() operator, making it effectively a 500281075Sdim * pin number index. The BitLength is the length of the field, which 501281075Sdim * is thus the number of pins. 502281075Sdim */ 503281075Sdim if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) 504281075Sdim { 505281075Sdim return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 506281075Sdim } 507107325Siwasaki 508281075Sdim ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 509306536Sjkim "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", 510281075Sdim AcpiUtGetTypeName (SourceDesc->Common.Type), 511281075Sdim SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, 512281075Sdim ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); 513281075Sdim 514281075Sdim Buffer = &SourceDesc->Integer.Value; 515281075Sdim 516281075Sdim /* Lock entire transaction if requested */ 517281075Sdim 518281075Sdim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 519281075Sdim 520281075Sdim /* Perform the write */ 521281075Sdim 522306536Sjkim Status = AcpiExAccessRegion ( 523306536Sjkim ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); 524281075Sdim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 525281075Sdim return_ACPI_STATUS (Status); 526281075Sdim } 527281075Sdim 528151937Sjkim /* Get a pointer to the data to be written */ 529151937Sjkim 530193267Sjkim switch (SourceDesc->Common.Type) 53167754Smsmith { 53277424Smsmith case ACPI_TYPE_INTEGER: 533250838Sjkim 53477424Smsmith Buffer = &SourceDesc->Integer.Value; 53577424Smsmith Length = sizeof (SourceDesc->Integer.Value); 53677424Smsmith break; 53777424Smsmith 53877424Smsmith case ACPI_TYPE_BUFFER: 539250838Sjkim 54077424Smsmith Buffer = SourceDesc->Buffer.Pointer; 54177424Smsmith Length = SourceDesc->Buffer.Length; 54277424Smsmith break; 54377424Smsmith 54477424Smsmith case ACPI_TYPE_STRING: 545250838Sjkim 54677424Smsmith Buffer = SourceDesc->String.Pointer; 54777424Smsmith Length = SourceDesc->String.Length; 54877424Smsmith break; 54977424Smsmith 55077424Smsmith default: 551250838Sjkim 55277424Smsmith return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 55367754Smsmith } 55467754Smsmith 55599146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 556123315Snjl "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", 557193267Sjkim SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type), 558193267Sjkim SourceDesc->Common.Type, Buffer, Length)); 559151937Sjkim 56099146Siwasaki ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, 561123315Snjl "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", 562193267Sjkim ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type), 563193267Sjkim ObjDesc->Common.Type, 56487031Smsmith ObjDesc->CommonField.BitLength, 56587031Smsmith ObjDesc->CommonField.StartFieldBitOffset, 56687031Smsmith ObjDesc->CommonField.BaseByteOffset)); 56767754Smsmith 568107325Siwasaki /* Lock entire transaction if requested */ 569107325Siwasaki 570167802Sjkim AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); 57177424Smsmith 572107325Siwasaki /* Write to the field */ 573107325Siwasaki 57487031Smsmith Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length); 575167802Sjkim AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); 57667754Smsmith 57777424Smsmith return_ACPI_STATUS (Status); 57877424Smsmith} 579