exfield.c revision 70243
1234285Sdim/******************************************************************************
2234285Sdim *
3234285Sdim * Module Name: amfield - ACPI AML (p-code) execution - field manipulation
4234285Sdim *              $Revision: 75 $
5234285Sdim *
6234285Sdim *****************************************************************************/
7234285Sdim
8234285Sdim/******************************************************************************
9234285Sdim *
10234285Sdim * 1. Copyright Notice
11234285Sdim *
12234285Sdim * Some or all of this work - Copyright (c) 1999, 2000, Intel Corp.
13234285Sdim * All rights reserved.
14234285Sdim *
15234285Sdim * 2. License
16234285Sdim *
17234285Sdim * 2.1. This is your license from Intel Corp. under its intellectual property
18234285Sdim * rights.  You may have additional license terms from the party that provided
19251662Sdim * you this software, covering your right to use that party's intellectual
20249423Sdim * property rights.
21251662Sdim *
22234285Sdim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23234285Sdim * copy of the source code appearing in this file ("Covered Code") an
24234285Sdim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25234285Sdim * base code distributed originally by Intel ("Original Intel Code") to copy,
26234285Sdim * make derivatives, distribute, use and display any portion of the Covered
27234285Sdim * Code in any form, with the right to sublicense such rights; and
28234285Sdim *
29263508Sdim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30234285Sdim * license (with the right to sublicense), under only those claims of Intel
31263508Sdim * patents that are infringed by the Original Intel Code, to make, use, sell,
32251662Sdim * offer to sell, and import the Covered Code and derivative works thereof
33251662Sdim * solely to the minimum extent necessary to exercise the above copyright
34234285Sdim * license, and in no event shall the patent license extend to any additions
35234285Sdim * to or modifications of the Original Intel Code.  No other license or right
36234285Sdim * is granted directly or by implication, estoppel or otherwise;
37234285Sdim *
38234285Sdim * The above copyright and patent license is granted only if the following
39234285Sdim * conditions are met:
40234285Sdim *
41234285Sdim * 3. Conditions
42234285Sdim *
43234285Sdim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44234285Sdim * Redistribution of source code of any substantial portion of the Covered
45234285Sdim * Code or modification with rights to further distribute source must include
46234285Sdim * the above Copyright Notice, the above License, this list of Conditions,
47234285Sdim * and the following Disclaimer and Export Compliance provision.  In addition,
48234285Sdim * Licensee must cause all Covered Code to which Licensee contributes to
49234285Sdim * contain a file documenting the changes Licensee made to create that Covered
50234285Sdim * Code and the date of any change.  Licensee must include in that file the
51234285Sdim * documentation of any changes made by any predecessor Licensee.  Licensee
52234285Sdim * must include a prominent statement that the modification is derived,
53234285Sdim * directly or indirectly, from Original Intel Code.
54234285Sdim *
55234285Sdim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56234285Sdim * Redistribution of source code of any substantial portion of the Covered
57234285Sdim * Code or modification without rights to further distribute source must
58234285Sdim * include the following Disclaimer and Export Compliance provision in the
59234285Sdim * documentation and/or other materials provided with distribution.  In
60234285Sdim * addition, Licensee may not authorize further sublicense of source of any
61234285Sdim * portion of the Covered Code, and must include terms to the effect that the
62234285Sdim * license from Licensee to its licensee is limited to the intellectual
63234285Sdim * property embodied in the software Licensee provides to its licensee, and
64234285Sdim * not to intellectual property embodied in modifications its licensee may
65234285Sdim * make.
66234285Sdim *
67234285Sdim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68234285Sdim * substantial portion of the Covered Code or modification must reproduce the
69234285Sdim * above Copyright Notice, and the following Disclaimer and Export Compliance
70234285Sdim * provision in the documentation and/or other materials provided with the
71234285Sdim * distribution.
72249423Sdim *
73249423Sdim * 3.4. Intel retains all right, title, and interest in and to the Original
74249423Sdim * Intel Code.
75249423Sdim *
76234285Sdim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77234285Sdim * Intel shall be used in advertising or otherwise to promote the sale, use or
78234285Sdim * other dealings in products derived from or relating to the Covered Code
79234285Sdim * without prior written authorization from Intel.
80234285Sdim *
81234285Sdim * 4. Disclaimer and Export Compliance
82234285Sdim *
83234285Sdim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84234285Sdim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85234285Sdim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86234285Sdim * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87234285Sdim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88234285Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89234285Sdim * PARTICULAR PURPOSE.
90234285Sdim *
91234285Sdim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92234285Sdim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93234285Sdim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94234285Sdim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95234285Sdim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96234285Sdim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97234285Sdim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98234285Sdim * LIMITED REMEDY.
99234285Sdim *
100234285Sdim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101234285Sdim * software or system incorporating such software without first obtaining any
102234285Sdim * required license or other approval from the U. S. Department of Commerce or
103234285Sdim * any other agency or department of the United States Government.  In the
104234285Sdim * event Licensee exports any such software from the United States or
105234285Sdim * re-exports any such software from a foreign destination, Licensee shall
106234285Sdim * ensure that the distribution and export/re-export of the software is in
107234285Sdim * compliance with all laws, regulations, orders, or other restrictions of the
108234285Sdim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109234285Sdim * any of its subsidiaries will export/re-export any technical data, process,
110234285Sdim * software, or service, directly or indirectly, to any country for which the
111234285Sdim * United States government or any agency thereof requires an export license,
112234285Sdim * other governmental approval, or letter of assurance, without first obtaining
113234285Sdim * such license, approval or letter.
114234285Sdim *
115234285Sdim *****************************************************************************/
116234285Sdim
117251662Sdim
118234285Sdim#define __AMFIELD_C__
119234285Sdim
120234285Sdim#include "acpi.h"
121234285Sdim#include "acdispat.h"
122234285Sdim#include "acinterp.h"
123239462Sdim#include "amlcode.h"
124234285Sdim#include "acnamesp.h"
125234285Sdim#include "achware.h"
126234285Sdim#include "acevents.h"
127234285Sdim
128234285Sdim
129234285Sdim#define _COMPONENT          INTERPRETER
130234285Sdim        MODULE_NAME         ("amfield")
131234285Sdim
132234285Sdim
133234285Sdim/*******************************************************************************
134251662Sdim *
135251662Sdim * FUNCTION:    AcpiAmlSetupField
136251662Sdim *
137249423Sdim * PARAMETERS:  *ObjDesc            - Field to be read or written
138251662Sdim *              *RgnDesc            - Region containing field
139234285Sdim *              FieldBitWidth       - Field Width in bits (8, 16, or 32)
140234285Sdim *
141234285Sdim * RETURN:      Status
142234285Sdim *
143234285Sdim * DESCRIPTION: Common processing for AcpiAmlReadField and AcpiAmlWriteField
144234285Sdim *
145234285Sdim *  ACPI SPECIFICATION REFERENCES:
146234285Sdim *  Each of the Type1Opcodes is defined as specified in in-line
147234285Sdim *  comments below. For each one, use the following definitions.
148234285Sdim *
149234285Sdim *  DefBitField     :=  BitFieldOp      SrcBuf  BitIdx  Destination
150234285Sdim *  DefByteField    :=  ByteFieldOp     SrcBuf  ByteIdx Destination
151234285Sdim *  DefCreateField  :=  CreateFieldOp   SrcBuf  BitIdx  NumBits  NameString
152234285Sdim *  DefDWordField   :=  DWordFieldOp    SrcBuf  ByteIdx Destination
153234285Sdim *  DefWordField    :=  WordFieldOp     SrcBuf  ByteIdx Destination
154234285Sdim *  BitIndex        :=  TermArg=>Integer
155234285Sdim *  ByteIndex       :=  TermArg=>Integer
156234285Sdim *  Destination     :=  NameString
157234285Sdim *  NumBits         :=  TermArg=>Integer
158234285Sdim *  SourceBuf       :=  TermArg=>Buffer
159234285Sdim *
160234285Sdim ******************************************************************************/
161234285Sdim
162234285SdimACPI_STATUS
163234285SdimAcpiAmlSetupField (
164234285Sdim    ACPI_OPERAND_OBJECT     *ObjDesc,
165234285Sdim    ACPI_OPERAND_OBJECT     *RgnDesc,
166234285Sdim    UINT32                  FieldBitWidth)
167234285Sdim{
168234285Sdim    ACPI_STATUS             Status = AE_OK;
169234285Sdim    UINT32                  FieldByteWidth;
170234285Sdim
171234285Sdim
172234285Sdim    FUNCTION_TRACE ("AmlSetupField");
173234285Sdim
174234285Sdim
175234285Sdim    /* Parameter validation */
176239462Sdim
177239462Sdim    if (!ObjDesc || !RgnDesc)
178234285Sdim    {
179234285Sdim        DEBUG_PRINT (ACPI_ERROR,
180239462Sdim            ("AmlSetupField: Internal error - null handle\n"));
181249423Sdim        return_ACPI_STATUS (AE_AML_NO_OPERAND);
182251662Sdim    }
183249423Sdim
184263508Sdim    if (ACPI_TYPE_REGION != RgnDesc->Common.Type)
185263508Sdim    {
186263508Sdim        DEBUG_PRINT (ACPI_ERROR,
187263508Sdim            ("AmlSetupField: Needed Region, found type %x %s\n",
188263508Sdim            RgnDesc->Common.Type, AcpiCmGetTypeName (RgnDesc->Common.Type)));
189263508Sdim        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
190234285Sdim    }
191234285Sdim
192239462Sdim
193239462Sdim    /*
194239462Sdim     * TBD: [Future] Acpi 2.0 supports Qword fields
195239462Sdim     *
196263508Sdim     * Init and validate Field width
197239462Sdim     * Possible values are 1, 2, 4
198239462Sdim     */
199234285Sdim
200249423Sdim    FieldByteWidth = DIV_8 (FieldBitWidth);
201249423Sdim
202249423Sdim    if ((FieldBitWidth != 8) &&
203251662Sdim        (FieldBitWidth != 16) &&
204251662Sdim        (FieldBitWidth != 32))
205249423Sdim    {
206249423Sdim        DEBUG_PRINT (ACPI_ERROR,
207249423Sdim            ("AmlSetupField: Internal error - bad width %d\n", FieldBitWidth));
208249423Sdim        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
209249423Sdim    }
210249423Sdim
211249423Sdim
212249423Sdim    /*
213251662Sdim     * If the Region Address and Length have not been previously evaluated,
214251662Sdim     * evaluate them and save the results.
215251662Sdim     */
216234285Sdim    if (!(RgnDesc->Region.Flags & AOPOBJ_DATA_VALID))
217234285Sdim    {
218234285Sdim
219234285Sdim        Status = AcpiDsGetRegionArguments (RgnDesc);
220234285Sdim        if (ACPI_FAILURE (Status))
221234285Sdim        {
222234285Sdim            return_ACPI_STATUS (Status);
223234285Sdim        }
224    }
225
226
227    if ((ObjDesc->Common.Type == ACPI_TYPE_FIELD_UNIT) &&
228        (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)))
229    {
230        /*
231         * Field Buffer and Index have not been previously evaluated,
232         */
233        DEBUG_PRINT (ACPI_ERROR, ("Uninitialized field!\n"));
234        return_ACPI_STATUS (AE_AML_INTERNAL);
235    }
236
237    if (RgnDesc->Region.Length <
238       (ObjDesc->Field.Offset & ~((UINT32) FieldByteWidth - 1)) +
239            FieldByteWidth)
240    {
241        /*
242         * Offset rounded up to next multiple of field width
243         * exceeds region length, indicate an error
244         */
245
246        DUMP_STACK_ENTRY (RgnDesc);
247        DUMP_STACK_ENTRY (ObjDesc);
248
249        DEBUG_PRINT (ACPI_ERROR,
250            ("AmlSetupField: Operation at %08lX width %d bits exceeds len %08lX field=%p region=%p\n",
251            ObjDesc->Field.Offset, FieldBitWidth, RgnDesc->Region.Length,
252            ObjDesc, RgnDesc));
253
254        return_ACPI_STATUS (AE_AML_REGION_LIMIT);
255    }
256
257    return_ACPI_STATUS (AE_OK);
258}
259
260
261/*******************************************************************************
262 *
263 * FUNCTION:    AcpiAmlAccessNamedField
264 *
265 * PARAMETERS:  Mode                - ACPI_READ or ACPI_WRITE
266 *              NamedField          - Handle for field to be accessed
267 *              *Buffer             - Value(s) to be read or written
268 *              BufferLength          - Number of bytes to transfer
269 *
270 * RETURN:      Status
271 *
272 * DESCRIPTION: Read or write a named field
273 *
274 ******************************************************************************/
275
276ACPI_STATUS
277AcpiAmlAccessNamedField (
278    UINT32                  Mode,
279    ACPI_HANDLE             NamedField,
280    void                    *Buffer,
281    UINT32                  BufferLength)
282{
283    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
284    ACPI_STATUS             Status = AE_OK;
285    BOOLEAN                 Locked = FALSE;
286    UINT32                  BitGranularity = 0;
287    UINT32                  ByteGranularity;
288    UINT32                  DatumLength;
289    UINT32                  ActualByteLength;
290    UINT32                  ByteFieldLength;
291
292
293    FUNCTION_TRACE_PTR ("AmlAccessNamedField", NamedField);
294
295
296    /* Basic data checking */
297    if ((!NamedField) || (ACPI_READ == Mode && !Buffer))
298    {
299        DEBUG_PRINT (ACPI_ERROR,
300            ("AcpiAmlAccessNamedField: Internal error - null parameter\n"));
301        return_ACPI_STATUS (AE_AML_INTERNAL);
302    }
303
304    /* Get the attached field object */
305
306    ObjDesc = AcpiNsGetAttachedObject (NamedField);
307    if (!ObjDesc)
308    {
309        DEBUG_PRINT (ACPI_ERROR,
310            ("AmlAccessNamedField: Internal error - null value pointer\n"));
311        return_ACPI_STATUS (AE_AML_INTERNAL);
312    }
313
314    /* Check the type */
315
316    if (INTERNAL_TYPE_DEF_FIELD != AcpiNsGetType (NamedField))
317    {
318        DEBUG_PRINT (ACPI_ERROR,
319            ("AmlAccessNamedField: Name %4.4s type %x is not a defined field\n",
320            &(((ACPI_NAMESPACE_NODE *) NamedField)->Name),
321            AcpiNsGetType (NamedField)));
322        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
323    }
324
325    /* ObjDesc valid and NamedField is a defined field  */
326
327    DEBUG_PRINT (ACPI_INFO,
328        ("AccessNamedField: Obj=%p Type=%x Buf=%p Len=%x\n",
329        ObjDesc, ObjDesc->Common.Type, Buffer, BufferLength));
330    DEBUG_PRINT (ACPI_INFO,
331        ("AccessNamedField: Mode=%d FieldLen=%d, BitOffset=%d\n",
332        Mode, ObjDesc->FieldUnit.Length, ObjDesc->FieldUnit.BitOffset));
333    DUMP_ENTRY (NamedField, ACPI_INFO);
334
335
336    /* Double-check that the attached object is also a field */
337
338    if (INTERNAL_TYPE_DEF_FIELD != ObjDesc->Common.Type)
339    {
340        DEBUG_PRINT (ACPI_ERROR,
341            ("AmlAccessNamedField: Internal error - Name %4.4s type %x does not match value-type %x at %p\n",
342            &(((ACPI_NAMESPACE_NODE *) NamedField)->Name),
343            AcpiNsGetType (NamedField), ObjDesc->Common.Type, ObjDesc));
344        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
345    }
346
347
348    /*
349     * Granularity was decoded from the field access type
350     * (AnyAcc will be the same as ByteAcc)
351     */
352
353    BitGranularity = ObjDesc->FieldUnit.Granularity;
354    ByteGranularity = DIV_8 (BitGranularity);
355
356    /*
357     * Check if request is too large for the field, and silently truncate
358     * if necessary
359     */
360
361    /* TBD: [Errors] should an error be returned in this case? */
362
363    ByteFieldLength = (UINT32) DIV_8 (ObjDesc->FieldUnit.Length + 7);
364
365
366    ActualByteLength = BufferLength;
367    if (BufferLength > ByteFieldLength)
368    {
369        DEBUG_PRINT (ACPI_INFO,
370            ("AmlAccessNamedField: Byte length %X truncated to %X\n",
371            ActualByteLength, ByteFieldLength));
372
373        ActualByteLength = ByteFieldLength;
374    }
375
376    /* TBD: should these round down to a power of 2? */
377
378    if (DIV_8(BitGranularity) > ByteFieldLength)
379    {
380        DEBUG_PRINT (ACPI_INFO,
381            ("AmlAccessNamedField: Bit granularity %X truncated to %X\n",
382            BitGranularity, MUL_8(ByteFieldLength)));
383
384        BitGranularity = MUL_8(ByteFieldLength);
385    }
386
387    if (ByteGranularity > ByteFieldLength)
388    {
389        DEBUG_PRINT (ACPI_INFO,
390            ("AmlAccessNamedField: Byte granularity %X truncated to %X\n",
391            ByteGranularity, ByteFieldLength));
392
393        ByteGranularity = ByteFieldLength;
394    }
395
396
397    /* Convert byte count to datum count, round up if necessary */
398
399    DatumLength = (ActualByteLength + (ByteGranularity-1)) / ByteGranularity;
400
401    DEBUG_PRINT (ACPI_INFO,
402        ("ByteLen=%x, DatumLen=%x, BitGran=%x, ByteGran=%x\n",
403        ActualByteLength, DatumLength, BitGranularity, ByteGranularity));
404
405
406    /* Get the global lock if needed */
407
408    Locked = AcpiAmlAcquireGlobalLock (ObjDesc->FieldUnit.LockRule);
409
410
411    /* Perform the actual read or write of the buffer */
412
413    switch (Mode)
414    {
415    case ACPI_READ:
416
417        Status = AcpiAmlReadField (ObjDesc, Buffer, BufferLength,
418                                    ActualByteLength, DatumLength,
419                                    BitGranularity, ByteGranularity);
420        break;
421
422
423    case ACPI_WRITE:
424
425        Status = AcpiAmlWriteField (ObjDesc, Buffer, BufferLength,
426                                    ActualByteLength, DatumLength,
427                                    BitGranularity, ByteGranularity);
428        break;
429
430
431    default:
432
433        DEBUG_PRINT (ACPI_ERROR,
434            ("AccessNamedField: Unknown I/O Mode: %X\n", Mode));
435        Status = AE_BAD_PARAMETER;
436        break;
437    }
438
439
440    /* Release global lock if we acquired it earlier */
441
442    AcpiAmlReleaseGlobalLock (Locked);
443
444    return_ACPI_STATUS (Status);
445}
446
447