1db2bae30SDana Myers /******************************************************************************
2db2bae30SDana Myers *
3*cb565728SJerry Jelinek * Module Name: exprep - ACPI AML field prep utilities
4db2bae30SDana Myers *
5db2bae30SDana Myers *****************************************************************************/
6db2bae30SDana Myers
726f3cdf0SGordon Ross /*
8*cb565728SJerry 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 "acinterp.h"
47db2bae30SDana Myers #include "amlcode.h"
48db2bae30SDana Myers #include "acnamesp.h"
49*cb565728SJerry Jelinek #include "acdispat.h"
50db2bae30SDana Myers
51db2bae30SDana Myers
52db2bae30SDana Myers #define _COMPONENT ACPI_EXECUTER
53db2bae30SDana Myers ACPI_MODULE_NAME ("exprep")
54db2bae30SDana Myers
55db2bae30SDana Myers /* Local prototypes */
56db2bae30SDana Myers
57db2bae30SDana Myers static UINT32
58db2bae30SDana Myers AcpiExDecodeFieldAccess (
59db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc,
60db2bae30SDana Myers UINT8 FieldFlags,
61db2bae30SDana Myers UINT32 *ReturnByteAlignment);
62db2bae30SDana Myers
63db2bae30SDana Myers
64db2bae30SDana Myers #ifdef ACPI_UNDER_DEVELOPMENT
65db2bae30SDana Myers
66db2bae30SDana Myers static UINT32
67db2bae30SDana Myers AcpiExGenerateAccess (
68db2bae30SDana Myers UINT32 FieldBitOffset,
69db2bae30SDana Myers UINT32 FieldBitLength,
70db2bae30SDana Myers UINT32 RegionLength);
71db2bae30SDana Myers
72*cb565728SJerry Jelinek
73db2bae30SDana Myers /*******************************************************************************
74db2bae30SDana Myers *
75db2bae30SDana Myers * FUNCTION: AcpiExGenerateAccess
76db2bae30SDana Myers *
77db2bae30SDana Myers * PARAMETERS: FieldBitOffset - Start of field within parent region/buffer
78db2bae30SDana Myers * FieldBitLength - Length of field in bits
79db2bae30SDana Myers * RegionLength - Length of parent in bytes
80db2bae30SDana Myers *
81db2bae30SDana Myers * RETURN: Field granularity (8, 16, 32 or 64) and
82db2bae30SDana Myers * ByteAlignment (1, 2, 3, or 4)
83db2bae30SDana Myers *
84db2bae30SDana Myers * DESCRIPTION: Generate an optimal access width for fields defined with the
85db2bae30SDana Myers * AnyAcc keyword.
86db2bae30SDana Myers *
87db2bae30SDana Myers * NOTE: Need to have the RegionLength in order to check for boundary
88db2bae30SDana Myers * conditions (end-of-region). However, the RegionLength is a deferred
89db2bae30SDana Myers * operation. Therefore, to complete this implementation, the generation
90db2bae30SDana Myers * of this access width must be deferred until the region length has
91db2bae30SDana Myers * been evaluated.
92db2bae30SDana Myers *
93db2bae30SDana Myers ******************************************************************************/
94db2bae30SDana Myers
95db2bae30SDana Myers static UINT32
AcpiExGenerateAccess(UINT32 FieldBitOffset,UINT32 FieldBitLength,UINT32 RegionLength)96db2bae30SDana Myers AcpiExGenerateAccess (
97db2bae30SDana Myers UINT32 FieldBitOffset,
98db2bae30SDana Myers UINT32 FieldBitLength,
99db2bae30SDana Myers UINT32 RegionLength)
100db2bae30SDana Myers {
101db2bae30SDana Myers UINT32 FieldByteLength;
102db2bae30SDana Myers UINT32 FieldByteOffset;
103db2bae30SDana Myers UINT32 FieldByteEndOffset;
104db2bae30SDana Myers UINT32 AccessByteWidth;
105db2bae30SDana Myers UINT32 FieldStartOffset;
106db2bae30SDana Myers UINT32 FieldEndOffset;
107db2bae30SDana Myers UINT32 MinimumAccessWidth = 0xFFFFFFFF;
108db2bae30SDana Myers UINT32 MinimumAccesses = 0xFFFFFFFF;
109db2bae30SDana Myers UINT32 Accesses;
110db2bae30SDana Myers
111db2bae30SDana Myers
112db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExGenerateAccess);
113db2bae30SDana Myers
114db2bae30SDana Myers
115db2bae30SDana Myers /* Round Field start offset and length to "minimal" byte boundaries */
116db2bae30SDana Myers
117*cb565728SJerry Jelinek FieldByteOffset = ACPI_DIV_8 (
118*cb565728SJerry Jelinek ACPI_ROUND_DOWN (FieldBitOffset, 8));
119*cb565728SJerry Jelinek
120*cb565728SJerry Jelinek FieldByteEndOffset = ACPI_DIV_8 (
121*cb565728SJerry Jelinek ACPI_ROUND_UP (FieldBitLength + FieldBitOffset, 8));
122*cb565728SJerry Jelinek
123db2bae30SDana Myers FieldByteLength = FieldByteEndOffset - FieldByteOffset;
124db2bae30SDana Myers
125db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
12626f3cdf0SGordon Ross "Bit length %u, Bit offset %u\n",
127db2bae30SDana Myers FieldBitLength, FieldBitOffset));
128db2bae30SDana Myers
129db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
13026f3cdf0SGordon Ross "Byte Length %u, Byte Offset %u, End Offset %u\n",
131db2bae30SDana Myers FieldByteLength, FieldByteOffset, FieldByteEndOffset));
132db2bae30SDana Myers
133db2bae30SDana Myers /*
134db2bae30SDana Myers * Iterative search for the maximum access width that is both aligned
135db2bae30SDana Myers * and does not go beyond the end of the region
136db2bae30SDana Myers *
137db2bae30SDana Myers * Start at ByteAcc and work upwards to QwordAcc max. (1,2,4,8 bytes)
138db2bae30SDana Myers */
139db2bae30SDana Myers for (AccessByteWidth = 1; AccessByteWidth <= 8; AccessByteWidth <<= 1)
140db2bae30SDana Myers {
141db2bae30SDana Myers /*
142db2bae30SDana Myers * 1) Round end offset up to next access boundary and make sure that
143db2bae30SDana Myers * this does not go beyond the end of the parent region.
144db2bae30SDana Myers * 2) When the Access width is greater than the FieldByteLength, we
145db2bae30SDana Myers * are done. (This does not optimize for the perfectly aligned
146db2bae30SDana Myers * case yet).
147db2bae30SDana Myers */
148*cb565728SJerry Jelinek if (ACPI_ROUND_UP (FieldByteEndOffset, AccessByteWidth) <=
149*cb565728SJerry Jelinek RegionLength)
150db2bae30SDana Myers {
151db2bae30SDana Myers FieldStartOffset =
152db2bae30SDana Myers ACPI_ROUND_DOWN (FieldByteOffset, AccessByteWidth) /
153db2bae30SDana Myers AccessByteWidth;
154db2bae30SDana Myers
155db2bae30SDana Myers FieldEndOffset =
156db2bae30SDana Myers ACPI_ROUND_UP ((FieldByteLength + FieldByteOffset),
157db2bae30SDana Myers AccessByteWidth) / AccessByteWidth;
158db2bae30SDana Myers
159db2bae30SDana Myers Accesses = FieldEndOffset - FieldStartOffset;
160db2bae30SDana Myers
161db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
16226f3cdf0SGordon Ross "AccessWidth %u end is within region\n", AccessByteWidth));
163db2bae30SDana Myers
164db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
16526f3cdf0SGordon Ross "Field Start %u, Field End %u -- requires %u accesses\n",
166db2bae30SDana Myers FieldStartOffset, FieldEndOffset, Accesses));
167db2bae30SDana Myers
168db2bae30SDana Myers /* Single access is optimal */
169db2bae30SDana Myers
170db2bae30SDana Myers if (Accesses <= 1)
171db2bae30SDana Myers {
172db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
173*cb565728SJerry Jelinek "Entire field can be accessed "
174*cb565728SJerry Jelinek "with one operation of size %u\n",
175db2bae30SDana Myers AccessByteWidth));
176db2bae30SDana Myers return_VALUE (AccessByteWidth);
177db2bae30SDana Myers }
178db2bae30SDana Myers
179db2bae30SDana Myers /*
180db2bae30SDana Myers * Fits in the region, but requires more than one read/write.
181db2bae30SDana Myers * try the next wider access on next iteration
182db2bae30SDana Myers */
183db2bae30SDana Myers if (Accesses < MinimumAccesses)
184db2bae30SDana Myers {
185db2bae30SDana Myers MinimumAccesses = Accesses;
186db2bae30SDana Myers MinimumAccessWidth = AccessByteWidth;
187db2bae30SDana Myers }
188db2bae30SDana Myers }
189db2bae30SDana Myers else
190db2bae30SDana Myers {
191db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
192*cb565728SJerry Jelinek "AccessWidth %u end is NOT within region\n",
193*cb565728SJerry Jelinek AccessByteWidth));
194db2bae30SDana Myers if (AccessByteWidth == 1)
195db2bae30SDana Myers {
196db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
197db2bae30SDana Myers "Field goes beyond end-of-region!\n"));
198db2bae30SDana Myers
199db2bae30SDana Myers /* Field does not fit in the region at all */
200db2bae30SDana Myers
201db2bae30SDana Myers return_VALUE (0);
202db2bae30SDana Myers }
203db2bae30SDana Myers
204db2bae30SDana Myers /*
205db2bae30SDana Myers * This width goes beyond the end-of-region, back off to
206db2bae30SDana Myers * previous access
207db2bae30SDana Myers */
208db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
20926f3cdf0SGordon Ross "Backing off to previous optimal access width of %u\n",
210db2bae30SDana Myers MinimumAccessWidth));
211db2bae30SDana Myers return_VALUE (MinimumAccessWidth);
212db2bae30SDana Myers }
213db2bae30SDana Myers }
214db2bae30SDana Myers
215db2bae30SDana Myers /*
216db2bae30SDana Myers * Could not read/write field with one operation,
217db2bae30SDana Myers * just use max access width
218db2bae30SDana Myers */
219db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
220db2bae30SDana Myers "Cannot access field in one operation, using width 8\n"));
221*cb565728SJerry Jelinek
222db2bae30SDana Myers return_VALUE (8);
223db2bae30SDana Myers }
224db2bae30SDana Myers #endif /* ACPI_UNDER_DEVELOPMENT */
225db2bae30SDana Myers
226db2bae30SDana Myers
227db2bae30SDana Myers /*******************************************************************************
228db2bae30SDana Myers *
229db2bae30SDana Myers * FUNCTION: AcpiExDecodeFieldAccess
230db2bae30SDana Myers *
231db2bae30SDana Myers * PARAMETERS: ObjDesc - Field object
232db2bae30SDana Myers * FieldFlags - Encoded fieldflags (contains access bits)
233db2bae30SDana Myers * ReturnByteAlignment - Where the byte alignment is returned
234db2bae30SDana Myers *
235db2bae30SDana Myers * RETURN: Field granularity (8, 16, 32 or 64) and
236db2bae30SDana Myers * ByteAlignment (1, 2, 3, or 4)
237db2bae30SDana Myers *
238db2bae30SDana Myers * DESCRIPTION: Decode the AccessType bits of a field definition.
239db2bae30SDana Myers *
240db2bae30SDana Myers ******************************************************************************/
241db2bae30SDana Myers
242db2bae30SDana Myers static UINT32
AcpiExDecodeFieldAccess(ACPI_OPERAND_OBJECT * ObjDesc,UINT8 FieldFlags,UINT32 * ReturnByteAlignment)243db2bae30SDana Myers AcpiExDecodeFieldAccess (
244db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc,
245db2bae30SDana Myers UINT8 FieldFlags,
246db2bae30SDana Myers UINT32 *ReturnByteAlignment)
247db2bae30SDana Myers {
248db2bae30SDana Myers UINT32 Access;
249db2bae30SDana Myers UINT32 ByteAlignment;
250db2bae30SDana Myers UINT32 BitLength;
251db2bae30SDana Myers
252db2bae30SDana Myers
253db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExDecodeFieldAccess);
254db2bae30SDana Myers
255db2bae30SDana Myers
256db2bae30SDana Myers Access = (FieldFlags & AML_FIELD_ACCESS_TYPE_MASK);
257db2bae30SDana Myers
258db2bae30SDana Myers switch (Access)
259db2bae30SDana Myers {
260db2bae30SDana Myers case AML_FIELD_ACCESS_ANY:
261db2bae30SDana Myers
262db2bae30SDana Myers #ifdef ACPI_UNDER_DEVELOPMENT
263db2bae30SDana Myers ByteAlignment =
264db2bae30SDana Myers AcpiExGenerateAccess (ObjDesc->CommonField.StartFieldBitOffset,
265db2bae30SDana Myers ObjDesc->CommonField.BitLength,
266db2bae30SDana Myers 0xFFFFFFFF /* Temp until we pass RegionLength as parameter */);
267db2bae30SDana Myers BitLength = ByteAlignment * 8;
268db2bae30SDana Myers #endif
269db2bae30SDana Myers
270db2bae30SDana Myers ByteAlignment = 1;
271db2bae30SDana Myers BitLength = 8;
272db2bae30SDana Myers break;
273db2bae30SDana Myers
274db2bae30SDana Myers case AML_FIELD_ACCESS_BYTE:
275db2bae30SDana Myers case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
276*cb565728SJerry Jelinek
277db2bae30SDana Myers ByteAlignment = 1;
278db2bae30SDana Myers BitLength = 8;
279db2bae30SDana Myers break;
280db2bae30SDana Myers
281db2bae30SDana Myers case AML_FIELD_ACCESS_WORD:
282*cb565728SJerry Jelinek
283db2bae30SDana Myers ByteAlignment = 2;
284db2bae30SDana Myers BitLength = 16;
285db2bae30SDana Myers break;
286db2bae30SDana Myers
287db2bae30SDana Myers case AML_FIELD_ACCESS_DWORD:
288*cb565728SJerry Jelinek
289db2bae30SDana Myers ByteAlignment = 4;
290db2bae30SDana Myers BitLength = 32;
291db2bae30SDana Myers break;
292db2bae30SDana Myers
293db2bae30SDana Myers case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
294*cb565728SJerry Jelinek
295db2bae30SDana Myers ByteAlignment = 8;
296db2bae30SDana Myers BitLength = 64;
297db2bae30SDana Myers break;
298db2bae30SDana Myers
299db2bae30SDana Myers default:
300*cb565728SJerry Jelinek
301db2bae30SDana Myers /* Invalid field access type */
302db2bae30SDana Myers
303db2bae30SDana Myers ACPI_ERROR ((AE_INFO,
30426f3cdf0SGordon Ross "Unknown field access type 0x%X",
305db2bae30SDana Myers Access));
306*cb565728SJerry Jelinek
307db2bae30SDana Myers return_UINT32 (0);
308db2bae30SDana Myers }
309db2bae30SDana Myers
310aa2aa9a6SDana Myers if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD)
311db2bae30SDana Myers {
312db2bae30SDana Myers /*
313db2bae30SDana Myers * BufferField access can be on any byte boundary, so the
314db2bae30SDana Myers * ByteAlignment is always 1 byte -- regardless of any ByteAlignment
315db2bae30SDana Myers * implied by the field access type.
316db2bae30SDana Myers */
317db2bae30SDana Myers ByteAlignment = 1;
318db2bae30SDana Myers }
319db2bae30SDana Myers
320db2bae30SDana Myers *ReturnByteAlignment = ByteAlignment;
321db2bae30SDana Myers return_UINT32 (BitLength);
322db2bae30SDana Myers }
323db2bae30SDana Myers
324db2bae30SDana Myers
325db2bae30SDana Myers /*******************************************************************************
326db2bae30SDana Myers *
327db2bae30SDana Myers * FUNCTION: AcpiExPrepCommonFieldObject
328db2bae30SDana Myers *
329db2bae30SDana Myers * PARAMETERS: ObjDesc - The field object
330db2bae30SDana Myers * FieldFlags - Access, LockRule, and UpdateRule.
331db2bae30SDana Myers * The format of a FieldFlag is described
332db2bae30SDana Myers * in the ACPI specification
333db2bae30SDana Myers * FieldAttribute - Special attributes (not used)
334db2bae30SDana Myers * FieldBitPosition - Field start position
335db2bae30SDana Myers * FieldBitLength - Field length in number of bits
336db2bae30SDana Myers *
337db2bae30SDana Myers * RETURN: Status
338db2bae30SDana Myers *
339db2bae30SDana Myers * DESCRIPTION: Initialize the areas of the field object that are common
340db2bae30SDana Myers * to the various types of fields. Note: This is very "sensitive"
341db2bae30SDana Myers * code because we are solving the general case for field
342db2bae30SDana Myers * alignment.
343db2bae30SDana Myers *
344db2bae30SDana Myers ******************************************************************************/
345db2bae30SDana Myers
346db2bae30SDana Myers ACPI_STATUS
AcpiExPrepCommonFieldObject(ACPI_OPERAND_OBJECT * ObjDesc,UINT8 FieldFlags,UINT8 FieldAttribute,UINT32 FieldBitPosition,UINT32 FieldBitLength)347db2bae30SDana Myers AcpiExPrepCommonFieldObject (
348db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc,
349db2bae30SDana Myers UINT8 FieldFlags,
350db2bae30SDana Myers UINT8 FieldAttribute,
351db2bae30SDana Myers UINT32 FieldBitPosition,
352db2bae30SDana Myers UINT32 FieldBitLength)
353db2bae30SDana Myers {
354db2bae30SDana Myers UINT32 AccessBitWidth;
355db2bae30SDana Myers UINT32 ByteAlignment;
356db2bae30SDana Myers UINT32 NearestByteAddress;
357db2bae30SDana Myers
358db2bae30SDana Myers
359db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExPrepCommonFieldObject);
360db2bae30SDana Myers
361db2bae30SDana Myers
362db2bae30SDana Myers /*
363db2bae30SDana Myers * Note: the structure being initialized is the
364db2bae30SDana Myers * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common
365db2bae30SDana Myers * area are initialized by this procedure.
366db2bae30SDana Myers */
367db2bae30SDana Myers ObjDesc->CommonField.FieldFlags = FieldFlags;
368db2bae30SDana Myers ObjDesc->CommonField.Attribute = FieldAttribute;
369db2bae30SDana Myers ObjDesc->CommonField.BitLength = FieldBitLength;
370db2bae30SDana Myers
371db2bae30SDana Myers /*
372db2bae30SDana Myers * Decode the access type so we can compute offsets. The access type gives
373db2bae30SDana Myers * two pieces of information - the width of each field access and the
374db2bae30SDana Myers * necessary ByteAlignment (address granularity) of the access.
375db2bae30SDana Myers *
376db2bae30SDana Myers * For AnyAcc, the AccessBitWidth is the largest width that is both
377db2bae30SDana Myers * necessary and possible in an attempt to access the whole field in one
378db2bae30SDana Myers * I/O operation. However, for AnyAcc, the ByteAlignment is always one
379db2bae30SDana Myers * byte.
380db2bae30SDana Myers *
381db2bae30SDana Myers * For all Buffer Fields, the ByteAlignment is always one byte.
382db2bae30SDana Myers *
383db2bae30SDana Myers * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
384db2bae30SDana Myers * the same (equivalent) as the ByteAlignment.
385db2bae30SDana Myers */
386*cb565728SJerry Jelinek AccessBitWidth = AcpiExDecodeFieldAccess (
387*cb565728SJerry Jelinek ObjDesc, FieldFlags, &ByteAlignment);
388db2bae30SDana Myers if (!AccessBitWidth)
389db2bae30SDana Myers {
390db2bae30SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
391db2bae30SDana Myers }
392db2bae30SDana Myers
39326f3cdf0SGordon Ross /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
394db2bae30SDana Myers
395db2bae30SDana Myers ObjDesc->CommonField.AccessByteWidth = (UINT8)
39626f3cdf0SGordon Ross ACPI_DIV_8 (AccessBitWidth);
397db2bae30SDana Myers
398db2bae30SDana Myers /*
399db2bae30SDana Myers * BaseByteOffset is the address of the start of the field within the
400db2bae30SDana Myers * region. It is the byte address of the first *datum* (field-width data
401db2bae30SDana Myers * unit) of the field. (i.e., the first datum that contains at least the
402db2bae30SDana Myers * first *bit* of the field.)
403db2bae30SDana Myers *
404db2bae30SDana Myers * Note: ByteAlignment is always either equal to the AccessBitWidth or 8
405db2bae30SDana Myers * (Byte access), and it defines the addressing granularity of the parent
406db2bae30SDana Myers * region or buffer.
407db2bae30SDana Myers */
408db2bae30SDana Myers NearestByteAddress =
409db2bae30SDana Myers ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition);
410db2bae30SDana Myers ObjDesc->CommonField.BaseByteOffset = (UINT32)
411db2bae30SDana Myers ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment);
412db2bae30SDana Myers
413db2bae30SDana Myers /*
414db2bae30SDana Myers * StartFieldBitOffset is the offset of the first bit of the field within
415db2bae30SDana Myers * a field datum.
416db2bae30SDana Myers */
417db2bae30SDana Myers ObjDesc->CommonField.StartFieldBitOffset = (UINT8)
418db2bae30SDana Myers (FieldBitPosition - ACPI_MUL_8 (ObjDesc->CommonField.BaseByteOffset));
419db2bae30SDana Myers
420db2bae30SDana Myers return_ACPI_STATUS (AE_OK);
421db2bae30SDana Myers }
422db2bae30SDana Myers
423db2bae30SDana Myers
424db2bae30SDana Myers /*******************************************************************************
425db2bae30SDana Myers *
426db2bae30SDana Myers * FUNCTION: AcpiExPrepFieldValue
427db2bae30SDana Myers *
428db2bae30SDana Myers * PARAMETERS: Info - Contains all field creation info
429db2bae30SDana Myers *
430db2bae30SDana Myers * RETURN: Status
431db2bae30SDana Myers *
432*cb565728SJerry Jelinek * DESCRIPTION: Construct an object of type ACPI_OPERAND_OBJECT with a
433*cb565728SJerry Jelinek * subtype of DefField and connect it to the parent Node.
434db2bae30SDana Myers *
435db2bae30SDana Myers ******************************************************************************/
436db2bae30SDana Myers
437db2bae30SDana Myers ACPI_STATUS
AcpiExPrepFieldValue(ACPI_CREATE_FIELD_INFO * Info)438db2bae30SDana Myers AcpiExPrepFieldValue (
439db2bae30SDana Myers ACPI_CREATE_FIELD_INFO *Info)
440db2bae30SDana Myers {
441db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc;
442db2bae30SDana Myers ACPI_OPERAND_OBJECT *SecondDesc = NULL;
443db2bae30SDana Myers ACPI_STATUS Status;
44426f3cdf0SGordon Ross UINT32 AccessByteWidth;
44526f3cdf0SGordon Ross UINT32 Type;
446db2bae30SDana Myers
447db2bae30SDana Myers
448db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExPrepFieldValue);
449db2bae30SDana Myers
450db2bae30SDana Myers
451db2bae30SDana Myers /* Parameter validation */
452db2bae30SDana Myers
453db2bae30SDana Myers if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD)
454db2bae30SDana Myers {
455db2bae30SDana Myers if (!Info->RegionNode)
456db2bae30SDana Myers {
457db2bae30SDana Myers ACPI_ERROR ((AE_INFO, "Null RegionNode"));
458db2bae30SDana Myers return_ACPI_STATUS (AE_AML_NO_OPERAND);
459db2bae30SDana Myers }
460db2bae30SDana Myers
461db2bae30SDana Myers Type = AcpiNsGetType (Info->RegionNode);
462db2bae30SDana Myers if (Type != ACPI_TYPE_REGION)
463db2bae30SDana Myers {
46426f3cdf0SGordon Ross ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
465db2bae30SDana Myers Type, AcpiUtGetTypeName (Type)));
466db2bae30SDana Myers
467db2bae30SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
468db2bae30SDana Myers }
469db2bae30SDana Myers }
470db2bae30SDana Myers
471db2bae30SDana Myers /* Allocate a new field object */
472db2bae30SDana Myers
473db2bae30SDana Myers ObjDesc = AcpiUtCreateInternalObject (Info->FieldType);
474db2bae30SDana Myers if (!ObjDesc)
475db2bae30SDana Myers {
476db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY);
477db2bae30SDana Myers }
478db2bae30SDana Myers
479db2bae30SDana Myers /* Initialize areas of the object that are common to all fields */
480db2bae30SDana Myers
481db2bae30SDana Myers ObjDesc->CommonField.Node = Info->FieldNode;
48226f3cdf0SGordon Ross Status = AcpiExPrepCommonFieldObject (ObjDesc,
48326f3cdf0SGordon Ross Info->FieldFlags, Info->Attribute,
48426f3cdf0SGordon Ross Info->FieldBitPosition, Info->FieldBitLength);
485db2bae30SDana Myers if (ACPI_FAILURE (Status))
486db2bae30SDana Myers {
487db2bae30SDana Myers AcpiUtDeleteObjectDesc (ObjDesc);
488db2bae30SDana Myers return_ACPI_STATUS (Status);
489db2bae30SDana Myers }
490db2bae30SDana Myers
491db2bae30SDana Myers /* Initialize areas of the object that are specific to the field type */
492db2bae30SDana Myers
493db2bae30SDana Myers switch (Info->FieldType)
494db2bae30SDana Myers {
495db2bae30SDana Myers case ACPI_TYPE_LOCAL_REGION_FIELD:
496db2bae30SDana Myers
497db2bae30SDana Myers ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode);
498db2bae30SDana Myers
499*cb565728SJerry Jelinek /* Fields specific to GenericSerialBus fields */
500*cb565728SJerry Jelinek
501*cb565728SJerry Jelinek ObjDesc->Field.AccessLength = Info->AccessLength;
502*cb565728SJerry Jelinek
503*cb565728SJerry Jelinek if (Info->ConnectionNode)
504*cb565728SJerry Jelinek {
505*cb565728SJerry Jelinek SecondDesc = Info->ConnectionNode->Object;
506*cb565728SJerry Jelinek if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID))
507*cb565728SJerry Jelinek {
508*cb565728SJerry Jelinek Status = AcpiDsGetBufferArguments (SecondDesc);
509*cb565728SJerry Jelinek if (ACPI_FAILURE (Status))
510*cb565728SJerry Jelinek {
511*cb565728SJerry Jelinek AcpiUtDeleteObjectDesc (ObjDesc);
512*cb565728SJerry Jelinek return_ACPI_STATUS (Status);
513*cb565728SJerry Jelinek }
514*cb565728SJerry Jelinek }
515*cb565728SJerry Jelinek
516*cb565728SJerry Jelinek ObjDesc->Field.ResourceBuffer =
517*cb565728SJerry Jelinek SecondDesc->Buffer.Pointer;
518*cb565728SJerry Jelinek ObjDesc->Field.ResourceLength =
519*cb565728SJerry Jelinek (UINT16) SecondDesc->Buffer.Length;
520*cb565728SJerry Jelinek }
521*cb565728SJerry Jelinek else if (Info->ResourceBuffer)
522*cb565728SJerry Jelinek {
523*cb565728SJerry Jelinek ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer;
524*cb565728SJerry Jelinek ObjDesc->Field.ResourceLength = Info->ResourceLength;
525*cb565728SJerry Jelinek }
526*cb565728SJerry Jelinek
527*cb565728SJerry Jelinek ObjDesc->Field.PinNumberIndex = Info->PinNumberIndex;
528*cb565728SJerry Jelinek
52926f3cdf0SGordon Ross /* Allow full data read from EC address space */
53026f3cdf0SGordon Ross
53126f3cdf0SGordon Ross if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
53226f3cdf0SGordon Ross (ObjDesc->CommonField.BitLength > 8))
53326f3cdf0SGordon Ross {
53426f3cdf0SGordon Ross AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES (
53526f3cdf0SGordon Ross ObjDesc->CommonField.BitLength);
53626f3cdf0SGordon Ross
53726f3cdf0SGordon Ross /* Maximum byte width supported is 255 */
53826f3cdf0SGordon Ross
53926f3cdf0SGordon Ross if (AccessByteWidth < 256)
54026f3cdf0SGordon Ross {
541*cb565728SJerry Jelinek ObjDesc->CommonField.AccessByteWidth =
542*cb565728SJerry Jelinek (UINT8) AccessByteWidth;
54326f3cdf0SGordon Ross }
54426f3cdf0SGordon Ross }
54526f3cdf0SGordon Ross
546db2bae30SDana Myers /* An additional reference for the container */
547db2bae30SDana Myers
548db2bae30SDana Myers AcpiUtAddReference (ObjDesc->Field.RegionObj);
549db2bae30SDana Myers
550db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
551db2bae30SDana Myers "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
552*cb565728SJerry Jelinek ObjDesc->Field.StartFieldBitOffset,
553*cb565728SJerry Jelinek ObjDesc->Field.BaseByteOffset,
554*cb565728SJerry Jelinek ObjDesc->Field.AccessByteWidth,
555*cb565728SJerry Jelinek ObjDesc->Field.RegionObj));
556db2bae30SDana Myers break;
557db2bae30SDana Myers
558db2bae30SDana Myers case ACPI_TYPE_LOCAL_BANK_FIELD:
559db2bae30SDana Myers
560db2bae30SDana Myers ObjDesc->BankField.Value = Info->BankValue;
56126f3cdf0SGordon Ross ObjDesc->BankField.RegionObj =
56226f3cdf0SGordon Ross AcpiNsGetAttachedObject (Info->RegionNode);
56326f3cdf0SGordon Ross ObjDesc->BankField.BankObj =
56426f3cdf0SGordon Ross AcpiNsGetAttachedObject (Info->RegisterNode);
565db2bae30SDana Myers
566db2bae30SDana Myers /* An additional reference for the attached objects */
567db2bae30SDana Myers
568db2bae30SDana Myers AcpiUtAddReference (ObjDesc->BankField.RegionObj);
569db2bae30SDana Myers AcpiUtAddReference (ObjDesc->BankField.BankObj);
570db2bae30SDana Myers
571db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
572db2bae30SDana Myers "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
573db2bae30SDana Myers ObjDesc->BankField.StartFieldBitOffset,
574db2bae30SDana Myers ObjDesc->BankField.BaseByteOffset,
575db2bae30SDana Myers ObjDesc->Field.AccessByteWidth,
576db2bae30SDana Myers ObjDesc->BankField.RegionObj,
577db2bae30SDana Myers ObjDesc->BankField.BankObj));
578db2bae30SDana Myers
579db2bae30SDana Myers /*
580db2bae30SDana Myers * Remember location in AML stream of the field unit
581db2bae30SDana Myers * opcode and operands -- since the BankValue
582db2bae30SDana Myers * operands must be evaluated.
583db2bae30SDana Myers */
584db2bae30SDana Myers SecondDesc = ObjDesc->Common.NextObject;
58526f3cdf0SGordon Ross SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT,
58626f3cdf0SGordon Ross Info->DataRegisterNode)->Named.Data;
58726f3cdf0SGordon Ross SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT,
58826f3cdf0SGordon Ross Info->DataRegisterNode)->Named.Length;
589db2bae30SDana Myers
590db2bae30SDana Myers break;
591db2bae30SDana Myers
592db2bae30SDana Myers case ACPI_TYPE_LOCAL_INDEX_FIELD:
593db2bae30SDana Myers
594db2bae30SDana Myers /* Get the Index and Data registers */
595db2bae30SDana Myers
59626f3cdf0SGordon Ross ObjDesc->IndexField.IndexObj =
59726f3cdf0SGordon Ross AcpiNsGetAttachedObject (Info->RegisterNode);
59826f3cdf0SGordon Ross ObjDesc->IndexField.DataObj =
59926f3cdf0SGordon Ross AcpiNsGetAttachedObject (Info->DataRegisterNode);
600db2bae30SDana Myers
601db2bae30SDana Myers if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj)
602db2bae30SDana Myers {
603db2bae30SDana Myers ACPI_ERROR ((AE_INFO, "Null Index Object during field prep"));
604db2bae30SDana Myers AcpiUtDeleteObjectDesc (ObjDesc);
605db2bae30SDana Myers return_ACPI_STATUS (AE_AML_INTERNAL);
606db2bae30SDana Myers }
607db2bae30SDana Myers
608db2bae30SDana Myers /* An additional reference for the attached objects */
609db2bae30SDana Myers
610db2bae30SDana Myers AcpiUtAddReference (ObjDesc->IndexField.DataObj);
611db2bae30SDana Myers AcpiUtAddReference (ObjDesc->IndexField.IndexObj);
612db2bae30SDana Myers
613db2bae30SDana Myers /*
614db2bae30SDana Myers * April 2006: Changed to match MS behavior
615db2bae30SDana Myers *
616db2bae30SDana Myers * The value written to the Index register is the byte offset of the
617db2bae30SDana Myers * target field in units of the granularity of the IndexField
618db2bae30SDana Myers *
619db2bae30SDana Myers * Previously, the value was calculated as an index in terms of the
620db2bae30SDana Myers * width of the Data register, as below:
621db2bae30SDana Myers *
622db2bae30SDana Myers * ObjDesc->IndexField.Value = (UINT32)
623db2bae30SDana Myers * (Info->FieldBitPosition / ACPI_MUL_8 (
624db2bae30SDana Myers * ObjDesc->Field.AccessByteWidth));
625db2bae30SDana Myers *
626db2bae30SDana Myers * February 2006: Tried value as a byte offset:
627db2bae30SDana Myers * ObjDesc->IndexField.Value = (UINT32)
628db2bae30SDana Myers * ACPI_DIV_8 (Info->FieldBitPosition);
629db2bae30SDana Myers */
630db2bae30SDana Myers ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN (
631db2bae30SDana Myers ACPI_DIV_8 (Info->FieldBitPosition),
632db2bae30SDana Myers ObjDesc->IndexField.AccessByteWidth);
633db2bae30SDana Myers
634db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
635*cb565728SJerry Jelinek "IndexField: BitOff %X, Off %X, Value %X, "
636*cb565728SJerry Jelinek "Gran %X, Index %p, Data %p\n",
637db2bae30SDana Myers ObjDesc->IndexField.StartFieldBitOffset,
638db2bae30SDana Myers ObjDesc->IndexField.BaseByteOffset,
639db2bae30SDana Myers ObjDesc->IndexField.Value,
640db2bae30SDana Myers ObjDesc->Field.AccessByteWidth,
641db2bae30SDana Myers ObjDesc->IndexField.IndexObj,
642db2bae30SDana Myers ObjDesc->IndexField.DataObj));
643db2bae30SDana Myers break;
644db2bae30SDana Myers
645db2bae30SDana Myers default:
646*cb565728SJerry Jelinek
647db2bae30SDana Myers /* No other types should get here */
648*cb565728SJerry Jelinek
649db2bae30SDana Myers break;
650db2bae30SDana Myers }
651db2bae30SDana Myers
652db2bae30SDana Myers /*
653db2bae30SDana Myers * Store the constructed descriptor (ObjDesc) into the parent Node,
654db2bae30SDana Myers * preserving the current type of that NamedObj.
655db2bae30SDana Myers */
656*cb565728SJerry Jelinek Status = AcpiNsAttachObject (
657*cb565728SJerry Jelinek Info->FieldNode, ObjDesc, AcpiNsGetType (Info->FieldNode));
658db2bae30SDana Myers
659*cb565728SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
660*cb565728SJerry Jelinek "Set NamedObj %p [%4.4s], ObjDesc %p\n",
661db2bae30SDana Myers Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc));
662db2bae30SDana Myers
663db2bae30SDana Myers /* Remove local reference to the object */
664db2bae30SDana Myers
665db2bae30SDana Myers AcpiUtRemoveReference (ObjDesc);
666db2bae30SDana Myers return_ACPI_STATUS (Status);
667db2bae30SDana Myers }
668