Subversion Repositories Kolibri OS

Rev

Rev 1498 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1498 Rev 2216
1
/******************************************************************************
1
/******************************************************************************
2
 *
2
 *
3
 * Module Name: exfldio - Aml Field I/O
3
 * Module Name: exfldio - Aml Field I/O
4
 *
4
 *
5
 *****************************************************************************/
5
 *****************************************************************************/
6
 
6
 
7
/******************************************************************************
7
/******************************************************************************
8
 *
8
 *
9
 * 1. Copyright Notice
9
 * 1. Copyright Notice
10
 *
10
 *
11
 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
12
 * All rights reserved.
12
 * All rights reserved.
13
 *
13
 *
14
 * 2. License
14
 * 2. License
15
 *
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
19
 * property rights.
20
 *
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
36
 *
37
 * The above copyright and patent license is granted only if the following
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
38
 * conditions are met:
39
 *
39
 *
40
 * 3. Conditions
40
 * 3. Conditions
41
 *
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
52
 * directly or indirectly, from Original Intel Code.
53
 *
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
64
 * make.
65
 *
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
70
 * distribution.
71
 *
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
73
 * Intel Code.
74
 *
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
78
 * without prior written authorization from Intel.
79
 *
79
 *
80
 * 4. Disclaimer and Export Compliance
80
 * 4. Disclaimer and Export Compliance
81
 *
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
88
 * PARTICULAR PURPOSE.
89
 *
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
97
 * LIMITED REMEDY.
98
 *
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
112
 * such license, approval or letter.
113
 *
113
 *
114
 *****************************************************************************/
114
 *****************************************************************************/
115
 
115
 
116
 
116
 
117
#define __EXFLDIO_C__
117
#define __EXFLDIO_C__
118
 
118
 
119
#include "acpi.h"
119
#include "acpi.h"
120
#include "accommon.h"
120
#include "accommon.h"
121
#include "acinterp.h"
121
#include "acinterp.h"
122
#include "amlcode.h"
122
#include "amlcode.h"
123
#include "acevents.h"
123
#include "acevents.h"
124
#include "acdispat.h"
124
#include "acdispat.h"
125
 
125
 
126
 
126
 
127
#define _COMPONENT          ACPI_EXECUTER
127
#define _COMPONENT          ACPI_EXECUTER
128
        ACPI_MODULE_NAME    ("exfldio")
128
        ACPI_MODULE_NAME    ("exfldio")
129
 
129
 
130
/* Local prototypes */
130
/* Local prototypes */
131
 
131
 
132
static ACPI_STATUS
132
static ACPI_STATUS
133
AcpiExFieldDatumIo (
133
AcpiExFieldDatumIo (
134
    ACPI_OPERAND_OBJECT     *ObjDesc,
134
    ACPI_OPERAND_OBJECT     *ObjDesc,
135
    UINT32                  FieldDatumByteOffset,
135
    UINT32                  FieldDatumByteOffset,
136
    UINT64                  *Value,
136
    UINT64                  *Value,
137
    UINT32                  ReadWrite);
137
    UINT32                  ReadWrite);
138
 
138
 
139
static BOOLEAN
139
static BOOLEAN
140
AcpiExRegisterOverflow (
140
AcpiExRegisterOverflow (
141
    ACPI_OPERAND_OBJECT     *ObjDesc,
141
    ACPI_OPERAND_OBJECT     *ObjDesc,
142
    UINT64                  Value);
142
    UINT64                  Value);
143
 
143
 
144
static ACPI_STATUS
144
static ACPI_STATUS
145
AcpiExSetupRegion (
145
AcpiExSetupRegion (
146
    ACPI_OPERAND_OBJECT     *ObjDesc,
146
    ACPI_OPERAND_OBJECT     *ObjDesc,
147
    UINT32                  FieldDatumByteOffset);
147
    UINT32                  FieldDatumByteOffset);
148
 
148
 
149
 
149
 
150
/*******************************************************************************
150
/*******************************************************************************
151
 *
151
 *
152
 * FUNCTION:    AcpiExSetupRegion
152
 * FUNCTION:    AcpiExSetupRegion
153
 *
153
 *
154
 * PARAMETERS:  ObjDesc                 - Field to be read or written
154
 * PARAMETERS:  ObjDesc                 - Field to be read or written
155
 *              FieldDatumByteOffset    - Byte offset of this datum within the
155
 *              FieldDatumByteOffset    - Byte offset of this datum within the
156
 *                                        parent field
156
 *                                        parent field
157
 *
157
 *
158
 * RETURN:      Status
158
 * RETURN:      Status
159
 *
159
 *
160
 * DESCRIPTION: Common processing for AcpiExExtractFromField and
160
 * DESCRIPTION: Common processing for AcpiExExtractFromField and
161
 *              AcpiExInsertIntoField.  Initialize the Region if necessary and
161
 *              AcpiExInsertIntoField.  Initialize the Region if necessary and
162
 *              validate the request.
162
 *              validate the request.
163
 *
163
 *
164
 ******************************************************************************/
164
 ******************************************************************************/
165
 
165
 
166
static ACPI_STATUS
166
static ACPI_STATUS
167
AcpiExSetupRegion (
167
AcpiExSetupRegion (
168
    ACPI_OPERAND_OBJECT     *ObjDesc,
168
    ACPI_OPERAND_OBJECT     *ObjDesc,
169
    UINT32                  FieldDatumByteOffset)
169
    UINT32                  FieldDatumByteOffset)
170
{
170
{
171
    ACPI_STATUS             Status = AE_OK;
171
    ACPI_STATUS             Status = AE_OK;
172
    ACPI_OPERAND_OBJECT     *RgnDesc;
172
    ACPI_OPERAND_OBJECT     *RgnDesc;
173
 
173
 
174
 
174
 
175
    ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
175
    ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset);
176
 
176
 
177
 
177
 
178
    RgnDesc = ObjDesc->CommonField.RegionObj;
178
    RgnDesc = ObjDesc->CommonField.RegionObj;
179
 
179
 
180
    /* We must have a valid region */
180
    /* We must have a valid region */
181
 
181
 
182
    if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
182
    if (RgnDesc->Common.Type != ACPI_TYPE_REGION)
183
    {
183
    {
184
        ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
184
        ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
185
            RgnDesc->Common.Type,
185
            RgnDesc->Common.Type,
186
            AcpiUtGetObjectTypeName (RgnDesc)));
186
            AcpiUtGetObjectTypeName (RgnDesc)));
187
 
187
 
188
        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
188
        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
189
    }
189
    }
190
 
190
 
191
    /*
191
    /*
192
     * If the Region Address and Length have not been previously evaluated,
192
     * If the Region Address and Length have not been previously evaluated,
193
     * evaluate them now and save the results.
193
     * evaluate them now and save the results.
194
     */
194
     */
195
    if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
195
    if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID))
196
    {
196
    {
197
        Status = AcpiDsGetRegionArguments (RgnDesc);
197
        Status = AcpiDsGetRegionArguments (RgnDesc);
198
        if (ACPI_FAILURE (Status))
198
        if (ACPI_FAILURE (Status))
199
        {
199
        {
200
            return_ACPI_STATUS (Status);
200
            return_ACPI_STATUS (Status);
201
        }
201
        }
202
    }
202
    }
203
 
203
 
204
    /*
204
    /*
205
     * Exit now for SMBus or IPMI address space, it has a non-linear
205
     * Exit now for SMBus or IPMI address space, it has a non-linear
206
     * address space and the request cannot be directly validated
206
     * address space and the request cannot be directly validated
207
     */
207
     */
208
    if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
208
    if (RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_SMBUS ||
209
        RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
209
        RgnDesc->Region.SpaceId == ACPI_ADR_SPACE_IPMI)
210
    {
210
    {
211
        /* SMBus or IPMI has a non-linear address space */
211
        /* SMBus or IPMI has a non-linear address space */
212
 
212
 
213
        return_ACPI_STATUS (AE_OK);
213
        return_ACPI_STATUS (AE_OK);
214
    }
214
    }
