OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [executer/] [exfield.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/******************************************************************************
2
 *
3
 * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2007, R. Byron Moore
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
#include <acpi/acpi.h>
45
#include <acpi/acdispat.h>
46
#include <acpi/acinterp.h>
47
 
48
#define _COMPONENT          ACPI_EXECUTER
49
ACPI_MODULE_NAME("exfield")
50
 
51
/*******************************************************************************
52
 *
53
 * FUNCTION:    acpi_ex_read_data_from_field
54
 *
55
 * PARAMETERS:  walk_state          - Current execution state
56
 *              obj_desc            - The named field
57
 *              ret_buffer_desc     - Where the return data object is stored
58
 *
59
 * RETURN:      Status
60
 *
61
 * DESCRIPTION: Read from a named field.  Returns either an Integer or a
62
 *              Buffer, depending on the size of the field.
63
 *
64
 ******************************************************************************/
65
acpi_status
66
acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
67
                             union acpi_operand_object *obj_desc,
68
                             union acpi_operand_object **ret_buffer_desc)
69
{
70
        acpi_status status;
71
        union acpi_operand_object *buffer_desc;
72
        acpi_size length;
73
        void *buffer;
74
        u8 locked;
75
 
76
        ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
77
 
78
        /* Parameter validation */
79
 
80
        if (!obj_desc) {
81
                return_ACPI_STATUS(AE_AML_NO_OPERAND);
82
        }
83
        if (!ret_buffer_desc) {
84
                return_ACPI_STATUS(AE_BAD_PARAMETER);
85
        }
86
 
87
        if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
88
                /*
89
                 * If the buffer_field arguments have not been previously evaluated,
90
                 * evaluate them now and save the results.
91
                 */
92
                if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
93
                        status = acpi_ds_get_buffer_field_arguments(obj_desc);
94
                        if (ACPI_FAILURE(status)) {
95
                                return_ACPI_STATUS(status);
96
                        }
97
                }
98
        } else
99
            if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD)
100
                && (obj_desc->field.region_obj->region.space_id ==
101
                    ACPI_ADR_SPACE_SMBUS)) {
102
                /*
103
                 * This is an SMBus read.  We must create a buffer to hold the data
104
                 * and directly access the region handler.
105
                 */
106
                buffer_desc =
107
                    acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
108
                if (!buffer_desc) {
109
                        return_ACPI_STATUS(AE_NO_MEMORY);
110
                }
111
 
112
                /* Lock entire transaction if requested */
113
 
114
                locked =
115
                    acpi_ex_acquire_global_lock(obj_desc->common_field.
116
                                                field_flags);
117
 
118
                /*
119
                 * Perform the read.
120
                 * Note: Smbus protocol value is passed in upper 16-bits of Function
121
                 */
122
                status = acpi_ex_access_region(obj_desc, 0,
123
                                               ACPI_CAST_PTR(acpi_integer,
124
                                                             buffer_desc->
125
                                                             buffer.pointer),
126
                                               ACPI_READ | (obj_desc->field.
127
                                                            attribute << 16));
128
                acpi_ex_release_global_lock(locked);
129
                goto exit;
130
        }
131
 
132
        /*
133
         * Allocate a buffer for the contents of the field.
134
         *
135
         * If the field is larger than the size of an acpi_integer, create
136
         * a BUFFER to hold it.  Otherwise, use an INTEGER.  This allows
137
         * the use of arithmetic operators on the returned value if the
138
         * field size is equal or smaller than an Integer.
139
         *
140
         * Note: Field.length is in bits.
141
         */
142
        length =
143
            (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
144
        if (length > acpi_gbl_integer_byte_width) {
145
 
146
                /* Field is too large for an Integer, create a Buffer instead */
147
 
148
                buffer_desc = acpi_ut_create_buffer_object(length);
149
                if (!buffer_desc) {
150
                        return_ACPI_STATUS(AE_NO_MEMORY);
151
                }
152
                buffer = buffer_desc->buffer.pointer;
153
        } else {
154
                /* Field will fit within an Integer (normal case) */
155
 
156
                buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
157
                if (!buffer_desc) {
158
                        return_ACPI_STATUS(AE_NO_MEMORY);
159
                }
160
 
161
                length = acpi_gbl_integer_byte_width;
162
                buffer_desc->integer.value = 0;
163
                buffer = &buffer_desc->integer.value;
164
        }
165
 
166
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
167
                          "FieldRead [TO]:   Obj %p, Type %X, Buf %p, ByteLen %X\n",
168
                          obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer,
169
                          (u32) length));
170
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
171
                          "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
172
                          obj_desc->common_field.bit_length,
173
                          obj_desc->common_field.start_field_bit_offset,
174
                          obj_desc->common_field.base_byte_offset));
175
 
176
        /* Lock entire transaction if requested */
177
 
178
        locked =
179
            acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
180
 
181
        /* Read from the field */
182
 
183
        status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
184
        acpi_ex_release_global_lock(locked);
185
 
186
      exit:
187
        if (ACPI_FAILURE(status)) {
188
                acpi_ut_remove_reference(buffer_desc);
189
        } else {
190
                *ret_buffer_desc = buffer_desc;
191
        }
192
 
193
        return_ACPI_STATUS(status);
194
}
195
 
196
/*******************************************************************************
197
 *
198
 * FUNCTION:    acpi_ex_write_data_to_field
199
 *
200
 * PARAMETERS:  source_desc         - Contains data to write
201
 *              obj_desc            - The named field
202
 *              result_desc         - Where the return value is returned, if any
203
 *
204
 * RETURN:      Status
205
 *
206
 * DESCRIPTION: Write to a named field
207
 *
208
 ******************************************************************************/
