exfield.c revision 167802
1273929Sjmmv/******************************************************************************
2273929Sjmmv *
3240122Smarcel * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
4240122Smarcel *              $Revision: 1.131 $
5240122Smarcel *
6240122Smarcel *****************************************************************************/
7240122Smarcel
8240122Smarcel/******************************************************************************
9240122Smarcel *
10240122Smarcel * 1. Copyright Notice
11240122Smarcel *
12240122Smarcel * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
13240122Smarcel * All rights reserved.
14240122Smarcel *
15240122Smarcel * 2. License
16240122Smarcel *
17240122Smarcel * 2.1. This is your license from Intel Corp. under its intellectual property
18240122Smarcel * rights.  You may have additional license terms from the party that provided
19240122Smarcel * you this software, covering your right to use that party's intellectual
20240122Smarcel * property rights.
21240122Smarcel *
22240122Smarcel * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23240122Smarcel * copy of the source code appearing in this file ("Covered Code") an
24240122Smarcel * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25240122Smarcel * base code distributed originally by Intel ("Original Intel Code") to copy,
26258289Sjmmv * make derivatives, distribute, use and display any portion of the Covered
27240122Smarcel * Code in any form, with the right to sublicense such rights; and
28240122Smarcel *
29240122Smarcel * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30240122Smarcel * license (with the right to sublicense), under only those claims of Intel
31240122Smarcel * patents that are infringed by the Original Intel Code, to make, use, sell,
32240122Smarcel * offer to sell, and import the Covered Code and derivative works thereof
33240122Smarcel * solely to the minimum extent necessary to exercise the above copyright
34240122Smarcel * license, and in no event shall the patent license extend to any additions
35240122Smarcel * to or modifications of the Original Intel Code.  No other license or right
36240122Smarcel * is granted directly or by implication, estoppel or otherwise;
37240122Smarcel *
38240122Smarcel * The above copyright and patent license is granted only if the following
39240122Smarcel * conditions are met:
40240122Smarcel *
41240122Smarcel * 3. Conditions
42240122Smarcel *
43240122Smarcel * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44240122Smarcel * Redistribution of source code of any substantial portion of the Covered
45240122Smarcel * Code or modification with rights to further distribute source must include
46240122Smarcel * the above Copyright Notice, the above License, this list of Conditions,
47240122Smarcel * and the following Disclaimer and Export Compliance provision.  In addition,
48240122Smarcel * Licensee must cause all Covered Code to which Licensee contributes to
49240122Smarcel * contain a file documenting the changes Licensee made to create that Covered
50240122Smarcel * Code and the date of any change.  Licensee must include in that file the
51240122Smarcel * documentation of any changes made by any predecessor Licensee.  Licensee
52240122Smarcel * must include a prominent statement that the modification is derived,
53240122Smarcel * directly or indirectly, from Original Intel Code.
54240122Smarcel *
55240122Smarcel * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56240122Smarcel * Redistribution of source code of any substantial portion of the Covered
57240122Smarcel * Code or modification without rights to further distribute source must
58240122Smarcel * include the following Disclaimer and Export Compliance provision in the
59262000Sjmmv * documentation and/or other materials provided with distribution.  In
60240122Smarcel * addition, Licensee may not authorize further sublicense of source of any
61273929Sjmmv * portion of the Covered Code, and must include terms to the effect that the
62240122Smarcel * license from Licensee to its licensee is limited to the intellectual
63240122Smarcel * property embodied in the software Licensee provides to its licensee, and
64240122Smarcel * not to intellectual property embodied in modifications its licensee may
65240122Smarcel * make.
66240122Smarcel *
67240122Smarcel * 3.3. Redistribution of Executable. Redistribution in executable form of any
68273929Sjmmv * substantial portion of the Covered Code or modification must reproduce the
69240122Smarcel * above Copyright Notice, and the following Disclaimer and Export Compliance
70240122Smarcel * provision in the documentation and/or other materials provided with the
71240122Smarcel * distribution.
72240122Smarcel *
73240122Smarcel * 3.4. Intel retains all right, title, and interest in and to the Original
74240122Smarcel * Intel Code.
75240122Smarcel *
76240122Smarcel * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77273929Sjmmv * Intel shall be used in advertising or otherwise to promote the sale, use or
78240122Smarcel * other dealings in products derived from or relating to the Covered Code
79240122Smarcel * without prior written authorization from Intel.
80240122Smarcel *
81240122Smarcel * 4. Disclaimer and Export Compliance
82240122Smarcel *
83261897Sjmmv * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84240122Smarcel * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85240122Smarcel * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86273929Sjmmv * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87240122Smarcel * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88240122Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89240122Smarcel * PARTICULAR PURPOSE.
90240122Smarcel *
91240122Smarcel * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92273929Sjmmv * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#define __EXFIELD_C__
119
120#include <contrib/dev/acpica/acpi.h>
121#include <contrib/dev/acpica/acdispat.h>
122#include <contrib/dev/acpica/acinterp.h>
123
124
125#define _COMPONENT          ACPI_EXECUTER
126        ACPI_MODULE_NAME    ("exfield")
127
128
129/*******************************************************************************
130 *
131 * FUNCTION:    AcpiExReadDataFromField
132 *
133 * PARAMETERS:  WalkState           - Current execution state
134 *              ObjDesc             - The named field
135 *              RetBufferDesc       - Where the return data object is stored
136 *
137 * RETURN:      Status
138 *
139 * DESCRIPTION: Read from a named field.  Returns either an Integer or a
140 *              Buffer, depending on the size of the field.
141 *
142 ******************************************************************************/
143
144ACPI_STATUS
145AcpiExReadDataFromField (
146    ACPI_WALK_STATE         *WalkState,
147    ACPI_OPERAND_OBJECT     *ObjDesc,
148    ACPI_OPERAND_OBJECT     **RetBufferDesc)
149{
150    ACPI_STATUS             Status;
151    ACPI_OPERAND_OBJECT     *BufferDesc;
152    ACPI_SIZE               Length;
153    void                    *Buffer;
154
155
156    ACPI_FUNCTION_TRACE_PTR (ExReadDataFromField, ObjDesc);
157
158
159    /* Parameter validation */
160
161    if (!ObjDesc)
162    {
163        return_ACPI_STATUS (AE_AML_NO_OPERAND);
164    }
165    if (!RetBufferDesc)
166    {
167        return_ACPI_STATUS (AE_BAD_PARAMETER);
168    }
169
170    if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD)
171    {
172        /*
173         * If the BufferField arguments have not been previously evaluated,
174         * evaluate them now and save the results.
175         */
176        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
177        {
178            Status = AcpiDsGetBufferFieldArguments (ObjDesc);
179            if (ACPI_FAILURE (Status))
180            {
181                return_ACPI_STATUS (Status);
182            }
183        }
184    }
185    else if ((ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
186             (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS))
187    {
188        /*
189         * This is an SMBus read.  We must create a buffer to hold the data
190         * and directly access the region handler.
191         */
192        BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE);
193        if (!BufferDesc)
194        {
195            return_ACPI_STATUS (AE_NO_MEMORY);
196        }
197
198        /* Lock entire transaction if requested */
199
200        AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
201
202        /*
203         * Perform the read.
204         * Note: Smbus protocol value is passed in upper 16-bits of Function
205         */
206        Status = AcpiExAccessRegion (ObjDesc, 0,
207                    ACPI_CAST_PTR (ACPI_INTEGER, BufferDesc->Buffer.Pointer),
208                    ACPI_READ | (ObjDesc->Field.Attribute << 16));
209        AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
210        goto Exit;
211    }
212
213    /*
214     * Allocate a buffer for the contents of the field.
215     *
216     * If the field is larger than the size of an ACPI_INTEGER, create
217     * a BUFFER to hold it.  Otherwise, use an INTEGER.  This allows
218     * the use of arithmetic operators on the returned value if the
219     * field size is equal or smaller than an Integer.
220     *
221     * Note: Field.length is in bits.
222     */
223    Length = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->Field.BitLength);
224    if (Length > AcpiGbl_IntegerByteWidth)
225    {
226        /* Field is too large for an Integer, create a Buffer instead */
227
228        BufferDesc = AcpiUtCreateBufferObject (Length);
229        if (!BufferDesc)
230        {
231            return_ACPI_STATUS (AE_NO_MEMORY);
232        }
233        Buffer = BufferDesc->Buffer.Pointer;
234    }
235    else
236    {
237        /* Field will fit within an Integer (normal case) */
238
239        BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
240        if (!BufferDesc)
241        {
242            return_ACPI_STATUS (AE_NO_MEMORY);
243        }
244
245        Length = AcpiGbl_IntegerByteWidth;
246        BufferDesc->Integer.Value = 0;
247        Buffer = &BufferDesc->Integer.Value;
248    }
249
250    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
251        "FieldRead [TO]:   Obj %p, Type %X, Buf %p, ByteLen %X\n",
252        ObjDesc, ACPI_GET_OBJECT_TYPE (ObjDesc), Buffer, (UINT32) Length));
253    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
254        "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
255        ObjDesc->CommonField.BitLength,
256        ObjDesc->CommonField.StartFieldBitOffset,
257        ObjDesc->CommonField.BaseByteOffset));
258
259    /* Lock entire transaction if requested */
260
261    AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
262
263    /* Read from the field */
264
265    Status = AcpiExExtractFromField (ObjDesc, Buffer, (UINT32) Length);
266    AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
267
268
269Exit:
270    if (ACPI_FAILURE (Status))
271    {
272        AcpiUtRemoveReference (BufferDesc);
273    }
274    else
275    {
276        *RetBufferDesc = BufferDesc;
277    }
278
279    return_ACPI_STATUS (Status);
280}
281
282
283/*******************************************************************************
284 *
285 * FUNCTION:    AcpiExWriteDataToField
286 *
287 * PARAMETERS:  SourceDesc          - Contains data to write
288 *              ObjDesc             - The named field
289 *              ResultDesc          - Where the return value is returned, if any
290 *
291 * RETURN:      Status
292 *
293 * DESCRIPTION: Write to a named field
294 *
295 ******************************************************************************/
296
297ACPI_STATUS
298AcpiExWriteDataToField (
299    ACPI_OPERAND_OBJECT     *SourceDesc,
300    ACPI_OPERAND_OBJECT     *ObjDesc,
301    ACPI_OPERAND_OBJECT     **ResultDesc)
302{
303    ACPI_STATUS             Status;
304    UINT32                  Length;
305    UINT32                  RequiredLength;
306    void                    *Buffer;
307    void                    *NewBuffer;
308    ACPI_OPERAND_OBJECT     *BufferDesc;
309
310
311    ACPI_FUNCTION_TRACE_PTR (ExWriteDataToField, ObjDesc);
312
313
314    /* Parameter validation */
315
316    if (!SourceDesc || !ObjDesc)
317    {
318        return_ACPI_STATUS (AE_AML_NO_OPERAND);
319    }
320
321    if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_BUFFER_FIELD)
322    {
323        /*
324         * If the BufferField arguments have not been previously evaluated,
325         * evaluate them now and save the results.
326         */
327        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
328        {
329            Status = AcpiDsGetBufferFieldArguments (ObjDesc);
330            if (ACPI_FAILURE (Status))
331            {
332                return_ACPI_STATUS (Status);
333            }
334        }
335    }
336    else if ((ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
337             (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_SMBUS))
338    {
339        /*
340         * This is an SMBus write.  We will bypass the entire field mechanism
341         * and handoff the buffer directly to the handler.
342         *
343         * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
344         */
345        if (ACPI_GET_OBJECT_TYPE (SourceDesc) != ACPI_TYPE_BUFFER)
346        {
347            ACPI_ERROR ((AE_INFO, "SMBus write requires Buffer, found type %s",
348                AcpiUtGetObjectTypeName (SourceDesc)));
349
350            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
351        }
352
353        if (SourceDesc->Buffer.Length < ACPI_SMBUS_BUFFER_SIZE)
354        {
355            ACPI_ERROR ((AE_INFO,
356                "SMBus write requires Buffer of length %X, found length %X",
357                ACPI_SMBUS_BUFFER_SIZE, SourceDesc->Buffer.Length));
358
359            return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
360        }
361
362        BufferDesc = AcpiUtCreateBufferObject (ACPI_SMBUS_BUFFER_SIZE);
363        if (!BufferDesc)
364        {
365            return_ACPI_STATUS (AE_NO_MEMORY);
366        }
367
368        Buffer = BufferDesc->Buffer.Pointer;
369        ACPI_MEMCPY (Buffer, SourceDesc->Buffer.Pointer,
370            ACPI_SMBUS_BUFFER_SIZE);
371
372        /* Lock entire transaction if requested */
373
374        AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
375
376        /*
377         * Perform the write (returns status and perhaps data in the
378         * same buffer)
379         * Note: SMBus protocol type is passed in upper 16-bits of Function.
380         */
381        Status = AcpiExAccessRegion (ObjDesc, 0,
382                        (ACPI_INTEGER *) Buffer,
383                        ACPI_WRITE | (ObjDesc->Field.Attribute << 16));
384        AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
385
386        *ResultDesc = BufferDesc;
387        return_ACPI_STATUS (Status);
388    }
389
390    /* Get a pointer to the data to be written */
391
392    switch (ACPI_GET_OBJECT_TYPE (SourceDesc))
393    {
394    case ACPI_TYPE_INTEGER:
395        Buffer = &SourceDesc->Integer.Value;
396        Length = sizeof (SourceDesc->Integer.Value);
397        break;
398
399    case ACPI_TYPE_BUFFER:
400        Buffer = SourceDesc->Buffer.Pointer;
401        Length = SourceDesc->Buffer.Length;
402        break;
403
404    case ACPI_TYPE_STRING:
405        Buffer = SourceDesc->String.Pointer;
406        Length = SourceDesc->String.Length;
407        break;
408
409    default:
410        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
411    }
412
413    /*
414     * We must have a buffer that is at least as long as the field
415     * we are writing to.  This is because individual fields are
416     * indivisible and partial writes are not supported -- as per
417     * the ACPI specification.
418     */
419    NewBuffer = NULL;
420    RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
421                        ObjDesc->CommonField.BitLength);
422
423    if (Length < RequiredLength)
424    {
425        /* We need to create a new buffer */
426
427        NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
428        if (!NewBuffer)
429        {
430            return_ACPI_STATUS (AE_NO_MEMORY);
431        }
432
433        /*
434         * Copy the original data to the new buffer, starting
435         * at Byte zero.  All unused (upper) bytes of the
436         * buffer will be 0.
437         */
438        ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, Length);
439        Buffer = NewBuffer;
440        Length = RequiredLength;
441    }
442
443    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
444        "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
445        SourceDesc, AcpiUtGetTypeName (ACPI_GET_OBJECT_TYPE (SourceDesc)),
446        ACPI_GET_OBJECT_TYPE (SourceDesc), Buffer, Length));
447
448    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
449        "FieldWrite [TO]:   Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
450        ObjDesc, AcpiUtGetTypeName (ACPI_GET_OBJECT_TYPE (ObjDesc)),
451        ACPI_GET_OBJECT_TYPE (ObjDesc),
452        ObjDesc->CommonField.BitLength,
453        ObjDesc->CommonField.StartFieldBitOffset,
454        ObjDesc->CommonField.BaseByteOffset));
455
456    /* Lock entire transaction if requested */
457
458    AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags);
459
460    /* Write to the field */
461
462    Status = AcpiExInsertIntoField (ObjDesc, Buffer, Length);
463    AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags);
464
465    /* Free temporary buffer if we used one */
466
467    if (NewBuffer)
468    {
469        ACPI_FREE (NewBuffer);
470    }
471
472    return_ACPI_STATUS (Status);
473}
474
475
476