215
 
215
 
216
#ifdef ACPI_UNDER_DEVELOPMENT
216
#ifdef ACPI_UNDER_DEVELOPMENT
217
    /*
217
    /*
218
     * If the Field access is AnyAcc, we can now compute the optimal
218
     * If the Field access is AnyAcc, we can now compute the optimal
219
     * access (because we know know the length of the parent region)
219
     * access (because we know know the length of the parent region)
220
     */
220
     */
221
    if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
221
    if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
222
    {
222
    {
223
        if (ACPI_FAILURE (Status))
223
        if (ACPI_FAILURE (Status))
224
        {
224
        {
225
            return_ACPI_STATUS (Status);
225
            return_ACPI_STATUS (Status);
226
        }
226
        }
227
    }
227
    }
228
#endif
228
#endif
229
 
229
 
230
    /*
230
    /*
231
     * Validate the request.  The entire request from the byte offset for a
231
     * Validate the request.  The entire request from the byte offset for a
232
     * length of one field datum (access width) must fit within the region.
232
     * length of one field datum (access width) must fit within the region.
233
     * (Region length is specified in bytes)
233
     * (Region length is specified in bytes)
234
     */
234
     */
235
    if (RgnDesc->Region.Length <
235
    if (RgnDesc->Region.Length <
236
            (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
236
            (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset +
237
            ObjDesc->CommonField.AccessByteWidth))
237
            ObjDesc->CommonField.AccessByteWidth))
238
    {
238
    {
239
        if (AcpiGbl_EnableInterpreterSlack)
239
        if (AcpiGbl_EnableInterpreterSlack)
240
        {
240
        {
241
            /*
241
            /*
242
             * Slack mode only:  We will go ahead and allow access to this
242
             * Slack mode only:  We will go ahead and allow access to this
243
             * field if it is within the region length rounded up to the next
243
             * field if it is within the region length rounded up to the next
244
             * access width boundary. ACPI_SIZE cast for 64-bit compile.
244
             * access width boundary. ACPI_SIZE cast for 64-bit compile.
245
             */
245
             */
246
            if (ACPI_ROUND_UP (RgnDesc->Region.Length,
246
            if (ACPI_ROUND_UP (RgnDesc->Region.Length,
247
                    ObjDesc->CommonField.AccessByteWidth) >=
247
                    ObjDesc->CommonField.AccessByteWidth) >=
248
                ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
248
                ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset +
249
                    ObjDesc->CommonField.AccessByteWidth +
249
                    ObjDesc->CommonField.AccessByteWidth +
250
                    FieldDatumByteOffset))
250
                    FieldDatumByteOffset))
251
            {
251
            {
252
                return_ACPI_STATUS (AE_OK);
252
                return_ACPI_STATUS (AE_OK);
253
            }
253
            }
254
        }
254
        }
255
 
255
 
256
        if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
256
        if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth)
257
        {
257
        {
258
            /*
258
            /*
259
             * This is the case where the AccessType (AccWord, etc.) is wider
259
             * This is the case where the AccessType (AccWord, etc.) is wider
260
             * than the region itself.  For example, a region of length one
260
             * than the region itself.  For example, a region of length one
261
             * byte, and a field with Dword access specified.
261
             * byte, and a field with Dword access specified.
262
             */
262
             */
263
            ACPI_ERROR ((AE_INFO,
263
            ACPI_ERROR ((AE_INFO,
264
                "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
264
                "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
265
                AcpiUtGetNodeName (ObjDesc->CommonField.Node),
265
                AcpiUtGetNodeName (ObjDesc->CommonField.Node),
266
                ObjDesc->CommonField.AccessByteWidth,
266
                ObjDesc->CommonField.AccessByteWidth,
267
                AcpiUtGetNodeName (RgnDesc->Region.Node),
267
                AcpiUtGetNodeName (RgnDesc->Region.Node),
268
                RgnDesc->Region.Length));
268
                RgnDesc->Region.Length));
269
        }
269
        }
270
 
270
 
271
        /*
271
        /*
272
         * Offset rounded up to next multiple of field width
272
         * Offset rounded up to next multiple of field width
273
         * exceeds region length, indicate an error
273
         * exceeds region length, indicate an error
274
         */
274
         */
275
        ACPI_ERROR ((AE_INFO,
275
        ACPI_ERROR ((AE_INFO,
276
            "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
276
            "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
277
            AcpiUtGetNodeName (ObjDesc->CommonField.Node),
277
            AcpiUtGetNodeName (ObjDesc->CommonField.Node),
278
            ObjDesc->CommonField.BaseByteOffset,
278
            ObjDesc->CommonField.BaseByteOffset,
279
            FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
279
            FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth,
280
            AcpiUtGetNodeName (RgnDesc->Region.Node),
280
            AcpiUtGetNodeName (RgnDesc->Region.Node),
281
            RgnDesc->Region.Length));
281
            RgnDesc->Region.Length));
282
 
282
 
283
        return_ACPI_STATUS (AE_AML_REGION_LIMIT);
283
        return_ACPI_STATUS (AE_AML_REGION_LIMIT);
284
    }
284
    }
285
 
285
 
286
    return_ACPI_STATUS (AE_OK);
286
    return_ACPI_STATUS (AE_OK);
287
}
287
}
288
 
288
 
289
 
289
 
290
/*******************************************************************************
290
/*******************************************************************************
291
 *
291
 *
292
 * FUNCTION:    AcpiExAccessRegion
292
 * FUNCTION:    AcpiExAccessRegion
293
 *
293
 *
294
 * PARAMETERS:  ObjDesc                 - Field to be read
294
 * PARAMETERS:  ObjDesc                 - Field to be read
295
 *              FieldDatumByteOffset    - Byte offset of this datum within the
295
 *              FieldDatumByteOffset    - Byte offset of this datum within the
296
 *                                        parent field
296
 *                                        parent field
297
 *              Value                   - Where to store value (must at least
297
 *              Value                   - Where to store value (must at least
298
 *                                        64 bits)
298
 *                                        64 bits)
299
 *              Function                - Read or Write flag plus other region-
299
 *              Function                - Read or Write flag plus other region-
300
 *                                        dependent flags
300
 *                                        dependent flags
301
 *
301
 *
302
 * RETURN:      Status
302
 * RETURN:      Status
303
 *
303
 *
304
 * DESCRIPTION: Read or Write a single field datum to an Operation Region.
304
 * DESCRIPTION: Read or Write a single field datum to an Operation Region.
305
 *
305
 *
306
 ******************************************************************************/
306
 ******************************************************************************/
307
 
307
 
308
ACPI_STATUS
308
ACPI_STATUS
309
AcpiExAccessRegion (
309
AcpiExAccessRegion (
310
    ACPI_OPERAND_OBJECT     *ObjDesc,
310
    ACPI_OPERAND_OBJECT     *ObjDesc,
311
    UINT32                  FieldDatumByteOffset,
311
    UINT32                  FieldDatumByteOffset,
312
    UINT64                  *Value,
312
    UINT64                  *Value,
313
    UINT32                  Function)
313
    UINT32                  Function)
