1 /******************************************************************************
3 * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #include <acpi/acpi.h>
50 #define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME("exfield")
53 /* Local prototypes */
55 acpi_ex_get_serial_access_length(u32 accessor_type
, u32 access_length
);
57 /*******************************************************************************
59 * FUNCTION: acpi_ex_get_serial_access_length
61 * PARAMETERS: accessor_type - The type of the protocol indicated by region
62 * field access attributes
63 * access_length - The access length of the region field
65 * RETURN: Decoded access length
67 * DESCRIPTION: This routine returns the length of the generic_serial_bus
70 ******************************************************************************/
73 acpi_ex_get_serial_access_length(u32 accessor_type
, u32 access_length
)
77 switch (accessor_type
) {
78 case AML_FIELD_ATTRIB_QUICK
:
83 case AML_FIELD_ATTRIB_SEND_RCV
:
84 case AML_FIELD_ATTRIB_BYTE
:
89 case AML_FIELD_ATTRIB_WORD
:
90 case AML_FIELD_ATTRIB_WORD_CALL
:
95 case AML_FIELD_ATTRIB_MULTIBYTE
:
96 case AML_FIELD_ATTRIB_RAW_BYTES
:
97 case AML_FIELD_ATTRIB_RAW_PROCESS
:
99 length
= access_length
;
102 case AML_FIELD_ATTRIB_BLOCK
:
103 case AML_FIELD_ATTRIB_BLOCK_CALL
:
106 length
= ACPI_GSBUS_BUFFER_SIZE
- 2;
113 /*******************************************************************************
115 * FUNCTION: acpi_ex_read_data_from_field
117 * PARAMETERS: walk_state - Current execution state
118 * obj_desc - The named field
119 * ret_buffer_desc - Where the return data object is stored
123 * DESCRIPTION: Read from a named field. Returns either an Integer or a
124 * Buffer, depending on the size of the field.
126 ******************************************************************************/
129 acpi_ex_read_data_from_field(struct acpi_walk_state
* walk_state
,
130 union acpi_operand_object
*obj_desc
,
131 union acpi_operand_object
**ret_buffer_desc
)
134 union acpi_operand_object
*buffer_desc
;
140 ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field
, obj_desc
);
142 /* Parameter validation */
145 return_ACPI_STATUS(AE_AML_NO_OPERAND
);
147 if (!ret_buffer_desc
) {
148 return_ACPI_STATUS(AE_BAD_PARAMETER
);
151 if (obj_desc
->common
.type
== ACPI_TYPE_BUFFER_FIELD
) {
153 * If the buffer_field arguments have not been previously evaluated,
154 * evaluate them now and save the results.
156 if (!(obj_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
157 status
= acpi_ds_get_buffer_field_arguments(obj_desc
);
158 if (ACPI_FAILURE(status
)) {
159 return_ACPI_STATUS(status
);
162 } else if ((obj_desc
->common
.type
== ACPI_TYPE_LOCAL_REGION_FIELD
) &&
163 (obj_desc
->field
.region_obj
->region
.space_id
==
165 || obj_desc
->field
.region_obj
->region
.space_id
==
167 || obj_desc
->field
.region_obj
->region
.space_id
==
168 ACPI_ADR_SPACE_IPMI
)) {
170 * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold
171 * the data and then directly access the region handler.
173 * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function
175 if (obj_desc
->field
.region_obj
->region
.space_id
==
176 ACPI_ADR_SPACE_SMBUS
) {
177 length
= ACPI_SMBUS_BUFFER_SIZE
;
179 ACPI_READ
| (obj_desc
->field
.attribute
<< 16);
180 } else if (obj_desc
->field
.region_obj
->region
.space_id
==
181 ACPI_ADR_SPACE_GSBUS
) {
182 accessor_type
= obj_desc
->field
.attribute
;
183 length
= acpi_ex_get_serial_access_length(accessor_type
,
189 * Add additional 2 bytes for the generic_serial_bus data buffer:
191 * Status; (Byte 0 of the data buffer)
192 * Length; (Byte 1 of the data buffer)
193 * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
196 function
= ACPI_READ
| (accessor_type
<< 16);
199 length
= ACPI_IPMI_BUFFER_SIZE
;
200 function
= ACPI_READ
;
203 buffer_desc
= acpi_ut_create_buffer_object(length
);
205 return_ACPI_STATUS(AE_NO_MEMORY
);
208 /* Lock entire transaction if requested */
210 acpi_ex_acquire_global_lock(obj_desc
->common_field
.field_flags
);
212 /* Call the region handler for the read */
214 status
= acpi_ex_access_region(obj_desc
, 0,
219 acpi_ex_release_global_lock(obj_desc
->common_field
.field_flags
);
224 * Allocate a buffer for the contents of the field.
226 * If the field is larger than the current integer width, create
227 * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
228 * the use of arithmetic operators on the returned value if the
229 * field size is equal or smaller than an Integer.
231 * Note: Field.length is in bits.
234 (acpi_size
) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc
->field
.bit_length
);
235 if (length
> acpi_gbl_integer_byte_width
) {
237 /* Field is too large for an Integer, create a Buffer instead */
239 buffer_desc
= acpi_ut_create_buffer_object(length
);
241 return_ACPI_STATUS(AE_NO_MEMORY
);
243 buffer
= buffer_desc
->buffer
.pointer
;
245 /* Field will fit within an Integer (normal case) */
247 buffer_desc
= acpi_ut_create_integer_object((u64
) 0);
249 return_ACPI_STATUS(AE_NO_MEMORY
);
252 length
= acpi_gbl_integer_byte_width
;
253 buffer
= &buffer_desc
->integer
.value
;
256 if ((obj_desc
->common
.type
== ACPI_TYPE_LOCAL_REGION_FIELD
) &&
257 (obj_desc
->field
.region_obj
->region
.space_id
==
258 ACPI_ADR_SPACE_GPIO
)) {
260 * For GPIO (general_purpose_io), the Address will be the bit offset
261 * from the previous Connection() operator, making it effectively a
262 * pin number index. The bit_length is the length of the field, which
263 * is thus the number of pins.
265 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD
,
266 "GPIO FieldRead [FROM]: Pin %u Bits %u\n",
267 obj_desc
->field
.pin_number_index
,
268 obj_desc
->field
.bit_length
));
270 /* Lock entire transaction if requested */
272 acpi_ex_acquire_global_lock(obj_desc
->common_field
.field_flags
);
274 /* Perform the write */
276 status
= acpi_ex_access_region(obj_desc
, 0,
277 (u64
*)buffer
, ACPI_READ
);
278 acpi_ex_release_global_lock(obj_desc
->common_field
.field_flags
);
279 if (ACPI_FAILURE(status
)) {
280 acpi_ut_remove_reference(buffer_desc
);
282 *ret_buffer_desc
= buffer_desc
;
284 return_ACPI_STATUS(status
);
287 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD
,
288 "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
289 obj_desc
, obj_desc
->common
.type
, buffer
,
291 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD
,
292 "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
293 obj_desc
->common_field
.bit_length
,
294 obj_desc
->common_field
.start_field_bit_offset
,
295 obj_desc
->common_field
.base_byte_offset
));
297 /* Lock entire transaction if requested */
299 acpi_ex_acquire_global_lock(obj_desc
->common_field
.field_flags
);
301 /* Read from the field */
303 status
= acpi_ex_extract_from_field(obj_desc
, buffer
, (u32
) length
);
304 acpi_ex_release_global_lock(obj_desc
->common_field
.field_flags
);
307 if (ACPI_FAILURE(status
)) {
308 acpi_ut_remove_reference(buffer_desc
);
310 *ret_buffer_desc
= buffer_desc
;
313 return_ACPI_STATUS(status
);
316 /*******************************************************************************
318 * FUNCTION: acpi_ex_write_data_to_field
320 * PARAMETERS: source_desc - Contains data to write
321 * obj_desc - The named field
322 * result_desc - Where the return value is returned, if any
326 * DESCRIPTION: Write to a named field
328 ******************************************************************************/
331 acpi_ex_write_data_to_field(union acpi_operand_object
*source_desc
,
332 union acpi_operand_object
*obj_desc
,
333 union acpi_operand_object
**result_desc
)
338 union acpi_operand_object
*buffer_desc
;
342 ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field
, obj_desc
);
344 /* Parameter validation */
346 if (!source_desc
|| !obj_desc
) {
347 return_ACPI_STATUS(AE_AML_NO_OPERAND
);
350 if (obj_desc
->common
.type
== ACPI_TYPE_BUFFER_FIELD
) {
352 * If the buffer_field arguments have not been previously evaluated,
353 * evaluate them now and save the results.
355 if (!(obj_desc
->common
.flags
& AOPOBJ_DATA_VALID
)) {
356 status
= acpi_ds_get_buffer_field_arguments(obj_desc
);
357 if (ACPI_FAILURE(status
)) {
358 return_ACPI_STATUS(status
);
361 } else if ((obj_desc
->common
.type
== ACPI_TYPE_LOCAL_REGION_FIELD
) &&
362 (obj_desc
->field
.region_obj
->region
.space_id
==
364 || obj_desc
->field
.region_obj
->region
.space_id
==
366 || obj_desc
->field
.region_obj
->region
.space_id
==
367 ACPI_ADR_SPACE_IPMI
)) {
369 * This is an SMBus, GSBus or IPMI write. We will bypass the entire field
370 * mechanism and handoff the buffer directly to the handler. For
371 * these address spaces, the buffer is bi-directional; on a write,
372 * return data is returned in the same buffer.
374 * Source must be a buffer of sufficient size:
375 * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
377 * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function
379 if (source_desc
->common
.type
!= ACPI_TYPE_BUFFER
) {
381 "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",
382 acpi_ut_get_object_type_name(source_desc
)));
384 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
387 if (obj_desc
->field
.region_obj
->region
.space_id
==
388 ACPI_ADR_SPACE_SMBUS
) {
389 length
= ACPI_SMBUS_BUFFER_SIZE
;
391 ACPI_WRITE
| (obj_desc
->field
.attribute
<< 16);
392 } else if (obj_desc
->field
.region_obj
->region
.space_id
==
393 ACPI_ADR_SPACE_GSBUS
) {
394 accessor_type
= obj_desc
->field
.attribute
;
395 length
= acpi_ex_get_serial_access_length(accessor_type
,
401 * Add additional 2 bytes for the generic_serial_bus data buffer:
403 * Status; (Byte 0 of the data buffer)
404 * Length; (Byte 1 of the data buffer)
405 * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
408 function
= ACPI_WRITE
| (accessor_type
<< 16);
411 length
= ACPI_IPMI_BUFFER_SIZE
;
412 function
= ACPI_WRITE
;
415 if (source_desc
->buffer
.length
< length
) {
417 "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",
418 length
, source_desc
->buffer
.length
));
420 return_ACPI_STATUS(AE_AML_BUFFER_LIMIT
);
423 /* Create the bi-directional buffer */
425 buffer_desc
= acpi_ut_create_buffer_object(length
);
427 return_ACPI_STATUS(AE_NO_MEMORY
);
430 buffer
= buffer_desc
->buffer
.pointer
;
431 memcpy(buffer
, source_desc
->buffer
.pointer
, length
);
433 /* Lock entire transaction if requested */
435 acpi_ex_acquire_global_lock(obj_desc
->common_field
.field_flags
);
438 * Perform the write (returns status and perhaps data in the
441 status
= acpi_ex_access_region(obj_desc
, 0,
442 (u64
*) buffer
, function
);
443 acpi_ex_release_global_lock(obj_desc
->common_field
.field_flags
);
445 *result_desc
= buffer_desc
;
446 return_ACPI_STATUS(status
);
447 } else if ((obj_desc
->common
.type
== ACPI_TYPE_LOCAL_REGION_FIELD
) &&
448 (obj_desc
->field
.region_obj
->region
.space_id
==
449 ACPI_ADR_SPACE_GPIO
)) {
451 * For GPIO (general_purpose_io), we will bypass the entire field
452 * mechanism and handoff the bit address and bit width directly to
453 * the handler. The Address will be the bit offset
454 * from the previous Connection() operator, making it effectively a
455 * pin number index. The bit_length is the length of the field, which
456 * is thus the number of pins.
458 if (source_desc
->common
.type
!= ACPI_TYPE_INTEGER
) {
459 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
462 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD
,
463 "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
464 acpi_ut_get_type_name(source_desc
->common
.
466 source_desc
->common
.type
,
467 (u32
)source_desc
->integer
.value
,
468 obj_desc
->field
.pin_number_index
,
469 obj_desc
->field
.bit_length
));
471 buffer
= &source_desc
->integer
.value
;
473 /* Lock entire transaction if requested */
475 acpi_ex_acquire_global_lock(obj_desc
->common_field
.field_flags
);
477 /* Perform the write */
479 status
= acpi_ex_access_region(obj_desc
, 0,
480 (u64
*)buffer
, ACPI_WRITE
);
481 acpi_ex_release_global_lock(obj_desc
->common_field
.field_flags
);
482 return_ACPI_STATUS(status
);
485 /* Get a pointer to the data to be written */
487 switch (source_desc
->common
.type
) {
488 case ACPI_TYPE_INTEGER
:
490 buffer
= &source_desc
->integer
.value
;
491 length
= sizeof(source_desc
->integer
.value
);
494 case ACPI_TYPE_BUFFER
:
496 buffer
= source_desc
->buffer
.pointer
;
497 length
= source_desc
->buffer
.length
;
500 case ACPI_TYPE_STRING
:
502 buffer
= source_desc
->string
.pointer
;
503 length
= source_desc
->string
.length
;
508 return_ACPI_STATUS(AE_AML_OPERAND_TYPE
);
511 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD
,
512 "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
514 acpi_ut_get_type_name(source_desc
->common
.type
),
515 source_desc
->common
.type
, buffer
, length
));
517 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD
,
518 "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
520 acpi_ut_get_type_name(obj_desc
->common
.type
),
521 obj_desc
->common
.type
,
522 obj_desc
->common_field
.bit_length
,
523 obj_desc
->common_field
.start_field_bit_offset
,
524 obj_desc
->common_field
.base_byte_offset
));
526 /* Lock entire transaction if requested */
528 acpi_ex_acquire_global_lock(obj_desc
->common_field
.field_flags
);
530 /* Write to the field */
532 status
= acpi_ex_insert_into_field(obj_desc
, buffer
, length
);
533 acpi_ex_release_global_lock(obj_desc
->common_field
.field_flags
);
535 return_ACPI_STATUS(status
);