dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / uts / intel / io / acpica / executer / exfield.c
blob208af637943550a4310713baef8187c2df8d00b6
1 /******************************************************************************
3 * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acdispat.h"
47 #include "acinterp.h"
48 #include "amlcode.h"
51 #define _COMPONENT ACPI_EXECUTER
52 ACPI_MODULE_NAME ("exfield")
54 /* Local prototypes */
56 static UINT32
57 AcpiExGetSerialAccessLength (
58 UINT32 AccessorType,
59 UINT32 AccessLength);
62 /*******************************************************************************
64 * FUNCTION: AcpiExGetSerialAccessLength
66 * PARAMETERS: AccessorType - The type of the protocol indicated by region
67 * field access attributes
68 * AccessLength - The access length of the region field
70 * RETURN: Decoded access length
72 * DESCRIPTION: This routine returns the length of the GenericSerialBus
73 * protocol bytes
75 ******************************************************************************/
77 static UINT32
78 AcpiExGetSerialAccessLength (
79 UINT32 AccessorType,
80 UINT32 AccessLength)
82 UINT32 Length;
85 switch (AccessorType)
87 case AML_FIELD_ATTRIB_QUICK:
89 Length = 0;
90 break;
92 case AML_FIELD_ATTRIB_SEND_RCV:
93 case AML_FIELD_ATTRIB_BYTE:
95 Length = 1;
96 break;
98 case AML_FIELD_ATTRIB_WORD:
99 case AML_FIELD_ATTRIB_WORD_CALL:
101 Length = 2;
102 break;
104 case AML_FIELD_ATTRIB_MULTIBYTE:
105 case AML_FIELD_ATTRIB_RAW_BYTES:
106 case AML_FIELD_ATTRIB_RAW_PROCESS:
108 Length = AccessLength;
109 break;
111 case AML_FIELD_ATTRIB_BLOCK:
112 case AML_FIELD_ATTRIB_BLOCK_CALL:
113 default:
115 Length = ACPI_GSBUS_BUFFER_SIZE - 2;
116 break;
119 return (Length);
123 /*******************************************************************************
125 * FUNCTION: AcpiExReadDataFromField
127 * PARAMETERS: WalkState - Current execution state
128 * ObjDesc - The named field
129 * RetBufferDesc - Where the return data object is stored
131 * RETURN: Status
133 * DESCRIPTION: Read from a named field. Returns either an Integer or a
134 * Buffer, depending on the size of the field.
136 ******************************************************************************/
138 ACPI_STATUS
139 AcpiExReadDataFromField (
140 ACPI_WALK_STATE *WalkState,
141 ACPI_OPERAND_OBJECT *ObjDesc,
142 ACPI_OPERAND_OBJECT **RetBufferDesc)
144 ACPI_STATUS Status;
145 ACPI_OPERAND_OBJECT *BufferDesc;
146 ACPI_SIZE Length;
147 void *Buffer;
148 UINT32 Function;
149 UINT16 AccessorType;
152 ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc);
155 /* Parameter validation */
157 if (!ObjDesc)
159 return_ACPI_STATUS (AE_AML_NO_OPERAND);
161 if (!RetBufferDesc)
163 return_ACPI_STATUS (AE_BAD_PARAMETER);
166 if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD)
169 * If the BufferField arguments have not been previously evaluated,
170 * evaluate them now and save the results.
172 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
174 Status = AcpiDsGetBufferFieldArguments (ObjDesc);
175 if (ACPI_FAILURE (Status))
177 return_ACPI_STATUS (Status);
181 else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
182 (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
183 ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||
184 ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI))
187 * This is an SMBus, GSBus or IPMI read. We must create a buffer to
188 * hold the data and then directly access the region handler.
190 * Note: SMBus and GSBus protocol value is passed in upper 16-bits
191 * of Function
193 if (ObjDesc->Field.RegionObj->Region.SpaceId ==
194 ACPI_ADR_SPACE_SMBUS)
196 Length = ACPI_SMBUS_BUFFER_SIZE;
197 Function = ACPI_READ | (ObjDesc->Field.Attribute << 16);
199 else if (ObjDesc->Field.RegionObj->Region.SpaceId ==
200 ACPI_ADR_SPACE_GSBUS)
202 AccessorType = ObjDesc->Field.Attribute;
203 Length = AcpiExGetSerialAccessLength (
204 AccessorType, ObjDesc->Field.AccessLength);
207 * Add additional 2 bytes for the GenericSerialBus data buffer:
209 * Status; (Byte 0 of the data buffer)
210 * Length; (Byte 1 of the data buffer)
211 * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
213 Length += 2;
214 Function = ACPI_READ | (AccessorType << 16);
216 else /* IPMI */
218 Length = ACPI_IPMI_BUFFER_SIZE;
219 Function = ACPI_READ;
222 BufferDesc = AcpiUtCreateBufferObject (Length);
223 if (!BufferDesc)
225 return_ACPI_STATUS (AE_NO_MEMORY);
228 /* Lock entire transaction if requested */
230 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
232 /* Call the region handler for the read */
234 Status = AcpiExAccessRegion (ObjDesc, 0,
235 ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function);
237 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
238 goto Exit;
242 * Allocate a buffer for the contents of the field.
244 * If the field is larger than the current integer width, create
245 * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
246 * the use of arithmetic operators on the returned value if the
247 * field size is equal or smaller than an Integer.
249 * Note: Field.length is in bits.
251 Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES (
252 ObjDesc->Field.BitLength);
254 if (Length > AcpiGbl_IntegerByteWidth)
256 /* Field is too large for an Integer, create a Buffer instead */
258 BufferDesc = AcpiUtCreateBufferObject (Length);
259 if (!BufferDesc)
261 return_ACPI_STATUS (AE_NO_MEMORY);
263 Buffer = BufferDesc->Buffer.Pointer;
265 else
267 /* Field will fit within an Integer (normal case) */
269 BufferDesc = AcpiUtCreateIntegerObject ((UINT64) 0);
270 if (!BufferDesc)
272 return_ACPI_STATUS (AE_NO_MEMORY);
275 Length = AcpiGbl_IntegerByteWidth;
276 Buffer = &BufferDesc->Integer.Value;
279 if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
280 (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO))
283 * For GPIO (GeneralPurposeIo), the Address will be the bit offset
284 * from the previous Connection() operator, making it effectively a
285 * pin number index. The BitLength is the length of the field, which
286 * is thus the number of pins.
288 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
289 "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
290 ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength));
292 /* Lock entire transaction if requested */
294 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
296 /* Perform the write */
298 Status = AcpiExAccessRegion (
299 ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ);
301 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
302 if (ACPI_FAILURE (Status))
304 AcpiUtRemoveReference (BufferDesc);
306 else
308 *RetBufferDesc = BufferDesc;
310 return_ACPI_STATUS (Status);
313 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
314 "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
315 ObjDesc, ObjDesc->Common.Type, Buffer, (UINT32) Length));
316 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
317 "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
318 ObjDesc->CommonField.BitLength,
319 ObjDesc->CommonField.StartFieldBitOffset,
320 ObjDesc->CommonField.BaseByteOffset));
322 /* Lock entire transaction if requested */
324 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
326 /* Read from the field */
328 Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length);
329 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
332 Exit:
333 if (ACPI_FAILURE (Status))
335 AcpiUtRemoveReference (BufferDesc);
337 else
339 *RetBufferDesc = BufferDesc;
342 return_ACPI_STATUS (Status);
346 /*******************************************************************************
348 * FUNCTION: AcpiExWriteDataToField
350 * PARAMETERS: SourceDesc - Contains data to write
351 * ObjDesc - The named field
352 * ResultDesc - Where the return value is returned, if any
354 * RETURN: Status
356 * DESCRIPTION: Write to a named field
358 ******************************************************************************/
360 ACPI_STATUS
361 AcpiExWriteDataToField (
362 ACPI_OPERAND_OBJECT *SourceDesc,
363 ACPI_OPERAND_OBJECT *ObjDesc,
364 ACPI_OPERAND_OBJECT **ResultDesc)
366 ACPI_STATUS Status;
367 UINT32 Length;
368 void *Buffer;
369 ACPI_OPERAND_OBJECT *BufferDesc;
370 UINT32 Function;
371 UINT16 AccessorType;
374 ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc);
377 /* Parameter validation */
379 if (!SourceDesc || !ObjDesc)
381 return_ACPI_STATUS (AE_AML_NO_OPERAND);
384 if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD)
387 * If the BufferField arguments have not been previously evaluated,
388 * evaluate them now and save the results.
390 if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
392 Status = AcpiDsGetBufferFieldArguments (ObjDesc);
393 if (ACPI_FAILURE (Status))
395 return_ACPI_STATUS (Status);
399 else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
400 (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
401 ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||
402 ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_IPMI))
405 * This is an SMBus, GSBus or IPMI write. We will bypass the entire
406 * field mechanism and handoff the buffer directly to the handler.
407 * For these address spaces, the buffer is bi-directional; on a
408 * write, return data is returned in the same buffer.
410 * Source must be a buffer of sufficient size:
411 * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
412 * ACPI_IPMI_BUFFER_SIZE.
414 * Note: SMBus and GSBus protocol type is passed in upper 16-bits
415 * of Function
417 if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER)
419 ACPI_ERROR ((AE_INFO,
420 "SMBus/IPMI/GenericSerialBus write requires "
421 "Buffer, found type %s",
422 AcpiUtGetObjectTypeName (SourceDesc)));
424 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
427 if (ObjDesc->Field.RegionObj->Region.SpaceId ==
428 ACPI_ADR_SPACE_SMBUS)
430 Length = ACPI_SMBUS_BUFFER_SIZE;
431 Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16);
433 else if (ObjDesc->Field.RegionObj->Region.SpaceId ==
434 ACPI_ADR_SPACE_GSBUS)
436 AccessorType = ObjDesc->Field.Attribute;
437 Length = AcpiExGetSerialAccessLength (
438 AccessorType, ObjDesc->Field.AccessLength);
441 * Add additional 2 bytes for the GenericSerialBus data buffer:
443 * Status; (Byte 0 of the data buffer)
444 * Length; (Byte 1 of the data buffer)
445 * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
447 Length += 2;
448 Function = ACPI_WRITE | (AccessorType << 16);
450 else /* IPMI */
452 Length = ACPI_IPMI_BUFFER_SIZE;
453 Function = ACPI_WRITE;
456 if (SourceDesc->Buffer.Length < Length)
458 ACPI_ERROR ((AE_INFO,
459 "SMBus/IPMI/GenericSerialBus write requires "
460 "Buffer of length %u, found length %u",
461 Length, SourceDesc->Buffer.Length));
463 return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
466 /* Create the bi-directional buffer */
468 BufferDesc = AcpiUtCreateBufferObject (Length);
469 if (!BufferDesc)
471 return_ACPI_STATUS (AE_NO_MEMORY);
474 Buffer = BufferDesc->Buffer.Pointer;
475 memcpy (Buffer, SourceDesc->Buffer.Pointer, Length);
477 /* Lock entire transaction if requested */
479 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
482 * Perform the write (returns status and perhaps data in the
483 * same buffer)
485 Status = AcpiExAccessRegion (
486 ObjDesc, 0, (UINT64 *) Buffer, Function);
487 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
489 *ResultDesc = BufferDesc;
490 return_ACPI_STATUS (Status);
492 else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
493 (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO))
496 * For GPIO (GeneralPurposeIo), we will bypass the entire field
497 * mechanism and handoff the bit address and bit width directly to
498 * the handler. The Address will be the bit offset
499 * from the previous Connection() operator, making it effectively a
500 * pin number index. The BitLength is the length of the field, which
501 * is thus the number of pins.
503 if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER)
505 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
508 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
509 "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
510 AcpiUtGetTypeName (SourceDesc->Common.Type),
511 SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value,
512 ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength));
514 Buffer = &SourceDesc->Integer.Value;
516 /* Lock entire transaction if requested */
518 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
520 /* Perform the write */
522 Status = AcpiExAccessRegion (
523 ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE);
524 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
525 return_ACPI_STATUS (Status);
528 /* Get a pointer to the data to be written */
530 switch (SourceDesc->Common.Type)
532 case ACPI_TYPE_INTEGER:
534 Buffer = &SourceDesc->Integer.Value;
535 Length = sizeof (SourceDesc->Integer.Value);
536 break;
538 case ACPI_TYPE_BUFFER:
540 Buffer = SourceDesc->Buffer.Pointer;
541 Length = SourceDesc->Buffer.Length;
542 break;
544 case ACPI_TYPE_STRING:
546 Buffer = SourceDesc->String.Pointer;
547 Length = SourceDesc->String.Length;
548 break;
550 default:
552 return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
555 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
556 "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
557 SourceDesc, AcpiUtGetTypeName (SourceDesc->Common.Type),
558 SourceDesc->Common.Type, Buffer, Length));
560 ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
561 "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
562 ObjDesc, AcpiUtGetTypeName (ObjDesc->Common.Type),
563 ObjDesc->Common.Type,
564 ObjDesc->CommonField.BitLength,
565 ObjDesc->CommonField.StartFieldBitOffset,
566 ObjDesc->CommonField.BaseByteOffset));
568 /* Lock entire transaction if requested */
570 AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
572 /* Write to the field */
574 Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length);
575 AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
577 return_ACPI_STATUS (Status);