314
{
314
{
315
    ACPI_STATUS             Status;
315
    ACPI_STATUS             Status;
316
    ACPI_OPERAND_OBJECT     *RgnDesc;
316
    ACPI_OPERAND_OBJECT     *RgnDesc;
317
    UINT32                  RegionOffset;
317
    UINT32                  RegionOffset;
318
 
318
 
319
 
319
 
320
    ACPI_FUNCTION_TRACE (ExAccessRegion);
320
    ACPI_FUNCTION_TRACE (ExAccessRegion);
321
 
321
 
322
 
322
 
323
    /*
323
    /*
324
     * Ensure that the region operands are fully evaluated and verify
324
     * Ensure that the region operands are fully evaluated and verify
325
     * the validity of the request
325
     * the validity of the request
326
     */
326
     */
327
    Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
327
    Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
328
    if (ACPI_FAILURE (Status))
328
    if (ACPI_FAILURE (Status))
329
    {
329
    {
330
        return_ACPI_STATUS (Status);
330
        return_ACPI_STATUS (Status);
331
    }
331
    }
332
 
332
 
333
    /*
333
    /*
334
     * The physical address of this field datum is:
334
     * The physical address of this field datum is:
335
     *
335
     *
336
     * 1) The base of the region, plus
336
     * 1) The base of the region, plus
337
     * 2) The base offset of the field, plus
337
     * 2) The base offset of the field, plus
338
     * 3) The current offset into the field
338
     * 3) The current offset into the field
339
     */
339
     */
340
    RgnDesc = ObjDesc->CommonField.RegionObj;
340
    RgnDesc = ObjDesc->CommonField.RegionObj;
341
    RegionOffset =
341
    RegionOffset =
342
        ObjDesc->CommonField.BaseByteOffset +
342
        ObjDesc->CommonField.BaseByteOffset +
343
        FieldDatumByteOffset;
343
        FieldDatumByteOffset;
344
 
344
 
345
    if ((Function & ACPI_IO_MASK) == ACPI_READ)
345
    if ((Function & ACPI_IO_MASK) == ACPI_READ)
346
    {
346
    {
347
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
347
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
348
    }
348
    }
349
    else
349
    else
350
    {
350
    {
351
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
351
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
352
    }
352
    }
353
 
353
 
354
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
354
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
355
        " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
355
        " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n",
356
        AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
356
        AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
357
        RgnDesc->Region.SpaceId,
357
        RgnDesc->Region.SpaceId,
358
        ObjDesc->CommonField.AccessByteWidth,
358
        ObjDesc->CommonField.AccessByteWidth,
359
        ObjDesc->CommonField.BaseByteOffset,
359
        ObjDesc->CommonField.BaseByteOffset,
360
        FieldDatumByteOffset,
360
        FieldDatumByteOffset,
361
        ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
361
        ACPI_CAST_PTR (void, (RgnDesc->Region.Address + RegionOffset))));
362
 
362
 
363
    /* Invoke the appropriate AddressSpace/OpRegion handler */
363
    /* Invoke the appropriate AddressSpace/OpRegion handler */
364
 
364
 
365
    Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, RegionOffset,
365
    Status = AcpiEvAddressSpaceDispatch (RgnDesc, Function, RegionOffset,
366
                ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
366
                ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);
367
 
367
 
368
    if (ACPI_FAILURE (Status))
368
    if (ACPI_FAILURE (Status))
369
    {
369
    {
370
        if (Status == AE_NOT_IMPLEMENTED)
370
        if (Status == AE_NOT_IMPLEMENTED)
371
        {
371
        {
372
            ACPI_ERROR ((AE_INFO,
372
            ACPI_ERROR ((AE_INFO,
373
                "Region %s(0x%X) not implemented",
373
                "Region %s (ID=%u) not implemented",
374
                AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
374
                AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
375
                RgnDesc->Region.SpaceId));
375
                RgnDesc->Region.SpaceId));
376
        }
376
        }
377
        else if (Status == AE_NOT_EXIST)
377
        else if (Status == AE_NOT_EXIST)
378
        {
378
        {
379
            ACPI_ERROR ((AE_INFO,
379
            ACPI_ERROR ((AE_INFO,
380
                "Region %s(0x%X) has no handler",
380
                "Region %s (ID=%u) has no handler",
381
                AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
381
                AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
382
                RgnDesc->Region.SpaceId));
382
                RgnDesc->Region.SpaceId));
383
        }
383
        }
384
    }
384
    }
385
 
385
 
386
    return_ACPI_STATUS (Status);
386
    return_ACPI_STATUS (Status);
387
}
387
}
388
 
388
 
389
 
389
 
390
/*******************************************************************************
390
/*******************************************************************************
391
 *
391
 *
392
 * FUNCTION:    AcpiExRegisterOverflow
392
 * FUNCTION:    AcpiExRegisterOverflow
393
 *
393
 *
394
 * PARAMETERS:  ObjDesc                 - Register(Field) to be written
394
 * PARAMETERS:  ObjDesc                 - Register(Field) to be written
395
 *              Value                   - Value to be stored
395
 *              Value                   - Value to be stored
396
 *
396
 *
397
 * RETURN:      TRUE if value overflows the field, FALSE otherwise
397
 * RETURN:      TRUE if value overflows the field, FALSE otherwise
398
 *
398
 *
399
 * DESCRIPTION: Check if a value is out of range of the field being written.
399
 * DESCRIPTION: Check if a value is out of range of the field being written.
400
 *              Used to check if the values written to Index and Bank registers
400
 *              Used to check if the values written to Index and Bank registers
401
 *              are out of range.  Normally, the value is simply truncated
401
 *              are out of range.  Normally, the value is simply truncated
402
 *              to fit the field, but this case is most likely a serious
402
 *              to fit the field, but this case is most likely a serious
403
 *              coding error in the ASL.
403
 *              coding error in the ASL.
404
 *
404
 *
405
 ******************************************************************************/
405
 ******************************************************************************/
406
 
406
 
407
static BOOLEAN
407
static BOOLEAN
408
AcpiExRegisterOverflow (
408
AcpiExRegisterOverflow (
409
    ACPI_OPERAND_OBJECT     *ObjDesc,
409
    ACPI_OPERAND_OBJECT     *ObjDesc,
410
    UINT64                  Value)
410
    UINT64                  Value)
411
{
411
{
412
 
412
 
413
    if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
413
    if (ObjDesc->CommonField.BitLength >= ACPI_INTEGER_BIT_SIZE)
414
    {
414
    {
415
        /*
415
        /*
416
         * The field is large enough to hold the maximum integer, so we can
416
         * The field is large enough to hold the maximum integer, so we can
417
         * never overflow it.
417
         * never overflow it.
418
         */
418
         */
419
        return (FALSE);
419
        return (FALSE);
420
    }
420
    }
421
 
421
 
422
    if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
422
    if (Value >= ((UINT64) 1 << ObjDesc->CommonField.BitLength))
423
    {
423
    {
424
        /*
424
        /*
425
         * The Value is larger than the maximum value that can fit into
425
         * The Value is larger than the maximum value that can fit into
426
         * the register.
426
         * the register.
427
         */
427
         */
428
        return (TRUE);
428
        return (TRUE);
429
    }
429
    }
430
 
430
 
431
    /* The Value will fit into the field with no truncation */
431
    /* The Value will fit into the field with no truncation */
432
 
432
 
433
    return (FALSE);
433
    return (FALSE);
434
}
434
}
435
 
435
 
436
 
436
 
437
/*******************************************************************************
437
/*******************************************************************************
438
 *
438
 *
439
 * FUNCTION:    AcpiExFieldDatumIo
439
 * FUNCTION:    AcpiExFieldDatumIo
440
 *
440
 *
441
 * PARAMETERS:  ObjDesc                 - Field to be read
441
 * PARAMETERS:  ObjDesc                 - Field to be read
442
 *              FieldDatumByteOffset    - Byte offset of this datum within the
442
 *              FieldDatumByteOffset    - Byte offset of this datum within the
443
 *                                        parent field
443
 *                                        parent field
444
 *              Value                   - Where to store value (must be 64 bits)
444
 *              Value                   - Where to store value (must be 64 bits)
445
 *              ReadWrite               - Read or Write flag
445
 *              ReadWrite               - Read or Write flag
446
 *
446
 *
447
 * RETURN:      Status
447
 * RETURN:      Status
448
 *
448
 *
449
 * DESCRIPTION: Read or Write a single datum of a field.  The FieldType is
449
 * DESCRIPTION: Read or Write a single datum of a field.  The FieldType is
450
 *              demultiplexed here to handle the different types of fields
450
 *              demultiplexed here to handle the different types of fields
451
 *              (BufferField, RegionField, IndexField, BankField)
451
 *              (BufferField, RegionField, IndexField, BankField)
452
 *
452
 *
453
 ******************************************************************************/
453
 ******************************************************************************/
