exfield.c revision 107325
1234353Sdim/******************************************************************************
2193323Sed *
3193323Sed * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
4193323Sed *              $Revision: 115 $
5193323Sed *
6193323Sed *****************************************************************************/
7193323Sed
8193323Sed/******************************************************************************
9193323Sed *
10193323Sed * 1. Copyright Notice
11193323Sed *
12193323Sed * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp.
13193323Sed * All rights reserved.
14193323Sed *
15193323Sed * 2. License
16193323Sed *
17193323Sed * 2.1. This is your license from Intel Corp. under its intellectual property
18193323Sed * rights.  You may have additional license terms from the party that provided
19193323Sed * you this software, covering your right to use that party's intellectual
20193323Sed * property rights.
21193323Sed *
22193323Sed * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23193323Sed * copy of the source code appearing in this file ("Covered Code") an
24193323Sed * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25193323Sed * base code distributed originally by Intel ("Original Intel Code") to copy,
26193323Sed * make derivatives, distribute, use and display any portion of the Covered
27193323Sed * Code in any form, with the right to sublicense such rights; and
28193323Sed *
29193323Sed * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30193323Sed * license (with the right to sublicense), under only those claims of Intel
31193323Sed * patents that are infringed by the Original Intel Code, to make, use, sell,
32193323Sed * offer to sell, and import the Covered Code and derivative works thereof
33193323Sed * solely to the minimum extent necessary to exercise the above copyright
34193323Sed * license, and in no event shall the patent license extend to any additions
35193323Sed * to or modifications of the Original Intel Code.  No other license or right
36193323Sed * is granted directly or by implication, estoppel or otherwise;
37193323Sed *
38193323Sed * The above copyright and patent license is granted only if the following
39193323Sed * conditions are met:
40193323Sed *
41193323Sed * 3. Conditions
42193323Sed *
43193323Sed * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44193323Sed * Redistribution of source code of any substantial portion of the Covered
45193323Sed * Code or modification with rights to further distribute source must include
46193323Sed * the above Copyright Notice, the above License, this list of Conditions,
47193323Sed * and the following Disclaimer and Export Compliance provision.  In addition,
48193323Sed * Licensee must cause all Covered Code to which Licensee contributes to
49193323Sed * contain a file documenting the changes Licensee made to create that Covered
50193323Sed * Code and the date of any change.  Licensee must include in that file the
51193323Sed * documentation of any changes made by any predecessor Licensee.  Licensee
52193323Sed * must include a prominent statement that the modification is derived,
53193323Sed * directly or indirectly, from Original Intel Code.
54193323Sed *
55193323Sed * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56193323Sed * Redistribution of source code of any substantial portion of the Covered
57193323Sed * Code or modification without rights to further distribute source must
58193323Sed * include the following Disclaimer and Export Compliance provision in the
59193323Sed * documentation and/or other materials provided with distribution.  In
60193323Sed * addition, Licensee may not authorize further sublicense of source of any
61193323Sed * portion of the Covered Code, and must include terms to the effect that the
62193323Sed * license from Licensee to its licensee is limited to the intellectual
63193323Sed * property embodied in the software Licensee provides to its licensee, and
64193323Sed * not to intellectual property embodied in modifications its licensee may
65193323Sed * make.
66193323Sed *
67193323Sed * 3.3. Redistribution of Executable. Redistribution in executable form of any
68193323Sed * substantial portion of the Covered Code or modification must reproduce the
69193323Sed * above Copyright Notice, and the following Disclaimer and Export Compliance
70193323Sed * provision in the documentation and/or other materials provided with the
71193323Sed * distribution.
72193323Sed *
73193323Sed * 3.4. Intel retains all right, title, and interest in and to the Original
74193323Sed * Intel Code.
75193323Sed *
76193323Sed * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77193323Sed * Intel shall be used in advertising or otherwise to promote the sale, use or
78193323Sed * other dealings in products derived from or relating to the Covered Code
79193323Sed * without prior written authorization from Intel.
80193323Sed *
81193323Sed * 4. Disclaimer and Export Compliance
82193323Sed *
83193323Sed * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84193323Sed * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85193323Sed * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86193323Sed * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87193323Sed * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89193323Sed * PARTICULAR PURPOSE.
90193323Sed *
91193323Sed * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92193323Sed * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93193323Sed * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94193323Sed * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95193323Sed * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96193323Sed * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97193323Sed * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98193323Sed * LIMITED REMEDY.
99193323Sed *
100193323Sed * 4.3. Licensee shall not export, either directly or indirectly, any of this
101193323Sed * software or system incorporating such software without first obtaining any
102193323Sed * required license or other approval from the U. S. Department of Commerce or
103193323Sed * any other agency or department of the United States Government.  In the
104193323Sed * event Licensee exports any such software from the United States or
105193323Sed * re-exports any such software from a foreign destination, Licensee shall
106193323Sed * ensure that the distribution and export/re-export of the software is in
107193323Sed * compliance with all laws, regulations, orders, or other restrictions of the
108193323Sed * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109193323Sed * any of its subsidiaries will export/re-export any technical data, process,
110193323Sed * software, or service, directly or indirectly, to any country for which the
111193323Sed * United States government or any agency thereof requires an export license,
112193323Sed * other governmental approval, or letter of assurance, without first obtaining
113193323Sed * such license, approval or letter.
114193323Sed *
115193323Sed *****************************************************************************/
116193323Sed
117193323Sed
118193323Sed#define __EXFIELD_C__
119193323Sed
120193323Sed#include "acpi.h"
121193323Sed#include "acdispat.h"
122193323Sed#include "acinterp.h"
123193323Sed
124193323Sed
125193323Sed#define _COMPONENT          ACPI_EXECUTER
126193323Sed        ACPI_MODULE_NAME    ("exfield")
127193323Sed
128193323Sed
129193323Sed/*******************************************************************************
130193323Sed *
131193323Sed * FUNCTION:    AcpiExReadDataFromField
132193323Sed *
133193323Sed * PARAMETERS:  WalkState           - Current execution state
134193323Sed *              ObjDesc             - The named field
135193323Sed *              RetBufferDesc       - Where the return data object is stored
136193323Sed *
137193323Sed * RETURN:      Status
138193323Sed *
139193323Sed * DESCRIPTION: Read from a named field.  Returns either an Integer or a
140193323Sed *              Buffer, depending on the size of the field.
141193323Sed *
142193323Sed ******************************************************************************/
143193323Sed
144193323SedACPI_STATUS
145193323SedAcpiExReadDataFromField (
146193323Sed    ACPI_WALK_STATE         *WalkState,
147193323Sed    ACPI_OPERAND_OBJECT     *ObjDesc,
148193323Sed    ACPI_OPERAND_OBJECT     **RetBufferDesc)
149193323Sed{
150193323Sed    ACPI_STATUS             Status;
151193323Sed    ACPI_OPERAND_OBJECT     *BufferDesc;
152193323Sed    UINT32                  Length;
153193323Sed    void                    *Buffer;
154193323Sed    BOOLEAN                 Locked;
155193323Sed
156193323Sed
157193323Sed    ACPI_FUNCTION_TRACE_PTR ("ExReadDataFromField", ObjDesc);
158193323Sed
159193323Sed
160193323Sed    /* Parameter validation */
161193323Sed
162193323Sed    if (!ObjDesc)
163193323Sed    {
164193323Sed        return_ACPI_STATUS (AE_AML_NO_OPERAND);
165193323Sed    }
166193323Sed
167193323Sed    if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD)
168193323Sed    {
169193323Sed        /*
170193323Sed         * If the BufferField arguments have not been previously evaluated,
171193323Sed         * evaluate them now and save the results.
172193323Sed         */
173193323Sed        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
174193323Sed        {
175193323Sed            Status = AcpiDsGetBufferFieldArguments (ObjDesc);
176193323Sed            if (ACPI_FAILURE (Status))
177193323Sed            {
178193323Sed                return_ACPI_STATUS (Status);
179193323Sed            }
180193323Sed        }
181193323Sed    }
182193323Sed    else if ((ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
183193323Sed             (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS))
184193323Sed    {
185193323Sed        /*
186193323Sed         * This is an SMBus read.  We must create a buffer to hold the data
187193323Sed         * and directly access the region handler.
188193323Sed         */
189193323Sed        BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE);
190193323Sed        if (!BufferDesc)
191193323Sed        {
192193323Sed            return_ACPI_STATUS (AE_NO_MEMORY);
193193323Sed        }
194193323Sed
195193323Sed        /* Lock entire transaction if requested */
196193323Sed
197193323Sed        Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
198193323Sed
199193323Sed        /*
200193323Sed         * Perform the read.
201193323Sed         * Note: Smbus protocol value is passed in upper 16-bits of Function
202193323Sed         */
203193323Sed        Status = AcpiExAccessRegion (ObjDesc, 0,
204193323Sed                        ACPI_CAST_PTR (ACPI_INTEGER, BufferDesc->Buffer.Pointer),
205193323Sed                        ACPI_READ | (ObjDesc->Field.Attribute << 16));
206193323Sed        AcpiExReleaseGlobalLock (Locked);
207193323Sed        goto Exit;
208193323Sed    }
209193323Sed
210193323Sed    /*
211193323Sed     * Allocate a buffer for the contents of the field.
212193323Sed     *
213193323Sed     * If the field is larger than the size of an ACPI_INTEGER, create
214193323Sed     * a BUFFER to hold it.  Otherwise, use an INTEGER.  This allows
215193323Sed     * the use of arithmetic operators on the returned value if the
216193323Sed     * field size is equal or smaller than an Integer.
217193323Sed     *
218193323Sed     * Note: Field.length is in bits.
219193323Sed     */
220193323Sed    Length = ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->Field.BitLength);
221193323Sed    if (Length > AcpiGbl_IntegerByteWidth)
222193323Sed    {
223193323Sed        /* Field is too large for an Integer, create a Buffer instead */
224193323Sed
225193323Sed        BufferDesc = AcpiUtCreateBufferObject (Length);
226193323Sed        if (!BufferDesc)
227193323Sed        {
228193323Sed            return_ACPI_STATUS (AE_NO_MEMORY);
229193323Sed        }
230193323Sed        Buffer = BufferDesc->Buffer.Pointer;
231193323Sed    }
232193323Sed    else
233193323Sed    {
234193323Sed        /* Field will fit within an Integer (normal case) */
235193323Sed
236193323Sed        BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
237193323Sed        if (!BufferDesc)
238193323Sed        {
239193323Sed            return_ACPI_STATUS (AE_NO_MEMORY);
240193323Sed        }
241193323Sed
242193323Sed        Length = AcpiGbl_IntegerByteWidth;
243193323Sed        BufferDesc->Integer.Value = 0;
244193323Sed        Buffer = &BufferDesc->Integer.Value;
245193323Sed    }
246193323Sed
247193323Sed    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
248193323Sed        "Obj=%p Type=%X Buf=%p Len=%X\n",
249193323Sed        ObjDesc, ACPI_GET_OBJECT_TYPE (ObjDesc), Buffer, Length));
250193323Sed    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
251193323Sed        "FieldWrite: BitLen=%X BitOff=%X ByteOff=%X\n",
252193323Sed        ObjDesc->CommonField.BitLength,
253193323Sed        ObjDesc->CommonField.StartFieldBitOffset,
254193323Sed        ObjDesc->CommonField.BaseByteOffset));
255193323Sed
256193323Sed    /* Lock entire transaction if requested */
257193323Sed
258193323Sed    Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
259193323Sed
260193323Sed    /* Read from the field */
261193323Sed
262193323Sed    Status = AcpiExExtractFromField (ObjDesc, Buffer, Length);
263193323Sed    AcpiExReleaseGlobalLock (Locked);
264193323Sed
265193323Sed
266193323SedExit:
267193323Sed    if (ACPI_FAILURE (Status))
268193323Sed    {
269193323Sed        AcpiUtRemoveReference (BufferDesc);
270193323Sed    }
271193323Sed    else if (RetBufferDesc)
272193323Sed    {
273193323Sed        *RetBufferDesc = BufferDesc;
274193323Sed    }
275193323Sed
276193323Sed    return_ACPI_STATUS (Status);
277193323Sed}
278193323Sed
279193323Sed
280193323Sed/*******************************************************************************
281193323Sed *
282193323Sed * FUNCTION:    AcpiExWriteDataToField
283193323Sed *
284193323Sed * PARAMETERS:  SourceDesc          - Contains data to write
285193323Sed *              ObjDesc             - The named field
286193323Sed *
287193323Sed * RETURN:      Status
288193323Sed *
289193323Sed * DESCRIPTION: Write to a named field
290193323Sed *
291193323Sed ******************************************************************************/
292193323Sed
293193323SedACPI_STATUS
294193323SedAcpiExWriteDataToField (
295193323Sed    ACPI_OPERAND_OBJECT     *SourceDesc,
296193323Sed    ACPI_OPERAND_OBJECT     *ObjDesc,
297193323Sed    ACPI_OPERAND_OBJECT     **ResultDesc)
298193323Sed{
299193323Sed    ACPI_STATUS             Status;
300193323Sed    UINT32                  Length;
301193323Sed    UINT32                  RequiredLength;
302193323Sed    void                    *Buffer;
303193323Sed    void                    *NewBuffer;
304193323Sed    BOOLEAN                 Locked;
305193323Sed    ACPI_OPERAND_OBJECT     *BufferDesc;
306193323Sed
307193323Sed
308193323Sed    ACPI_FUNCTION_TRACE_PTR ("ExWriteDataToField", ObjDesc);
309193323Sed
310193323Sed
311193323Sed    /* Parameter validation */
312193323Sed
313193323Sed    if (!SourceDesc || !ObjDesc)
314193323Sed    {
315193323Sed        return_ACPI_STATUS (AE_AML_NO_OPERAND);
316193323Sed    }
317193323Sed
318193323Sed    if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD)
319193323Sed    {
320193323Sed        /*
321193323Sed         * If the BufferField arguments have not been previously evaluated,
322193323Sed         * evaluate them now and save the results.
323193323Sed         */
324193323Sed        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
325193323Sed        {
326193323Sed            Status = AcpiDsGetBufferFieldArguments (ObjDesc);
327193323Sed            if (ACPI_FAILURE (Status))
328193323Sed            {
329193323Sed                return_ACPI_STATUS (Status);
330193323Sed            }
331193323Sed        }
332193323Sed    }
333193323Sed    else if ((ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
334193323Sed             (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS))
335193323Sed    {
336193323Sed        /*
337193323Sed         * This is an SMBus write.  We will bypass the entire field mechanism
338193323Sed         * and handoff the buffer directly to the handler.
339193323Sed         *
340193323Sed         * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
341193323Sed         */
342193323Sed        if (ACPI_GET_OBJECT_TYPE (SourceDesc) != ACPI_TYPE_BUFFER)
343193323Sed        {
344193323Sed            ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n",
345193323Sed                AcpiUtGetObjectTypeName (SourceDesc)));
346193323Sed            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
347193323Sed        }
348193323Sed
349193323Sed        if (SourceDesc->Buffer.Length < ACPI_SMBUS_BUFFER_SIZE)
350193323Sed        {
351193323Sed            ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n",
352193323Sed                ACPI_SMBUS_BUFFER_SIZE, SourceDesc->Buffer.Length));
353193323Sed            return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
354193323Sed        }
355193323Sed
356193323Sed        BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE);
357193323Sed        if (!BufferDesc)
358193323Sed        {
359193323Sed            return_ACPI_STATUS (AE_NO_MEMORY);
360193323Sed        }
361193323Sed
362193323Sed        Buffer = BufferDesc->Buffer.Pointer;
363193323Sed        ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer, ACPI_SMBUS_BUFFER_SIZE);
364193323Sed
365193323Sed        /* Lock entire transaction if requested */
366193323Sed
367193323Sed        Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
368193323Sed
369193323Sed        /*
370193323Sed         * Perform the write (returns status and perhaps data in the same buffer)
371193323Sed         * Note: SMBus protocol type is passed in upper 16-bits of Function.
372193323Sed         */
373193323Sed        Status = AcpiExAccessRegion (ObjDesc, 0,
374193323Sed                        (ACPI_INTEGER *) Buffer,
375193323Sed                        ACPI_WRITE | (ObjDesc->Field.Attribute << 16));
376193323Sed        AcpiExReleaseGlobalLock (Locked);
377193323Sed
378193323Sed        *ResultDesc = BufferDesc;
379193323Sed        return_ACPI_STATUS (Status);
380193323Sed    }
381193323Sed
382193323Sed    /*
383193323Sed     * Get a pointer to the data to be written
384193323Sed     */
385193323Sed    switch (ACPI_GET_OBJECT_TYPE (SourceDesc))
386193323Sed    {
387193323Sed    case ACPI_TYPE_INTEGER:
388193323Sed        Buffer = &SourceDesc->Integer.Value;
389193323Sed        Length = sizeof (SourceDesc->Integer.Value);
390193323Sed        break;
391193323Sed
392193323Sed    case ACPI_TYPE_BUFFER:
393193323Sed        Buffer = SourceDesc->Buffer.Pointer;
394193323Sed        Length = SourceDesc->Buffer.Length;
395193323Sed        break;
396193323Sed
397193323Sed    case ACPI_TYPE_STRING:
398193323Sed        Buffer = SourceDesc->String.Pointer;
399193323Sed        Length = SourceDesc->String.Length;
400193323Sed        break;
401193323Sed
402193323Sed    default:
403193323Sed        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
404193323Sed    }
405193323Sed
406193323Sed    /*
407193323Sed     * We must have a buffer that is at least as long as the field
408193323Sed     * we are writing to.  This is because individual fields are
409193323Sed     * indivisible and partial writes are not supported -- as per
410193323Sed     * the ACPI specification.
411193323Sed     */
412193323Sed    NewBuffer = NULL;
413193323Sed    RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength);
414193323Sed
415193323Sed    if (Length < RequiredLength)
416193323Sed    {
417193323Sed        /* We need to create a new buffer */
418193323Sed
419193323Sed        NewBuffer = ACPI_MEM_CALLOCATE (RequiredLength);
420193323Sed        if (!NewBuffer)
421193323Sed        {
422193323Sed            return_ACPI_STATUS (AE_NO_MEMORY);
423193323Sed        }
424193323Sed
425193323Sed        /*
426193323Sed         * Copy the original data to the new buffer, starting
427193323Sed         * at Byte zero.  All unused (upper) bytes of the
428193323Sed         * buffer will be 0.
429193323Sed         */
430193323Sed        ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, Length);
431193323Sed        Buffer = NewBuffer;
432193323Sed        Length = RequiredLength;
433193323Sed    }
434193323Sed
435193323Sed    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
436193323Sed        "Obj=%p Type=%X Buf=%p Len=%X\n",
437193323Sed        ObjDesc, ACPI_GET_OBJECT_TYPE (ObjDesc), Buffer, Length));
438193323Sed    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
439193323Sed        "FieldRead: BitLen=%X BitOff=%X ByteOff=%X\n",
440193323Sed        ObjDesc->CommonField.BitLength,
441193323Sed        ObjDesc->CommonField.StartFieldBitOffset,
442193323Sed        ObjDesc->CommonField.BaseByteOffset));
443193323Sed
444193323Sed    /* Lock entire transaction if requested */
445193323Sed
446193323Sed    Locked = AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
447193323Sed
448193323Sed    /* Write to the field */
449193323Sed
450193323Sed    Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length);
451193323Sed    AcpiExReleaseGlobalLock (Locked);
452193323Sed
453193323Sed    /* Free temporary buffer if we used one */
454193323Sed
455193323Sed    if (NewBuffer)
456193323Sed    {
457193323Sed        ACPI_MEM_FREE (NewBuffer);
458193323Sed    }
459193323Sed
460193323Sed    return_ACPI_STATUS (Status);
461193323Sed}
462193323Sed
463193323Sed
464193323Sed