xref: /titanic_44/usr/src/uts/intel/io/acpica/executer/exprep.c (revision cb56572868bfc488bbd3ab847b09db2a25554d44)
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