454
 
454
 
455
static ACPI_STATUS
455
static ACPI_STATUS
456
AcpiExFieldDatumIo (
456
AcpiExFieldDatumIo (
457
    ACPI_OPERAND_OBJECT     *ObjDesc,
457
    ACPI_OPERAND_OBJECT     *ObjDesc,
458
    UINT32                  FieldDatumByteOffset,
458
    UINT32                  FieldDatumByteOffset,
459
    UINT64                  *Value,
459
    UINT64                  *Value,
460
    UINT32                  ReadWrite)
460
    UINT32                  ReadWrite)
461
{
461
{
462
    ACPI_STATUS             Status;
462
    ACPI_STATUS             Status;
463
    UINT64                  LocalValue;
463
    UINT64                  LocalValue;
464
 
464
 
465
 
465
 
466
    ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
466
    ACPI_FUNCTION_TRACE_U32 (ExFieldDatumIo, FieldDatumByteOffset);
467
 
467
 
468
 
468
 
469
    if (ReadWrite == ACPI_READ)
469
    if (ReadWrite == ACPI_READ)
470
    {
470
    {
471
        if (!Value)
471
        if (!Value)
472
        {
472
        {
473
            LocalValue = 0;
473
            LocalValue = 0;
474
 
474
 
475
            /* To support reads without saving return value */
475
            /* To support reads without saving return value */
476
            Value = &LocalValue;
476
            Value = &LocalValue;
477
        }
477
        }
478
 
478
 
479
        /* Clear the entire return buffer first, [Very Important!] */
479
        /* Clear the entire return buffer first, [Very Important!] */
480
 
480
 
481
        *Value = 0;
481
        *Value = 0;
482
    }
482
    }
483
 
483
 
484
    /*
484
    /*
485
     * The four types of fields are:
485
     * The four types of fields are:
486
     *
486
     *
487
     * BufferField - Read/write from/to a Buffer
487
     * BufferField - Read/write from/to a Buffer
488
     * RegionField - Read/write from/to a Operation Region.
488
     * RegionField - Read/write from/to a Operation Region.
489
     * BankField   - Write to a Bank Register, then read/write from/to an
489
     * BankField   - Write to a Bank Register, then read/write from/to an
490
     *               OperationRegion
490
     *               OperationRegion
491
     * IndexField  - Write to an Index Register, then read/write from/to a
491
     * IndexField  - Write to an Index Register, then read/write from/to a
492
     *               Data Register
492
     *               Data Register
493
     */
493
     */
494
    switch (ObjDesc->Common.Type)
494
    switch (ObjDesc->Common.Type)
495
    {
495
    {
496
    case ACPI_TYPE_BUFFER_FIELD:
496
    case ACPI_TYPE_BUFFER_FIELD:
497
        /*
497
        /*
498
         * If the BufferField arguments have not been previously evaluated,
498
         * If the BufferField arguments have not been previously evaluated,
499
         * evaluate them now and save the results.
499
         * evaluate them now and save the results.
500
         */
500
         */
501
        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
501
        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
502
        {
502
        {
503
            Status = AcpiDsGetBufferFieldArguments (ObjDesc);
503
            Status = AcpiDsGetBufferFieldArguments (ObjDesc);
504
            if (ACPI_FAILURE (Status))
504
            if (ACPI_FAILURE (Status))
505
            {
505
            {
506
                return_ACPI_STATUS (Status);
506
                return_ACPI_STATUS (Status);
507
            }
507
            }
508
        }
508
        }
509
 
509
 
510
        if (ReadWrite == ACPI_READ)
510
        if (ReadWrite == ACPI_READ)
511
        {
511
        {
512
            /*
512
            /*
513
             * Copy the data from the source buffer.
513
             * Copy the data from the source buffer.
514
             * Length is the field width in bytes.
514
             * Length is the field width in bytes.
515
             */
515
             */
516
            ACPI_MEMCPY (Value,
516
            ACPI_MEMCPY (Value,
517
                (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
517
                (ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
518
                    ObjDesc->BufferField.BaseByteOffset +
518
                    ObjDesc->BufferField.BaseByteOffset +
519
                    FieldDatumByteOffset,
519
                    FieldDatumByteOffset,
520
                ObjDesc->CommonField.AccessByteWidth);
520
                ObjDesc->CommonField.AccessByteWidth);
521
        }
521
        }
522
        else
522
        else
523
        {
523
        {
524
            /*
524
            /*
525
             * Copy the data to the target buffer.
525
             * Copy the data to the target buffer.
526
             * Length is the field width in bytes.
526
             * Length is the field width in bytes.
527
             */
527
             */
528
            ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
528
            ACPI_MEMCPY ((ObjDesc->BufferField.BufferObj)->Buffer.Pointer +
529
                ObjDesc->BufferField.BaseByteOffset +
529
                ObjDesc->BufferField.BaseByteOffset +
530
                FieldDatumByteOffset,
530
                FieldDatumByteOffset,
531
                Value, ObjDesc->CommonField.AccessByteWidth);
531
                Value, ObjDesc->CommonField.AccessByteWidth);
532
        }
532
        }
533
 
533
 
534
        Status = AE_OK;
534
        Status = AE_OK;
535
        break;
535
        break;
536
 
536
 
537
 
537
 
538
    case ACPI_TYPE_LOCAL_BANK_FIELD:
538
    case ACPI_TYPE_LOCAL_BANK_FIELD:
539
 
539
 
540
        /*
540
        /*
541
         * Ensure that the BankValue is not beyond the capacity of
541
         * Ensure that the BankValue is not beyond the capacity of
542
         * the register
542
         * the register
543
         */
543
         */
544
        if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
544
        if (AcpiExRegisterOverflow (ObjDesc->BankField.BankObj,
545
                (UINT64) ObjDesc->BankField.Value))
545
                (UINT64) ObjDesc->BankField.Value))
546
        {
546
        {
547
            return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
547
            return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
548
        }
548
        }
549
 
549
 
550
        /*
550
        /*
551
         * For BankFields, we must write the BankValue to the BankRegister
551
         * For BankFields, we must write the BankValue to the BankRegister
552
         * (itself a RegionField) before we can access the data.
552
         * (itself a RegionField) before we can access the data.
553
         */
553
         */
554
        Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
554
        Status = AcpiExInsertIntoField (ObjDesc->BankField.BankObj,
555
                    &ObjDesc->BankField.Value,
555
                    &ObjDesc->BankField.Value,
556
                    sizeof (ObjDesc->BankField.Value));
556
                    sizeof (ObjDesc->BankField.Value));
557
        if (ACPI_FAILURE (Status))
557
        if (ACPI_FAILURE (Status))
558
        {
558
        {
559
            return_ACPI_STATUS (Status);
559
            return_ACPI_STATUS (Status);
560
        }
560
        }
561
 
561
 
562
        /*
562
        /*
563
         * Now that the Bank has been selected, fall through to the
563
         * Now that the Bank has been selected, fall through to the
564
         * RegionField case and write the datum to the Operation Region
564
         * RegionField case and write the datum to the Operation Region
565
         */
565
         */
566
 
566
 
567
        /*lint -fallthrough */
567
        /*lint -fallthrough */
568
 
568
 
569
 
569
 
570
    case ACPI_TYPE_LOCAL_REGION_FIELD:
570
    case ACPI_TYPE_LOCAL_REGION_FIELD:
571
        /*
571
        /*
572
         * For simple RegionFields, we just directly access the owning
572
         * For simple RegionFields, we just directly access the owning
573
         * Operation Region.
573
         * Operation Region.
574
         */
574
         */
575
        Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
575
        Status = AcpiExAccessRegion (ObjDesc, FieldDatumByteOffset, Value,
576
                    ReadWrite);
576
                    ReadWrite);
577
        break;
577
        break;
578
 
578
 
579
 
579
 
580
    case ACPI_TYPE_LOCAL_INDEX_FIELD:
580
    case ACPI_TYPE_LOCAL_INDEX_FIELD:
581
 
581
 
582
 
582
 
583
        /*
583
        /*
584
         * Ensure that the IndexValue is not beyond the capacity of
584
         * Ensure that the IndexValue is not beyond the capacity of
585
         * the register
585
         * the register
586
         */
586
         */
587
        if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
587
        if (AcpiExRegisterOverflow (ObjDesc->IndexField.IndexObj,
588
                (UINT64) ObjDesc->IndexField.Value))
588
                (UINT64) ObjDesc->IndexField.Value))
