Commit | Line | Data |
---|---|---|
95857638 | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
1da177e4 LT |
2 | /****************************************************************************** |
3 | * | |
1fad8738 | 4 | * Module Name: exprep - ACPI AML field prep utilities |
1da177e4 | 5 | * |
612c2932 | 6 | * Copyright (C) 2000 - 2023, Intel Corp. |
1da177e4 | 7 | * |
95857638 | 8 | *****************************************************************************/ |
1da177e4 | 9 | |
1da177e4 | 10 | #include <acpi/acpi.h> |
e2f7a777 LB |
11 | #include "accommon.h" |
12 | #include "acinterp.h" | |
13 | #include "amlcode.h" | |
14 | #include "acnamesp.h" | |
9ce81784 | 15 | #include "acdispat.h" |
1da177e4 | 16 | |
1da177e4 | 17 | #define _COMPONENT ACPI_EXECUTER |
4be44fcd | 18 | ACPI_MODULE_NAME("exprep") |
1da177e4 | 19 | |
44f6c012 | 20 | /* Local prototypes */ |
44f6c012 | 21 | static u32 |
4be44fcd LB |
22 | acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, |
23 | u8 field_flags, u32 * return_byte_alignment); | |
1da177e4 LT |
24 | |
25 | #ifdef ACPI_UNDER_DEVELOPMENT | |
44f6c012 RM |
26 | |
27 | static u32 | |
4be44fcd LB |
28 | acpi_ex_generate_access(u32 field_bit_offset, |
29 | u32 field_bit_length, u32 region_length); | |
44f6c012 | 30 | |
1da177e4 LT |
31 | /******************************************************************************* |
32 | * | |
33 | * FUNCTION: acpi_ex_generate_access | |
34 | * | |
35 | * PARAMETERS: field_bit_offset - Start of field within parent region/buffer | |
36 | * field_bit_length - Length of field in bits | |
37 | * region_length - Length of parent in bytes | |
38 | * | |
39 | * RETURN: Field granularity (8, 16, 32 or 64) and | |
40 | * byte_alignment (1, 2, 3, or 4) | |
41 | * | |
42 | * DESCRIPTION: Generate an optimal access width for fields defined with the | |
43 | * any_acc keyword. | |
44 | * | |
45 | * NOTE: Need to have the region_length in order to check for boundary | |
73a3090a BM |
46 | * conditions (end-of-region). However, the region_length is a deferred |
47 | * operation. Therefore, to complete this implementation, the generation | |
1da177e4 LT |
48 | * of this access width must be deferred until the region length has |
49 | * been evaluated. | |
50 | * | |
51 | ******************************************************************************/ | |
52 | ||
53 | static u32 | |
4be44fcd LB |
54 | acpi_ex_generate_access(u32 field_bit_offset, |
55 | u32 field_bit_length, u32 region_length) | |
1da177e4 | 56 | { |
4be44fcd LB |
57 | u32 field_byte_length; |
58 | u32 field_byte_offset; | |
59 | u32 field_byte_end_offset; | |
60 | u32 access_byte_width; | |
61 | u32 field_start_offset; | |
62 | u32 field_end_offset; | |
63 | u32 minimum_access_width = 0xFFFFFFFF; | |
64 | u32 minimum_accesses = 0xFFFFFFFF; | |
65 | u32 accesses; | |
66 | ||
b229cf92 | 67 | ACPI_FUNCTION_TRACE(ex_generate_access); |
1da177e4 LT |
68 | |
69 | /* Round Field start offset and length to "minimal" byte boundaries */ | |
70 | ||
4be44fcd | 71 | field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8)); |
1fad8738 BM |
72 | |
73 | field_byte_end_offset = | |
74 | ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length + field_bit_offset, 8)); | |
75 | ||
4be44fcd | 76 | field_byte_length = field_byte_end_offset - field_byte_offset; |
1da177e4 | 77 | |
4be44fcd | 78 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b27d6597 | 79 | "Bit length %u, Bit offset %u\n", |
4be44fcd | 80 | field_bit_length, field_bit_offset)); |
44f6c012 | 81 | |
4be44fcd | 82 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b27d6597 | 83 | "Byte Length %u, Byte Offset %u, End Offset %u\n", |
4be44fcd LB |
84 | field_byte_length, field_byte_offset, |
85 | field_byte_end_offset)); | |
1da177e4 LT |
86 | |
87 | /* | |
88 | * Iterative search for the maximum access width that is both aligned | |
89 | * and does not go beyond the end of the region | |
90 | * | |
91 | * Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes) | |
92 | */ | |
4be44fcd LB |
93 | for (access_byte_width = 1; access_byte_width <= 8; |
94 | access_byte_width <<= 1) { | |
1da177e4 | 95 | /* |
44f6c012 RM |
96 | * 1) Round end offset up to next access boundary and make sure that |
97 | * this does not go beyond the end of the parent region. | |
98 | * 2) When the Access width is greater than the field_byte_length, we | |
99 | * are done. (This does not optimize for the perfectly aligned | |
100 | * case yet). | |
1da177e4 | 101 | */ |
4be44fcd LB |
102 | if (ACPI_ROUND_UP(field_byte_end_offset, access_byte_width) <= |
103 | region_length) { | |
44f6c012 | 104 | field_start_offset = |
4be44fcd LB |
105 | ACPI_ROUND_DOWN(field_byte_offset, |
106 | access_byte_width) / | |
107 | access_byte_width; | |
44f6c012 RM |
108 | |
109 | field_end_offset = | |
4be44fcd LB |
110 | ACPI_ROUND_UP((field_byte_length + |
111 | field_byte_offset), | |
112 | access_byte_width) / | |
113 | access_byte_width; | |
44f6c012 RM |
114 | |
115 | accesses = field_end_offset - field_start_offset; | |
1da177e4 | 116 | |
4be44fcd | 117 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b27d6597 | 118 | "AccessWidth %u end is within region\n", |
4be44fcd | 119 | access_byte_width)); |
44f6c012 | 120 | |
4be44fcd | 121 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b27d6597 | 122 | "Field Start %u, Field End %u -- requires %u accesses\n", |
4be44fcd LB |
123 | field_start_offset, field_end_offset, |
124 | accesses)); | |
1da177e4 LT |
125 | |
126 | /* Single access is optimal */ | |
127 | ||
128 | if (accesses <= 1) { | |
4be44fcd | 129 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
1fad8738 BM |
130 | "Entire field can be accessed " |
131 | "with one operation of size %u\n", | |
4be44fcd LB |
132 | access_byte_width)); |
133 | return_VALUE(access_byte_width); | |
1da177e4 LT |
134 | } |
135 | ||
136 | /* | |
137 | * Fits in the region, but requires more than one read/write. | |
138 | * try the next wider access on next iteration | |
139 | */ | |
140 | if (accesses < minimum_accesses) { | |
4be44fcd | 141 | minimum_accesses = accesses; |
1da177e4 LT |
142 | minimum_access_width = access_byte_width; |
143 | } | |
4be44fcd LB |
144 | } else { |
145 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | |
b27d6597 | 146 | "AccessWidth %u end is NOT within region\n", |
4be44fcd | 147 | access_byte_width)); |
1da177e4 | 148 | if (access_byte_width == 1) { |
4be44fcd LB |
149 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
150 | "Field goes beyond end-of-region!\n")); | |
1da177e4 | 151 | |
44f6c012 | 152 | /* Field does not fit in the region at all */ |
1da177e4 | 153 | |
4be44fcd | 154 | return_VALUE(0); |
44f6c012 RM |
155 | } |
156 | ||
157 | /* | |
158 | * This width goes beyond the end-of-region, back off to | |
159 | * previous access | |
160 | */ | |
4be44fcd | 161 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b27d6597 | 162 | "Backing off to previous optimal access width of %u\n", |
4be44fcd LB |
163 | minimum_access_width)); |
164 | return_VALUE(minimum_access_width); | |
1da177e4 LT |
165 | } |
166 | } | |
167 | ||
44f6c012 RM |
168 | /* |
169 | * Could not read/write field with one operation, | |
170 | * just use max access width | |
171 | */ | |
4be44fcd LB |
172 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
173 | "Cannot access field in one operation, using width 8\n")); | |
1fad8738 | 174 | |
4be44fcd | 175 | return_VALUE(8); |
1da177e4 | 176 | } |
4be44fcd | 177 | #endif /* ACPI_UNDER_DEVELOPMENT */ |
1da177e4 LT |
178 | |
179 | /******************************************************************************* | |
180 | * | |
181 | * FUNCTION: acpi_ex_decode_field_access | |
182 | * | |
44f6c012 RM |
183 | * PARAMETERS: obj_desc - Field object |
184 | * field_flags - Encoded fieldflags (contains access bits) | |
185 | * return_byte_alignment - Where the byte alignment is returned | |
1da177e4 LT |
186 | * |
187 | * RETURN: Field granularity (8, 16, 32 or 64) and | |
188 | * byte_alignment (1, 2, 3, or 4) | |
189 | * | |
190 | * DESCRIPTION: Decode the access_type bits of a field definition. | |
191 | * | |
192 | ******************************************************************************/ | |
193 | ||
194 | static u32 | |
4be44fcd LB |
195 | acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, |
196 | u8 field_flags, u32 * return_byte_alignment) | |
1da177e4 | 197 | { |
4be44fcd LB |
198 | u32 access; |
199 | u32 byte_alignment; | |
200 | u32 bit_length; | |
1da177e4 | 201 | |
b229cf92 | 202 | ACPI_FUNCTION_TRACE(ex_decode_field_access); |
1da177e4 LT |
203 | |
204 | access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK); | |
205 | ||
206 | switch (access) { | |
207 | case AML_FIELD_ACCESS_ANY: | |
208 | ||
209 | #ifdef ACPI_UNDER_DEVELOPMENT | |
44f6c012 | 210 | byte_alignment = |
4be44fcd LB |
211 | acpi_ex_generate_access(obj_desc->common_field. |
212 | start_field_bit_offset, | |
213 | obj_desc->common_field.bit_length, | |
214 | 0xFFFFFFFF | |
215 | /* Temp until we pass region_length as parameter */ | |
fd350943 | 216 | ); |
1da177e4 LT |
217 | bit_length = byte_alignment * 8; |
218 | #endif | |
219 | ||
220 | byte_alignment = 1; | |
221 | bit_length = 8; | |
222 | break; | |
223 | ||
224 | case AML_FIELD_ACCESS_BYTE: | |
4be44fcd | 225 | case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ |
1d1ea1b7 | 226 | |
1da177e4 | 227 | byte_alignment = 1; |
4be44fcd | 228 | bit_length = 8; |
1da177e4 LT |
229 | break; |
230 | ||
231 | case AML_FIELD_ACCESS_WORD: | |
1d1ea1b7 | 232 | |
1da177e4 | 233 | byte_alignment = 2; |
4be44fcd | 234 | bit_length = 16; |
1da177e4 LT |
235 | break; |
236 | ||
237 | case AML_FIELD_ACCESS_DWORD: | |
1d1ea1b7 | 238 | |
1da177e4 | 239 | byte_alignment = 4; |
4be44fcd | 240 | bit_length = 32; |
1da177e4 LT |
241 | break; |
242 | ||
4be44fcd | 243 | case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ |
1d1ea1b7 | 244 | |
1da177e4 | 245 | byte_alignment = 8; |
4be44fcd | 246 | bit_length = 64; |
1da177e4 LT |
247 | break; |
248 | ||
249 | default: | |
1d1ea1b7 | 250 | |
1da177e4 LT |
251 | /* Invalid field access type */ |
252 | ||
f6a22b0b | 253 | ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access)); |
1fad8738 | 254 | |
fd1af712 | 255 | return_UINT32(0); |
1da177e4 LT |
256 | } |
257 | ||
3371c19c | 258 | if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { |
1da177e4 LT |
259 | /* |
260 | * buffer_field access can be on any byte boundary, so the | |
261 | * byte_alignment is always 1 byte -- regardless of any byte_alignment | |
262 | * implied by the field access type. | |
263 | */ | |
264 | byte_alignment = 1; | |
265 | } | |
266 | ||
267 | *return_byte_alignment = byte_alignment; | |
fd1af712 | 268 | return_UINT32(bit_length); |
1da177e4 LT |
269 | } |
270 | ||
1da177e4 LT |
271 | /******************************************************************************* |
272 | * | |
273 | * FUNCTION: acpi_ex_prep_common_field_object | |
274 | * | |
275 | * PARAMETERS: obj_desc - The field object | |
276 | * field_flags - Access, lock_rule, and update_rule. | |
277 | * The format of a field_flag is described | |
278 | * in the ACPI specification | |
44f6c012 | 279 | * field_attribute - Special attributes (not used) |
1da177e4 LT |
280 | * field_bit_position - Field start position |
281 | * field_bit_length - Field length in number of bits | |
282 | * | |
283 | * RETURN: Status | |
284 | * | |
285 | * DESCRIPTION: Initialize the areas of the field object that are common | |
73a3090a | 286 | * to the various types of fields. Note: This is very "sensitive" |
1da177e4 LT |
287 | * code because we are solving the general case for field |
288 | * alignment. | |
289 | * | |
290 | ******************************************************************************/ | |
291 | ||
292 | acpi_status | |
4be44fcd LB |
293 | acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, |
294 | u8 field_flags, | |
295 | u8 field_attribute, | |
296 | u32 field_bit_position, u32 field_bit_length) | |
1da177e4 | 297 | { |
4be44fcd LB |
298 | u32 access_bit_width; |
299 | u32 byte_alignment; | |
300 | u32 nearest_byte_address; | |
1da177e4 | 301 | |
b229cf92 | 302 | ACPI_FUNCTION_TRACE(ex_prep_common_field_object); |
1da177e4 LT |
303 | |
304 | /* | |
305 | * Note: the structure being initialized is the | |
306 | * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common | |
307 | * area are initialized by this procedure. | |
308 | */ | |
309 | obj_desc->common_field.field_flags = field_flags; | |
310 | obj_desc->common_field.attribute = field_attribute; | |
311 | obj_desc->common_field.bit_length = field_bit_length; | |
312 | ||
313 | /* | |
73a3090a | 314 | * Decode the access type so we can compute offsets. The access type gives |
1da177e4 LT |
315 | * two pieces of information - the width of each field access and the |
316 | * necessary byte_alignment (address granularity) of the access. | |
317 | * | |
318 | * For any_acc, the access_bit_width is the largest width that is both | |
319 | * necessary and possible in an attempt to access the whole field in one | |
73a3090a | 320 | * I/O operation. However, for any_acc, the byte_alignment is always one |
1da177e4 LT |
321 | * byte. |
322 | * | |
323 | * For all Buffer Fields, the byte_alignment is always one byte. | |
324 | * | |
325 | * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is | |
326 | * the same (equivalent) as the byte_alignment. | |
327 | */ | |
1fad8738 BM |
328 | access_bit_width = |
329 | acpi_ex_decode_field_access(obj_desc, field_flags, &byte_alignment); | |
1da177e4 | 330 | if (!access_bit_width) { |
4be44fcd | 331 | return_ACPI_STATUS(AE_AML_OPERAND_VALUE); |
1da177e4 LT |
332 | } |
333 | ||
09387b43 | 334 | /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */ |
1da177e4 LT |
335 | |
336 | obj_desc->common_field.access_byte_width = (u8) | |
09387b43 | 337 | ACPI_DIV_8(access_bit_width); |
1da177e4 LT |
338 | |
339 | /* | |
340 | * base_byte_offset is the address of the start of the field within the | |
73a3090a | 341 | * region. It is the byte address of the first *datum* (field-width data |
1da177e4 LT |
342 | * unit) of the field. (i.e., the first datum that contains at least the |
343 | * first *bit* of the field.) | |
344 | * | |
345 | * Note: byte_alignment is always either equal to the access_bit_width or 8 | |
346 | * (Byte access), and it defines the addressing granularity of the parent | |
347 | * region or buffer. | |
348 | */ | |
349 | nearest_byte_address = | |
4be44fcd | 350 | ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position); |
1da177e4 | 351 | obj_desc->common_field.base_byte_offset = (u32) |
4be44fcd | 352 | ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment); |
1da177e4 LT |
353 | |
354 | /* | |
355 | * start_field_bit_offset is the offset of the first bit of the field within | |
356 | * a field datum. | |
357 | */ | |
358 | obj_desc->common_field.start_field_bit_offset = (u8) | |
4be44fcd LB |
359 | (field_bit_position - |
360 | ACPI_MUL_8(obj_desc->common_field.base_byte_offset)); | |
1da177e4 | 361 | |
4be44fcd | 362 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
363 | } |
364 | ||
1da177e4 LT |
365 | /******************************************************************************* |
366 | * | |
367 | * FUNCTION: acpi_ex_prep_field_value | |
368 | * | |
ba494bee | 369 | * PARAMETERS: info - Contains all field creation info |
1da177e4 LT |
370 | * |
371 | * RETURN: Status | |
372 | * | |
cf48958e BM |
373 | * DESCRIPTION: Construct an object of type union acpi_operand_object with a |
374 | * subtype of def_field and connect it to the parent Node. | |
1da177e4 LT |
375 | * |
376 | ******************************************************************************/ | |
377 | ||
4be44fcd | 378 | acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) |
1da177e4 | 379 | { |
4be44fcd | 380 | union acpi_operand_object *obj_desc; |
ef805d95 | 381 | union acpi_operand_object *second_desc = NULL; |
4be44fcd | 382 | acpi_status status; |
09387b43 BM |
383 | u32 access_byte_width; |
384 | u32 type; | |
1da177e4 | 385 | |
b229cf92 | 386 | ACPI_FUNCTION_TRACE(ex_prep_field_value); |
1da177e4 LT |
387 | |
388 | /* Parameter validation */ | |
389 | ||
390 | if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) { | |
391 | if (!info->region_node) { | |
b229cf92 | 392 | ACPI_ERROR((AE_INFO, "Null RegionNode")); |
4be44fcd | 393 | return_ACPI_STATUS(AE_AML_NO_OPERAND); |
1da177e4 LT |
394 | } |
395 | ||
4be44fcd | 396 | type = acpi_ns_get_type(info->region_node); |
1da177e4 | 397 | if (type != ACPI_TYPE_REGION) { |
b8e4d893 | 398 | ACPI_ERROR((AE_INFO, |
09387b43 BM |
399 | "Needed Region, found type 0x%X (%s)", type, |
400 | acpi_ut_get_type_name(type))); | |
1da177e4 | 401 | |
4be44fcd | 402 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
1da177e4 LT |
403 | } |
404 | } | |
405 | ||
406 | /* Allocate a new field object */ | |
407 | ||
4be44fcd | 408 | obj_desc = acpi_ut_create_internal_object(info->field_type); |
1da177e4 | 409 | if (!obj_desc) { |
4be44fcd | 410 | return_ACPI_STATUS(AE_NO_MEMORY); |
1da177e4 LT |
411 | } |
412 | ||
413 | /* Initialize areas of the object that are common to all fields */ | |
414 | ||
415 | obj_desc->common_field.node = info->field_node; | |
09387b43 BM |
416 | status = acpi_ex_prep_common_field_object(obj_desc, |
417 | info->field_flags, | |
4be44fcd LB |
418 | info->attribute, |
419 | info->field_bit_position, | |
420 | info->field_bit_length); | |
421 | if (ACPI_FAILURE(status)) { | |
422 | acpi_ut_delete_object_desc(obj_desc); | |
423 | return_ACPI_STATUS(status); | |
1da177e4 LT |
424 | } |
425 | ||
426 | /* Initialize areas of the object that are specific to the field type */ | |
427 | ||
428 | switch (info->field_type) { | |
429 | case ACPI_TYPE_LOCAL_REGION_FIELD: | |
430 | ||
4be44fcd LB |
431 | obj_desc->field.region_obj = |
432 | acpi_ns_get_attached_object(info->region_node); | |
1da177e4 | 433 | |
9ce81784 BM |
434 | /* Fields specific to generic_serial_bus fields */ |
435 | ||
436 | obj_desc->field.access_length = info->access_length; | |
437 | ||
438 | if (info->connection_node) { | |
439 | second_desc = info->connection_node->object; | |
a0a2459b AV |
440 | if (second_desc == NULL) { |
441 | break; | |
442 | } | |
9ce81784 BM |
443 | if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) { |
444 | status = | |
445 | acpi_ds_get_buffer_arguments(second_desc); | |
446 | if (ACPI_FAILURE(status)) { | |
447 | acpi_ut_delete_object_desc(obj_desc); | |
448 | return_ACPI_STATUS(status); | |
449 | } | |
450 | } | |
451 | ||
452 | obj_desc->field.resource_buffer = | |
453 | second_desc->buffer.pointer; | |
454 | obj_desc->field.resource_length = | |
455 | (u16)second_desc->buffer.length; | |
456 | } else if (info->resource_buffer) { | |
457 | obj_desc->field.resource_buffer = info->resource_buffer; | |
458 | obj_desc->field.resource_length = info->resource_length; | |
459 | } | |
460 | ||
75ec6e55 BM |
461 | obj_desc->field.pin_number_index = info->pin_number_index; |
462 | ||
09387b43 | 463 | /* Allow full data read from EC address space */ |
1da177e4 | 464 | |
09387b43 BM |
465 | if ((obj_desc->field.region_obj->region.space_id == |
466 | ACPI_ADR_SPACE_EC) | |
467 | && (obj_desc->common_field.bit_length > 8)) { | |
468 | access_byte_width = | |
469 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field. | |
470 | bit_length); | |
471 | ||
472 | /* Maximum byte width supported is 255 */ | |
1da177e4 | 473 | |
09387b43 | 474 | if (access_byte_width < 256) { |
dadf28a1 | 475 | obj_desc->common_field.access_byte_width = |
09387b43 | 476 | (u8)access_byte_width; |
2060c445 | 477 | } |
dadf28a1 | 478 | } |
4be44fcd | 479 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b229cf92 | 480 | "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", |
4be44fcd LB |
481 | obj_desc->field.start_field_bit_offset, |
482 | obj_desc->field.base_byte_offset, | |
483 | obj_desc->field.access_byte_width, | |
484 | obj_desc->field.region_obj)); | |
1da177e4 LT |
485 | break; |
486 | ||
1da177e4 LT |
487 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
488 | ||
4be44fcd LB |
489 | obj_desc->bank_field.value = info->bank_value; |
490 | obj_desc->bank_field.region_obj = | |
491 | acpi_ns_get_attached_object(info->region_node); | |
492 | obj_desc->bank_field.bank_obj = | |
493 | acpi_ns_get_attached_object(info->register_node); | |
1da177e4 LT |
494 | |
495 | /* An additional reference for the attached objects */ | |
496 | ||
4be44fcd LB |
497 | acpi_ut_add_reference(obj_desc->bank_field.region_obj); |
498 | acpi_ut_add_reference(obj_desc->bank_field.bank_obj); | |
1da177e4 | 499 | |
4be44fcd | 500 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b229cf92 | 501 | "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", |
4be44fcd LB |
502 | obj_desc->bank_field.start_field_bit_offset, |
503 | obj_desc->bank_field.base_byte_offset, | |
504 | obj_desc->field.access_byte_width, | |
505 | obj_desc->bank_field.region_obj, | |
506 | obj_desc->bank_field.bank_obj)); | |
ef805d95 LM |
507 | |
508 | /* | |
509 | * Remember location in AML stream of the field unit | |
510 | * opcode and operands -- since the bank_value | |
511 | * operands must be evaluated. | |
512 | */ | |
513 | second_desc = obj_desc->common.next_object; | |
514 | second_desc->extra.aml_start = | |
b5243764 BM |
515 | ACPI_CAST_PTR(union acpi_parse_object, |
516 | info->data_register_node)->named.data; | |
ef805d95 | 517 | second_desc->extra.aml_length = |
b5243764 BM |
518 | ACPI_CAST_PTR(union acpi_parse_object, |
519 | info->data_register_node)->named.length; | |
ef805d95 | 520 | |
1da177e4 LT |
521 | break; |
522 | ||
1da177e4 LT |
523 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
524 | ||
b8e4d893 BM |
525 | /* Get the Index and Data registers */ |
526 | ||
4be44fcd LB |
527 | obj_desc->index_field.index_obj = |
528 | acpi_ns_get_attached_object(info->register_node); | |
529 | obj_desc->index_field.data_obj = | |
530 | acpi_ns_get_attached_object(info->data_register_node); | |
4be44fcd LB |
531 | |
532 | if (!obj_desc->index_field.data_obj | |
533 | || !obj_desc->index_field.index_obj) { | |
b8e4d893 BM |
534 | ACPI_ERROR((AE_INFO, |
535 | "Null Index Object during field prep")); | |
4be44fcd LB |
536 | acpi_ut_delete_object_desc(obj_desc); |
537 | return_ACPI_STATUS(AE_AML_INTERNAL); | |
1da177e4 LT |
538 | } |
539 | ||
540 | /* An additional reference for the attached objects */ | |
541 | ||
4be44fcd LB |
542 | acpi_ut_add_reference(obj_desc->index_field.data_obj); |
543 | acpi_ut_add_reference(obj_desc->index_field.index_obj); | |
544 | ||
b8e4d893 | 545 | /* |
b229cf92 | 546 | * April 2006: Changed to match MS behavior |
ea936b78 | 547 | * |
b8e4d893 | 548 | * The value written to the Index register is the byte offset of the |
b229cf92 | 549 | * target field in units of the granularity of the index_field |
ea936b78 BM |
550 | * |
551 | * Previously, the value was calculated as an index in terms of the | |
552 | * width of the Data register, as below: | |
553 | * | |
b229cf92 BM |
554 | * obj_desc->index_field.Value = (u32) |
555 | * (Info->field_bit_position / ACPI_MUL_8 ( | |
556 | * obj_desc->Field.access_byte_width)); | |
557 | * | |
558 | * February 2006: Tried value as a byte offset: | |
559 | * obj_desc->index_field.Value = (u32) | |
560 | * ACPI_DIV_8 (Info->field_bit_position); | |
b8e4d893 | 561 | */ |
ea936b78 | 562 | obj_desc->index_field.value = |
b229cf92 BM |
563 | (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position), |
564 | obj_desc->index_field. | |
565 | access_byte_width); | |
b8e4d893 | 566 | |
4be44fcd | 567 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
1fad8738 BM |
568 | "IndexField: BitOff %X, Off %X, Value %X, " |
569 | "Gran %X, Index %p, Data %p\n", | |
4be44fcd LB |
570 | obj_desc->index_field.start_field_bit_offset, |
571 | obj_desc->index_field.base_byte_offset, | |
572 | obj_desc->index_field.value, | |
573 | obj_desc->field.access_byte_width, | |
574 | obj_desc->index_field.index_obj, | |
575 | obj_desc->index_field.data_obj)); | |
1da177e4 LT |
576 | break; |
577 | ||
578 | default: | |
1d1ea1b7 | 579 | |
1da177e4 | 580 | /* No other types should get here */ |
1d1ea1b7 | 581 | |
1da177e4 LT |
582 | break; |
583 | } | |
584 | ||
585 | /* | |
586 | * Store the constructed descriptor (obj_desc) into the parent Node, | |
587 | * preserving the current type of that named_obj. | |
588 | */ | |
1fad8738 BM |
589 | status = |
590 | acpi_ns_attach_object(info->field_node, obj_desc, | |
591 | acpi_ns_get_type(info->field_node)); | |
1da177e4 | 592 | |
4be44fcd | 593 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
b229cf92 | 594 | "Set NamedObj %p [%4.4s], ObjDesc %p\n", |
4be44fcd LB |
595 | info->field_node, |
596 | acpi_ut_get_node_name(info->field_node), obj_desc)); | |
1da177e4 LT |
597 | |
598 | /* Remove local reference to the object */ | |
599 | ||
4be44fcd LB |
600 | acpi_ut_remove_reference(obj_desc); |
601 | return_ACPI_STATUS(status); | |
1da177e4 | 602 | } |