209
 
210
acpi_status
211
acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
212
                            union acpi_operand_object *obj_desc,
213
                            union acpi_operand_object **result_desc)
214
{
215
        acpi_status status;
216
        u32 length;
217
        u32 required_length;
218
        void *buffer;
219
        void *new_buffer;
220
        u8 locked;
221
        union acpi_operand_object *buffer_desc;
222
 
223
        ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
224
 
225
        /* Parameter validation */
226
 
227
        if (!source_desc || !obj_desc) {
228
                return_ACPI_STATUS(AE_AML_NO_OPERAND);
229
        }
230
 
231
        if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
232
                /*
233
                 * If the buffer_field arguments have not been previously evaluated,
234
                 * evaluate them now and save the results.
235
                 */
236
                if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
237
                        status = acpi_ds_get_buffer_field_arguments(obj_desc);
238
                        if (ACPI_FAILURE(status)) {
239
                                return_ACPI_STATUS(status);
240
                        }
241
                }
242
        } else
243
            if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD)
244
                && (obj_desc->field.region_obj->region.space_id ==
245
                    ACPI_ADR_SPACE_SMBUS)) {
246
                /*
247
                 * This is an SMBus write.  We will bypass the entire field mechanism
248
                 * and handoff the buffer directly to the handler.
249
                 *
250
                 * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
251
                 */
252
                if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) {
253
                        ACPI_ERROR((AE_INFO,
254
                                    "SMBus write requires Buffer, found type %s",
255
                                    acpi_ut_get_object_type_name(source_desc)));
256
 
257
                        return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
258
                }
259
 
260
                if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
261
                        ACPI_ERROR((AE_INFO,
262
                                    "SMBus write requires Buffer of length %X, found length %X",
263
                                    ACPI_SMBUS_BUFFER_SIZE,
264
                                    source_desc->buffer.length));
265
 
266
                        return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
267
                }
268
 
269
                buffer_desc =
270
                    acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
271
                if (!buffer_desc) {
272
                        return_ACPI_STATUS(AE_NO_MEMORY);
273
                }
274
 
275
                buffer = buffer_desc->buffer.pointer;
276
                ACPI_MEMCPY(buffer, source_desc->buffer.pointer,
277
                            ACPI_SMBUS_BUFFER_SIZE);
278
 
279
                /* Lock entire transaction if requested */
280
 
281
                locked =
282
                    acpi_ex_acquire_global_lock(obj_desc->common_field.
283
                                                field_flags);
284
 
285
                /*
286
                 * Perform the write (returns status and perhaps data in the
287
                 * same buffer)
288
                 * Note: SMBus protocol type is passed in upper 16-bits of Function.
289
                 */
290
                status = acpi_ex_access_region(obj_desc, 0,
291
                                               (acpi_integer *) buffer,
292
                                               ACPI_WRITE | (obj_desc->field.
293
                                                             attribute << 16));
294
                acpi_ex_release_global_lock(locked);
295
 
296
                *result_desc = buffer_desc;
297
                return_ACPI_STATUS(status);
298
        }
299
 
300
        /* Get a pointer to the data to be written */
301
 
302
        switch (ACPI_GET_OBJECT_TYPE(source_desc)) {
303
        case ACPI_TYPE_INTEGER:
304
                buffer = &source_desc->integer.value;
305
                length = sizeof(source_desc->integer.value);
306
                break;
307
 
308
        case ACPI_TYPE_BUFFER:
309
                buffer = source_desc->buffer.pointer;
310
                length = source_desc->buffer.length;
311
                break;
312
 
313
        case ACPI_TYPE_STRING:
314
                buffer = source_desc->string.pointer;
315
                length = source_desc->string.length;
316
                break;
317
 
318
        default:
319
                return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
320
        }
321
 
322
        /*
323
         * We must have a buffer that is at least as long as the field
324
         * we are writing to.  This is because individual fields are
325
         * indivisible and partial writes are not supported -- as per
326
         * the ACPI specification.
327
         */
328
        new_buffer = NULL;
329
        required_length =
330
            ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
331
 
332
        if (length < required_length) {
333
 
334
                /* We need to create a new buffer */
335
 
336
                new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
337
                if (!new_buffer) {
338
                        return_ACPI_STATUS(AE_NO_MEMORY);
339
                }
340
 
341
                /*
342
                 * Copy the original data to the new buffer, starting
343
                 * at Byte zero.  All unused (upper) bytes of the
344
                 * buffer will be 0.
345
                 */
346
                ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length);
347
                buffer = new_buffer;
348
                length = required_length;
349
        }
350
 
351
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
352
                          "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
353
                          source_desc,
354
                          acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE
355
                                                (source_desc)),
356
                          ACPI_GET_OBJECT_TYPE(source_desc), buffer, length));
357
 
358
        ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
359
                          "FieldWrite [TO]:   Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
360
                          obj_desc,
361
                          acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)),
362
                          ACPI_GET_OBJECT_TYPE(obj_desc),
363
                          obj_desc->common_field.bit_length,
364
                          obj_desc->common_field.start_field_bit_offset,
365
                          obj_desc->common_field.base_byte_offset));
366
 
367
        /* Lock entire transaction if requested */
368
 
369
        locked =
370
            acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
371
 
372
        /* Write to the field */
373
 
374
        status = acpi_ex_insert_into_field(obj_desc, buffer, length);
375
        acpi_ex_release_global_lock(locked);
376
 
377
        /* Free temporary buffer if we used one */
378
 
379
        if (new_buffer) {
380
                ACPI_FREE(new_buffer);
381
        }
382
 
383
        return_ACPI_STATUS(status);
384
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.