589
        {
589
        {
590
            return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
590
            return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
591
        }
591
        }
592
 
592
 
593
        /* Write the index value to the IndexRegister (itself a RegionField) */
593
        /* Write the index value to the IndexRegister (itself a RegionField) */
594
 
594
 
595
        FieldDatumByteOffset += ObjDesc->IndexField.Value;
595
        FieldDatumByteOffset += ObjDesc->IndexField.Value;
596
 
596
 
597
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
597
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
598
            "Write to Index Register: Value %8.8X\n",
598
            "Write to Index Register: Value %8.8X\n",
599
            FieldDatumByteOffset));
599
            FieldDatumByteOffset));
600
 
600
 
601
        Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
601
        Status = AcpiExInsertIntoField (ObjDesc->IndexField.IndexObj,
602
                    &FieldDatumByteOffset,
602
                    &FieldDatumByteOffset,
603
                    sizeof (FieldDatumByteOffset));
603
                    sizeof (FieldDatumByteOffset));
604
        if (ACPI_FAILURE (Status))
604
        if (ACPI_FAILURE (Status))
605
        {
605
        {
606
            return_ACPI_STATUS (Status);
606
            return_ACPI_STATUS (Status);
607
        }
607
        }
608
 
608
 
609
        if (ReadWrite == ACPI_READ)
609
        if (ReadWrite == ACPI_READ)
610
        {
610
        {
611
            /* Read the datum from the DataRegister */
611
            /* Read the datum from the DataRegister */
612
 
612
 
613
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
613
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
614
                "Read from Data Register\n"));
614
                "Read from Data Register\n"));
615
 
615
 
616
            Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
616
            Status = AcpiExExtractFromField (ObjDesc->IndexField.DataObj,
617
                        Value, sizeof (UINT64));
617
                        Value, sizeof (UINT64));
618
        }
618
        }
619
        else
619
        else
620
        {
620
        {
621
            /* Write the datum to the DataRegister */
621
            /* Write the datum to the DataRegister */
622
 
622
 
623
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
623
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
624
                "Write to Data Register: Value %8.8X%8.8X\n",
624
                "Write to Data Register: Value %8.8X%8.8X\n",
625
                ACPI_FORMAT_UINT64 (*Value)));
625
                ACPI_FORMAT_UINT64 (*Value)));
626
 
626
 
627
            Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
627
            Status = AcpiExInsertIntoField (ObjDesc->IndexField.DataObj,
628
                        Value, sizeof (UINT64));
628
                        Value, sizeof (UINT64));
629
        }
629
        }
630
        break;
630
        break;
631
 
631
 
632
 
632
 
633
    default:
633
    default:
634
 
634
 
635
        ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
635
        ACPI_ERROR ((AE_INFO, "Wrong object type in field I/O %u",
636
            ObjDesc->Common.Type));
636
            ObjDesc->Common.Type));
637
        Status = AE_AML_INTERNAL;
637
        Status = AE_AML_INTERNAL;
638
        break;
638
        break;
639
    }
639
    }
640
 
640
 
641
    if (ACPI_SUCCESS (Status))
641
    if (ACPI_SUCCESS (Status))
642
    {
642
    {
643
        if (ReadWrite == ACPI_READ)
643
        if (ReadWrite == ACPI_READ)
644
        {
644
        {
645
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
645
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
646
                "Value Read %8.8X%8.8X, Width %u\n",
646
                "Value Read %8.8X%8.8X, Width %u\n",
647
                ACPI_FORMAT_UINT64 (*Value),
647
                ACPI_FORMAT_UINT64 (*Value),
648
                ObjDesc->CommonField.AccessByteWidth));
648
                ObjDesc->CommonField.AccessByteWidth));
649
        }
649
        }
650
        else
650
        else
651
        {
651
        {
652
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
652
            ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
653
                "Value Written %8.8X%8.8X, Width %u\n",
653
                "Value Written %8.8X%8.8X, Width %u\n",
654
                ACPI_FORMAT_UINT64 (*Value),
654
                ACPI_FORMAT_UINT64 (*Value),
655
                ObjDesc->CommonField.AccessByteWidth));
655
                ObjDesc->CommonField.AccessByteWidth));
656
        }
656
        }
657
    }
657
    }
658
 
658
 
659
    return_ACPI_STATUS (Status);
659
    return_ACPI_STATUS (Status);
660
}
660
}
661
 
661
 
662
 
662
 
663
/*******************************************************************************
663
/*******************************************************************************
664
 *
664
 *
665
 * FUNCTION:    AcpiExWriteWithUpdateRule
665
 * FUNCTION:    AcpiExWriteWithUpdateRule
666
 *
666
 *
667
 * PARAMETERS:  ObjDesc                 - Field to be written
667
 * PARAMETERS:  ObjDesc                 - Field to be written
668
 *              Mask                    - bitmask within field datum
668
 *              Mask                    - bitmask within field datum
669
 *              FieldValue              - Value to write
669
 *              FieldValue              - Value to write
670
 *              FieldDatumByteOffset    - Offset of datum within field
670
 *              FieldDatumByteOffset    - Offset of datum within field
671
 *
671
 *
672
 * RETURN:      Status
672
 * RETURN:      Status
673
 *
673
 *
674
 * DESCRIPTION: Apply the field update rule to a field write
674
 * DESCRIPTION: Apply the field update rule to a field write
675
 *
675
 *
676
 ******************************************************************************/
676
 ******************************************************************************/
677
 
677
 
678
ACPI_STATUS
678
ACPI_STATUS
679
AcpiExWriteWithUpdateRule (
679
AcpiExWriteWithUpdateRule (
680
    ACPI_OPERAND_OBJECT     *ObjDesc,
680
    ACPI_OPERAND_OBJECT     *ObjDesc,
681
    UINT64                  Mask,
681
    UINT64                  Mask,
682
    UINT64                  FieldValue,
682
    UINT64                  FieldValue,
683
    UINT32                  FieldDatumByteOffset)
683
    UINT32                  FieldDatumByteOffset)
684
{
684
{
685
    ACPI_STATUS             Status = AE_OK;
685
    ACPI_STATUS             Status = AE_OK;
686
    UINT64                  MergedValue;
686
    UINT64                  MergedValue;
687
    UINT64                  CurrentValue;
687
    UINT64                  CurrentValue;
688
 
688
 
689
 
689
 
690
    ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
690
    ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);
691
 
691
 
692
 
692
 
693
    /* Start with the new bits  */
693
    /* Start with the new bits  */
694
 
694
 
695
    MergedValue = FieldValue;
695
    MergedValue = FieldValue;
696
 
696
 
697
    /* If the mask is all ones, we don't need to worry about the update rule */
697
    /* If the mask is all ones, we don't need to worry about the update rule */
698
 
698
 
699
    if (Mask != ACPI_UINT64_MAX)
699
    if (Mask != ACPI_UINT64_MAX)
700
    {
700
    {
701
        /* Decode the update rule */
701
        /* Decode the update rule */
702
 
702
 
703
        switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
703
        switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
704
        {
704
        {
705
        case AML_FIELD_UPDATE_PRESERVE:
705
        case AML_FIELD_UPDATE_PRESERVE:
706
            /*
706
            /*
707
             * Check if update rule needs to be applied (not if mask is all
707
             * Check if update rule needs to be applied (not if mask is all
708
             * ones)  The left shift drops the bits we want to ignore.
708
             * ones)  The left shift drops the bits we want to ignore.
709
             */
709
             */
710
            if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
710
            if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
711
                           ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
711
                           ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
712
            {
712
            {
713
                /*
713
                /*
714
                 * Read the current contents of the byte/word/dword containing
714
                 * Read the current contents of the byte/word/dword containing
715
                 * the field, and merge with the new field value.
715
                 * the field, and merge with the new field value.
716
                 */
716
                 */
717
                Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
717
                Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
718
                            &CurrentValue, ACPI_READ);
718
                            &CurrentValue, ACPI_READ);
719
                if (ACPI_FAILURE (Status))
719
                if (ACPI_FAILURE (Status))
720
                {
720
                {
721
                    return_ACPI_STATUS (Status);
721
                    return_ACPI_STATUS (Status);
722
                }
722
                }
723
 
723
 
724
                MergedValue |= (CurrentValue & ~Mask);
724
                MergedValue |= (CurrentValue & ~Mask);
725
            }
725
            }
726
            break;
726
            break;
727
 
727
 
728
        case AML_FIELD_UPDATE_WRITE_AS_ONES:
728
        case AML_FIELD_UPDATE_WRITE_AS_ONES:
729
 
729
 
730
            /* Set positions outside the field to all ones */
730
            /* Set positions outside the field to all ones */
731
 
731
 
732
            MergedValue |= ~Mask;
732
            MergedValue |= ~Mask;
733
            break;
733
            break;
734
 
734
 
735
        case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
735
        case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
736
 
736
 
737
            /* Set positions outside the field to all zeros */
737
            /* Set positions outside the field to all zeros */
738
 
738
 
739
            MergedValue &= Mask;
739
            MergedValue &= Mask;
740
            break;
740
            break;
741
 
741
 
742
        default:
742
        default:
743
 
743
 
744
            ACPI_ERROR ((AE_INFO,
744
            ACPI_ERROR ((AE_INFO,
745
                "Unknown UpdateRule value: 0x%X",
745
                "Unknown UpdateRule value: 0x%X",
746
                (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
746
                (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)));
747
            return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
747
            return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
748
        }
748
        }
749
    }
749
    }
750
 
750
 
751
    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
751
    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
752
        "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
752
        "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
753
        ACPI_FORMAT_UINT64 (Mask),
753
        ACPI_FORMAT_UINT64 (Mask),
754
        FieldDatumByteOffset,
754
        FieldDatumByteOffset,
755
        ObjDesc->CommonField.AccessByteWidth,
755
        ObjDesc->CommonField.AccessByteWidth,
756
        ACPI_FORMAT_UINT64 (FieldValue),
756
        ACPI_FORMAT_UINT64 (FieldValue),
757
        ACPI_FORMAT_UINT64 (MergedValue)));
757
        ACPI_FORMAT_UINT64 (MergedValue)));
758
 
758
 
759
    /* Write the merged value */
759
    /* Write the merged value */
760
 
760
 
761
    Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
761
    Status = AcpiExFieldDatumIo (ObjDesc, FieldDatumByteOffset,
762
                &MergedValue, ACPI_WRITE);
762
                &MergedValue, ACPI_WRITE);
763
 
763
 
764
    return_ACPI_STATUS (Status);
764
    return_ACPI_STATUS (Status);
765
}
765
}
766
 
766
 
767
 
767
 
768
/*******************************************************************************
768
/*******************************************************************************
769
 *
769
 *
770
 * FUNCTION:    AcpiExExtractFromField
770
 * FUNCTION:    AcpiExExtractFromField
771
 *
771
 *
772
 * PARAMETERS:  ObjDesc             - Field to be read
772
 * PARAMETERS:  ObjDesc             - Field to be read
773
 *              Buffer              - Where to store the field data
773
 *              Buffer              - Where to store the field data
774
 *              BufferLength        - Length of Buffer
774
 *              BufferLength        - Length of Buffer
775
 *
775
 *
776
 * RETURN:      Status
776
 * RETURN:      Status
777
 *
777
 *
778
 * DESCRIPTION: Retrieve the current value of the given field
778
 * DESCRIPTION: Retrieve the current value of the given field
779
 *
779
 *
780
 ******************************************************************************/
780
 ******************************************************************************/
781
 
781
 
782
ACPI_STATUS
782
ACPI_STATUS
783
AcpiExExtractFromField (
783
AcpiExExtractFromField (
784
    ACPI_OPERAND_OBJECT     *ObjDesc,
784
    ACPI_OPERAND_OBJECT     *ObjDesc,
785
    void                    *Buffer,
785
    void                    *Buffer,
786
    UINT32                  BufferLength)
786
    UINT32                  BufferLength)
787
{
787
{
788
    ACPI_STATUS             Status;
788
    ACPI_STATUS             Status;
789
    UINT64                  RawDatum;
789
    UINT64                  RawDatum;
790
    UINT64                  MergedDatum;
790
    UINT64                  MergedDatum;
791
    UINT32                  FieldOffset = 0;
791
    UINT32                  FieldOffset = 0;
792
    UINT32                  BufferOffset = 0;
792
    UINT32                  BufferOffset = 0;
793
    UINT32                  BufferTailBits;
793
    UINT32                  BufferTailBits;
794
    UINT32                  DatumCount;
794
    UINT32                  DatumCount;
795
    UINT32                  FieldDatumCount;
795
    UINT32                  FieldDatumCount;
796
    UINT32                  AccessBitWidth;
796
    UINT32                  AccessBitWidth;
797
    UINT32                  i;
797
    UINT32                  i;
798
 
798
 
799
 
799
 
800
    ACPI_FUNCTION_TRACE (ExExtractFromField);
800
    ACPI_FUNCTION_TRACE (ExExtractFromField);
801
 
801
 
802
 
802
 
803
    /* Validate target buffer and clear it */
803
    /* Validate target buffer and clear it */
804
 
804
 
805
    if (BufferLength <
805
    if (BufferLength <
806
        ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
806
        ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
807
    {
807
    {
808
        ACPI_ERROR ((AE_INFO,
808
        ACPI_ERROR ((AE_INFO,
809
            "Field size %u (bits) is too large for buffer (%u)",
809
            "Field size %u (bits) is too large for buffer (%u)",
810
            ObjDesc->CommonField.BitLength, BufferLength));
810
            ObjDesc->CommonField.BitLength, BufferLength));
811
 
811
 
812
        return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
812
        return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
813
    }
813
    }
814
 
814
 
815
    ACPI_MEMSET (Buffer, 0, BufferLength);
815
    ACPI_MEMSET (Buffer, 0, BufferLength);
816
    AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
816
    AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
817
 
817
 
818
    /* Handle the simple case here */
818
    /* Handle the simple case here */
819
 
819
 
820
    if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
820
    if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
821
        (ObjDesc->CommonField.BitLength == AccessBitWidth))
821
        (ObjDesc->CommonField.BitLength == AccessBitWidth))
822
    {
822
    {
823
        Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
823
        Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
824
        return_ACPI_STATUS (Status);
824
        return_ACPI_STATUS (Status);
825
    }
825
    }
826
 
826
 
827
/* TBD: Move to common setup code */
827
/* TBD: Move to common setup code */
828
 
828
 
829
    /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
829
    /* Field algorithm is limited to sizeof(UINT64), truncate if needed */
830
 
830
 
831
    if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
831
    if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
832
    {
832
    {
833
        ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
833
        ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
834
        AccessBitWidth = sizeof (UINT64) * 8;
834
        AccessBitWidth = sizeof (UINT64) * 8;
835
    }
835
    }
836
 
836
 
837
    /* Compute the number of datums (access width data items) */
837
    /* Compute the number of datums (access width data items) */
838
 
838
 
839
    DatumCount = ACPI_ROUND_UP_TO (
839
    DatumCount = ACPI_ROUND_UP_TO (
840
        ObjDesc->CommonField.BitLength, AccessBitWidth);
840
        ObjDesc->CommonField.BitLength, AccessBitWidth);
841
 
841
 
842
    FieldDatumCount = ACPI_ROUND_UP_TO (
842
    FieldDatumCount = ACPI_ROUND_UP_TO (
843
        ObjDesc->CommonField.BitLength +
843
        ObjDesc->CommonField.BitLength +
844
        ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
844
        ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);
845
 
845
 
846
    /* Priming read from the field */
846
    /* Priming read from the field */
847
 
847
 
848
    Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
848
    Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
849
    if (ACPI_FAILURE (Status))
849
    if (ACPI_FAILURE (Status))
850
    {
850
    {
851
        return_ACPI_STATUS (Status);
851
        return_ACPI_STATUS (Status);
852
    }
852
    }
853
    MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
853
    MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
854
 
854
 
855
    /* Read the rest of the field */
855
    /* Read the rest of the field */
856
 
856
 
857
    for (i = 1; i < FieldDatumCount; i++)
857
    for (i = 1; i < FieldDatumCount; i++)
858
    {
858
    {
859
        /* Get next input datum from the field */
859
        /* Get next input datum from the field */
860
 
860
 
861
        FieldOffset += ObjDesc->CommonField.AccessByteWidth;
861
        FieldOffset += ObjDesc->CommonField.AccessByteWidth;
862
        Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
862
        Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset,
863
                    &RawDatum, ACPI_READ);
863
                    &RawDatum, ACPI_READ);
864
        if (ACPI_FAILURE (Status))
864
        if (ACPI_FAILURE (Status))
865
        {
865
        {
866
            return_ACPI_STATUS (Status);
866
            return_ACPI_STATUS (Status);
867
        }
867
        }
868
 
868
 
869
        /*
869
        /*
870
         * Merge with previous datum if necessary.
870
         * Merge with previous datum if necessary.
871
         *
871
         *
872
         * Note: Before the shift, check if the shift value will be larger than
872
         * Note: Before the shift, check if the shift value will be larger than
873
         * the integer size. If so, there is no need to perform the operation.
873
         * the integer size. If so, there is no need to perform the operation.
874
         * This avoids the differences in behavior between different compilers
874
         * This avoids the differences in behavior between different compilers
875
         * concerning shift values larger than the target data width.
875
         * concerning shift values larger than the target data width.
876
         */
876
         */
877
        if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
877
        if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
878
            ACPI_INTEGER_BIT_SIZE)
878
            ACPI_INTEGER_BIT_SIZE)
879
        {
879
        {
880
            MergedDatum |= RawDatum <<
880
            MergedDatum |= RawDatum <<
881
                (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
881
                (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
882
        }
882
        }
883
 
883
 
884
        if (i == DatumCount)
884
        if (i == DatumCount)
885
        {
885
        {
886
            break;
886
            break;
887
        }
887
        }
888
 
888
 
889
        /* Write merged datum to target buffer */
889
        /* Write merged datum to target buffer */
890
 
890
 
891
        ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
891
        ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
892
            ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
892
            ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
893
                BufferLength - BufferOffset));
893
                BufferLength - BufferOffset));
894
 
894
 
895
        BufferOffset += ObjDesc->CommonField.AccessByteWidth;
895
        BufferOffset += ObjDesc->CommonField.AccessByteWidth;
896
        MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
896
        MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
897
    }
897
    }
898
 
898
 
899
    /* Mask off any extra bits in the last datum */
899
    /* Mask off any extra bits in the last datum */
900
 
900
 
901
    BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
901
    BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
902
    if (BufferTailBits)
902
    if (BufferTailBits)
903
    {
903
    {
904
        MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
904
        MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
905
    }
905
    }
906
 
906
 
907
    /* Write the last datum to the buffer */
907
    /* Write the last datum to the buffer */
908
 
908
 
909
    ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
909
    ACPI_MEMCPY (((char *) Buffer) + BufferOffset, &MergedDatum,
910
        ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
910
        ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
911
            BufferLength - BufferOffset));
911
            BufferLength - BufferOffset));
912
 
912
 
913
    return_ACPI_STATUS (AE_OK);
913
    return_ACPI_STATUS (AE_OK);
914
}
914
}
915
 
915
 
916
 
916
 
917
/*******************************************************************************
917
/*******************************************************************************
918
 *
918
 *
919
 * FUNCTION:    AcpiExInsertIntoField
919
 * FUNCTION:    AcpiExInsertIntoField
920
 *
920
 *
921
 * PARAMETERS:  ObjDesc             - Field to be written
921
 * PARAMETERS:  ObjDesc             - Field to be written
922
 *              Buffer              - Data to be written
922
 *              Buffer              - Data to be written
923
 *              BufferLength        - Length of Buffer
923
 *              BufferLength        - Length of Buffer
924
 *
924
 *
925
 * RETURN:      Status
925
 * RETURN:      Status
926
 *
926
 *
927
 * DESCRIPTION: Store the Buffer contents into the given field
927
 * DESCRIPTION: Store the Buffer contents into the given field
928
 *
928
 *
929
 ******************************************************************************/
929
 ******************************************************************************/
930
 
930
 
931
ACPI_STATUS
931
ACPI_STATUS
932
AcpiExInsertIntoField (
932
AcpiExInsertIntoField (
933
    ACPI_OPERAND_OBJECT     *ObjDesc,
933
    ACPI_OPERAND_OBJECT     *ObjDesc,
934
    void                    *Buffer,
934
    void                    *Buffer,
935
    UINT32                  BufferLength)
935
    UINT32                  BufferLength)
936
{
936
{
937
    void                    *NewBuffer;
937
    void                    *NewBuffer;
938
    ACPI_STATUS             Status;
938
    ACPI_STATUS             Status;
939
    UINT64                  Mask;
939
    UINT64                  Mask;
940
    UINT64                  WidthMask;
940
    UINT64                  WidthMask;
941
    UINT64                  MergedDatum;
941
    UINT64                  MergedDatum;
942
    UINT64                  RawDatum = 0;
942
    UINT64                  RawDatum = 0;
943
    UINT32                  FieldOffset = 0;
943
    UINT32                  FieldOffset = 0;
944
    UINT32                  BufferOffset = 0;
944
    UINT32                  BufferOffset = 0;
945
    UINT32                  BufferTailBits;
945
    UINT32                  BufferTailBits;
946
    UINT32                  DatumCount;
946
    UINT32                  DatumCount;
947
    UINT32                  FieldDatumCount;
947
    UINT32                  FieldDatumCount;
948
    UINT32                  AccessBitWidth;
948
    UINT32                  AccessBitWidth;
949
    UINT32                  RequiredLength;
949
    UINT32                  RequiredLength;
950
    UINT32                  i;
950
    UINT32                  i;
951
 
951
 
952
 
952
 
953
    ACPI_FUNCTION_TRACE (ExInsertIntoField);
953
    ACPI_FUNCTION_TRACE (ExInsertIntoField);
954
 
954
 
955
 
955
 
956
    /* Validate input buffer */
956
    /* Validate input buffer */
957
 
957
 
958
    NewBuffer = NULL;
958
    NewBuffer = NULL;
959
    RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
959
    RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
960
                        ObjDesc->CommonField.BitLength);
960
                        ObjDesc->CommonField.BitLength);
961
    /*
961
    /*
962
     * We must have a buffer that is at least as long as the field
962
     * We must have a buffer that is at least as long as the field
963
     * we are writing to.  This is because individual fields are
963
     * we are writing to.  This is because individual fields are
964
     * indivisible and partial writes are not supported -- as per
964
     * indivisible and partial writes are not supported -- as per
965
     * the ACPI specification.
965
     * the ACPI specification.
966
     */
966
     */
967
    if (BufferLength < RequiredLength)
967
    if (BufferLength < RequiredLength)
968
    {
968
    {
969
        /* We need to create a new buffer */
969
        /* We need to create a new buffer */
970
 
970
 
971
        NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
971
        NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
972
        if (!NewBuffer)
972
        if (!NewBuffer)
973
        {
973
        {
974
            return_ACPI_STATUS (AE_NO_MEMORY);
974
            return_ACPI_STATUS (AE_NO_MEMORY);
975
        }
975
        }
976
 
976
 
977
        /*
977
        /*
978
         * Copy the original data to the new buffer, starting
978
         * Copy the original data to the new buffer, starting
979
         * at Byte zero.  All unused (upper) bytes of the
979
         * at Byte zero.  All unused (upper) bytes of the
980
         * buffer will be 0.
980
         * buffer will be 0.
981
         */
981
         */
982
        ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength);
982
        ACPI_MEMCPY ((char *) NewBuffer, (char *) Buffer, BufferLength);
983
        Buffer = NewBuffer;
983
        Buffer = NewBuffer;
984
        BufferLength = RequiredLength;
984
        BufferLength = RequiredLength;
985
    }
985
    }
986
 
986
 
987
/* TBD: Move to common setup code */
987
/* TBD: Move to common setup code */
988
 
988
 
989
    /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
989
    /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
990
    if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
990
    if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
991
    {
991
    {
992
        ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
992
        ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
993
    }
993
    }
994
 
994
 
995
    AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
995
    AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);
996
 
996
 
997
    /*
997
    /*
998
     * Create the bitmasks used for bit insertion.
998
     * Create the bitmasks used for bit insertion.
999
     * Note: This if/else is used to bypass compiler differences with the
999
     * Note: This if/else is used to bypass compiler differences with the
1000
     * shift operator
1000
     * shift operator
1001
     */
1001
     */
1002
    if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE)
1002
    if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE)
1003
    {
1003
    {
1004
        WidthMask = ACPI_UINT64_MAX;
1004
        WidthMask = ACPI_UINT64_MAX;
1005
    }
1005
    }
1006
    else
1006
    else
1007
    {
1007
    {
1008
        WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth);
1008
        WidthMask = ACPI_MASK_BITS_ABOVE (AccessBitWidth);
1009
    }
1009
    }
1010
 
1010
 
1011
    Mask = WidthMask &
1011
    Mask = WidthMask &
1012
        ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
1012
        ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);
1013
 
1013
 
1014
    /* Compute the number of datums (access width data items) */
1014
    /* Compute the number of datums (access width data items) */
1015
 
1015
 
1016
    DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
1016
    DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
1017
        AccessBitWidth);
1017
        AccessBitWidth);
1018
 
1018
 
1019
    FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
1019
    FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
1020
        ObjDesc->CommonField.StartFieldBitOffset,
1020
        ObjDesc->CommonField.StartFieldBitOffset,
1021
        AccessBitWidth);
1021
        AccessBitWidth);
1022
 
1022
 
1023
    /* Get initial Datum from the input buffer */
1023
    /* Get initial Datum from the input buffer */
1024
 
1024
 
1025
    ACPI_MEMCPY (&RawDatum, Buffer,
1025
    ACPI_MEMCPY (&RawDatum, Buffer,
1026
        ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1026
        ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1027
            BufferLength - BufferOffset));
1027
            BufferLength - BufferOffset));
1028
 
1028
 
1029
    MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1029
    MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1030
 
1030
 
1031
    /* Write the entire field */
1031
    /* Write the entire field */
1032
 
1032
 
1033
    for (i = 1; i < FieldDatumCount; i++)
1033
    for (i = 1; i < FieldDatumCount; i++)
1034
    {
1034
    {
1035
        /* Write merged datum to the target field */
1035
        /* Write merged datum to the target field */
1036
 
1036
 
1037
        MergedDatum &= Mask;
1037
        MergedDatum &= Mask;
1038
        Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask,
1038
        Status = AcpiExWriteWithUpdateRule (ObjDesc, Mask,
1039
                    MergedDatum, FieldOffset);
1039
                    MergedDatum, FieldOffset);
1040
        if (ACPI_FAILURE (Status))
1040
        if (ACPI_FAILURE (Status))
1041
        {
1041
        {
1042
            goto Exit;
1042
            goto Exit;
1043
        }
1043
        }
1044
 
1044
 
1045
        FieldOffset += ObjDesc->CommonField.AccessByteWidth;
1045
        FieldOffset += ObjDesc->CommonField.AccessByteWidth;
1046
 
1046
 
1047
        /*
1047
        /*
1048
         * Start new output datum by merging with previous input datum
1048
         * Start new output datum by merging with previous input datum
1049
         * if necessary.
1049
         * if necessary.
1050
         *
1050
         *
1051
         * Note: Before the shift, check if the shift value will be larger than
1051
         * Note: Before the shift, check if the shift value will be larger than
1052
         * the integer size. If so, there is no need to perform the operation.
1052
         * the integer size. If so, there is no need to perform the operation.
1053
         * This avoids the differences in behavior between different compilers
1053
         * This avoids the differences in behavior between different compilers
1054
         * concerning shift values larger than the target data width.
1054
         * concerning shift values larger than the target data width.
1055
         */
1055
         */
1056
        if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
1056
        if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
1057
            ACPI_INTEGER_BIT_SIZE)
1057
            ACPI_INTEGER_BIT_SIZE)
1058
        {
1058
        {
1059
            MergedDatum = RawDatum >>
1059
            MergedDatum = RawDatum >>
1060
                (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
1060
                (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
1061
        }
1061
        }
1062
        else
1062
        else
1063
        {
1063
        {
1064
            MergedDatum = 0;
1064
            MergedDatum = 0;
1065
        }
1065
        }
1066
 
1066
 
1067
        Mask = WidthMask;
1067
        Mask = WidthMask;
1068
 
1068
 
1069
        if (i == DatumCount)
1069
        if (i == DatumCount)
1070
        {
1070
        {
1071
            break;
1071
            break;
1072
        }
1072
        }
1073
 
1073
 
1074
        /* Get the next input datum from the buffer */
1074
        /* Get the next input datum from the buffer */
1075
 
1075
 
1076
        BufferOffset += ObjDesc->CommonField.AccessByteWidth;
1076
        BufferOffset += ObjDesc->CommonField.AccessByteWidth;
1077
        ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset,
1077
        ACPI_MEMCPY (&RawDatum, ((char *) Buffer) + BufferOffset,
1078
            ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1078
            ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
1079
                 BufferLength - BufferOffset));
1079
                 BufferLength - BufferOffset));
1080
 
1080
 
1081
        MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1081
        MergedDatum |= RawDatum << ObjDesc->CommonField.StartFieldBitOffset;
1082
    }
1082
    }
1083
 
1083
 
1084
    /* Mask off any extra bits in the last datum */
1084
    /* Mask off any extra bits in the last datum */
1085
 
1085
 
1086
    BufferTailBits = (ObjDesc->CommonField.BitLength +
1086
    BufferTailBits = (ObjDesc->CommonField.BitLength +
1087
        ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
1087
        ObjDesc->CommonField.StartFieldBitOffset) % AccessBitWidth;
1088
    if (BufferTailBits)
1088
    if (BufferTailBits)
1089
    {
1089
    {
1090
        Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1090
        Mask &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
1091
    }
1091
    }
1092
 
1092
 
1093
    /* Write the last datum to the field */
1093
    /* Write the last datum to the field */
1094
 
1094
 
1095
    MergedDatum &= Mask;
1095
    MergedDatum &= Mask;
1096
    Status = AcpiExWriteWithUpdateRule (ObjDesc,
1096
    Status = AcpiExWriteWithUpdateRule (ObjDesc,
1097
                Mask, MergedDatum, FieldOffset);
1097
                Mask, MergedDatum, FieldOffset);
1098
 
1098
 
1099
Exit:
1099
Exit:
1100
    /* Free temporary buffer if we used one */
1100
    /* Free temporary buffer if we used one */
1101
 
1101
 
1102
    if (NewBuffer)
1102
    if (NewBuffer)
1103
    {
1103
    {
1104
        ACPI_FREE (NewBuffer);
1104
        ACPI_FREE (NewBuffer);
1105
    }
1105
    }
1106
    return_ACPI_STATUS (Status);
1106
    return_ACPI_STATUS (Status);
1107
}
1107
}
1108
>
1108
>
1109
>
1109
>
1110
>
1110
>
1111
>
1111
>
1112
>
1112
>
1113
>
1113
>