1 | /****************************************************************************** |
2 | * |
3 | * Module Name: exprep - ACPI AML field prep utilities |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
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.h" |
45 | #include "accommon.h" |
46 | #include "acinterp.h" |
47 | #include "amlcode.h" |
48 | #include "acnamesp.h" |
49 | #include "acdispat.h" |
50 | |
51 | |
52 | #define _COMPONENT ACPI_EXECUTER |
53 | ACPI_MODULE_NAME ("exprep" ) |
54 | |
55 | /* Local prototypes */ |
56 | |
57 | static UINT32 |
58 | AcpiExDecodeFieldAccess ( |
59 | ACPI_OPERAND_OBJECT *ObjDesc, |
60 | UINT8 FieldFlags, |
61 | UINT32 *ReturnByteAlignment); |
62 | |
63 | |
64 | #ifdef ACPI_UNDER_DEVELOPMENT |
65 | |
66 | static UINT32 |
67 | AcpiExGenerateAccess ( |
68 | UINT32 FieldBitOffset, |
69 | UINT32 FieldBitLength, |
70 | UINT32 RegionLength); |
71 | |
72 | |
73 | /******************************************************************************* |
74 | * |
75 | * FUNCTION: AcpiExGenerateAccess |
76 | * |
77 | * PARAMETERS: FieldBitOffset - Start of field within parent region/buffer |
78 | * FieldBitLength - Length of field in bits |
79 | * RegionLength - Length of parent in bytes |
80 | * |
81 | * RETURN: Field granularity (8, 16, 32 or 64) and |
82 | * ByteAlignment (1, 2, 3, or 4) |
83 | * |
84 | * DESCRIPTION: Generate an optimal access width for fields defined with the |
85 | * AnyAcc keyword. |
86 | * |
87 | * NOTE: Need to have the RegionLength in order to check for boundary |
88 | * conditions (end-of-region). However, the RegionLength is a deferred |
89 | * operation. Therefore, to complete this implementation, the generation |
90 | * of this access width must be deferred until the region length has |
91 | * been evaluated. |
92 | * |
93 | ******************************************************************************/ |
94 | |
95 | static UINT32 |
96 | AcpiExGenerateAccess ( |
97 | UINT32 FieldBitOffset, |
98 | UINT32 FieldBitLength, |
99 | UINT32 RegionLength) |
100 | { |
101 | UINT32 FieldByteLength; |
102 | UINT32 FieldByteOffset; |
103 | UINT32 FieldByteEndOffset; |
104 | UINT32 AccessByteWidth; |
105 | UINT32 FieldStartOffset; |
106 | UINT32 FieldEndOffset; |
107 | UINT32 MinimumAccessWidth = 0xFFFFFFFF; |
108 | UINT32 MinimumAccesses = 0xFFFFFFFF; |
109 | UINT32 Accesses; |
110 | |
111 | |
112 | ACPI_FUNCTION_TRACE (ExGenerateAccess); |
113 | |
114 | |
115 | /* Round Field start offset and length to "minimal" byte boundaries */ |
116 | |
117 | FieldByteOffset = ACPI_DIV_8 ( |
118 | ACPI_ROUND_DOWN (FieldBitOffset, 8)); |
119 | |
120 | FieldByteEndOffset = ACPI_DIV_8 ( |
121 | ACPI_ROUND_UP (FieldBitLength + FieldBitOffset, 8)); |
122 | |
123 | FieldByteLength = FieldByteEndOffset - FieldByteOffset; |
124 | |
125 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
126 | "Bit length %u, Bit offset %u\n" , |
127 | FieldBitLength, FieldBitOffset)); |
128 | |
129 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
130 | "Byte Length %u, Byte Offset %u, End Offset %u\n" , |
131 | FieldByteLength, FieldByteOffset, FieldByteEndOffset)); |
132 | |
133 | /* |
134 | * Iterative search for the maximum access width that is both aligned |
135 | * and does not go beyond the end of the region |
136 | * |
137 | * Start at ByteAcc and work upwards to QwordAcc max. (1,2,4,8 bytes) |
138 | */ |
139 | for (AccessByteWidth = 1; AccessByteWidth <= 8; AccessByteWidth <<= 1) |
140 | { |
141 | /* |
142 | * 1) Round end offset up to next access boundary and make sure that |
143 | * this does not go beyond the end of the parent region. |
144 | * 2) When the Access width is greater than the FieldByteLength, we |
145 | * are done. (This does not optimize for the perfectly aligned |
146 | * case yet). |
147 | */ |
148 | if (ACPI_ROUND_UP (FieldByteEndOffset, AccessByteWidth) <= |
149 | RegionLength) |
150 | { |
151 | FieldStartOffset = |
152 | ACPI_ROUND_DOWN (FieldByteOffset, AccessByteWidth) / |
153 | AccessByteWidth; |
154 | |
155 | FieldEndOffset = |
156 | ACPI_ROUND_UP ((FieldByteLength + FieldByteOffset), |
157 | AccessByteWidth) / AccessByteWidth; |
158 | |
159 | Accesses = FieldEndOffset - FieldStartOffset; |
160 | |
161 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
162 | "AccessWidth %u end is within region\n" , AccessByteWidth)); |
163 | |
164 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
165 | "Field Start %u, Field End %u -- requires %u accesses\n" , |
166 | FieldStartOffset, FieldEndOffset, Accesses)); |
167 | |
168 | /* Single access is optimal */ |
169 | |
170 | if (Accesses <= 1) |
171 | { |
172 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
173 | "Entire field can be accessed " |
174 | "with one operation of size %u\n" , |
175 | AccessByteWidth)); |
176 | return_VALUE (AccessByteWidth); |
177 | } |
178 | |
179 | /* |
180 | * Fits in the region, but requires more than one read/write. |
181 | * try the next wider access on next iteration |
182 | */ |
183 | if (Accesses < MinimumAccesses) |
184 | { |
185 | MinimumAccesses = Accesses; |
186 | MinimumAccessWidth = AccessByteWidth; |
187 | } |
188 | } |
189 | else |
190 | { |
191 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
192 | "AccessWidth %u end is NOT within region\n" , |
193 | AccessByteWidth)); |
194 | if (AccessByteWidth == 1) |
195 | { |
196 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
197 | "Field goes beyond end-of-region!\n" )); |
198 | |
199 | /* Field does not fit in the region at all */ |
200 | |
201 | return_VALUE (0); |
202 | } |
203 | |
204 | /* |
205 | * This width goes beyond the end-of-region, back off to |
206 | * previous access |
207 | */ |
208 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
209 | "Backing off to previous optimal access width of %u\n" , |
210 | MinimumAccessWidth)); |
211 | return_VALUE (MinimumAccessWidth); |
212 | } |
213 | } |
214 | |
215 | /* |
216 | * Could not read/write field with one operation, |
217 | * just use max access width |
218 | */ |
219 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
220 | "Cannot access field in one operation, using width 8\n" )); |
221 | |
222 | return_VALUE (8); |
223 | } |
224 | #endif /* ACPI_UNDER_DEVELOPMENT */ |
225 | |
226 | |
227 | /******************************************************************************* |
228 | * |
229 | * FUNCTION: AcpiExDecodeFieldAccess |
230 | * |
231 | * PARAMETERS: ObjDesc - Field object |
232 | * FieldFlags - Encoded fieldflags (contains access bits) |
233 | * ReturnByteAlignment - Where the byte alignment is returned |
234 | * |
235 | * RETURN: Field granularity (8, 16, 32 or 64) and |
236 | * ByteAlignment (1, 2, 3, or 4) |
237 | * |
238 | * DESCRIPTION: Decode the AccessType bits of a field definition. |
239 | * |
240 | ******************************************************************************/ |
241 | |
242 | static UINT32 |
243 | AcpiExDecodeFieldAccess ( |
244 | ACPI_OPERAND_OBJECT *ObjDesc, |
245 | UINT8 FieldFlags, |
246 | UINT32 *ReturnByteAlignment) |
247 | { |
248 | UINT32 Access; |
249 | UINT32 ByteAlignment; |
250 | UINT32 BitLength; |
251 | |
252 | |
253 | ACPI_FUNCTION_TRACE (ExDecodeFieldAccess); |
254 | |
255 | |
256 | Access = (FieldFlags & AML_FIELD_ACCESS_TYPE_MASK); |
257 | |
258 | switch (Access) |
259 | { |
260 | case AML_FIELD_ACCESS_ANY: |
261 | |
262 | #ifdef ACPI_UNDER_DEVELOPMENT |
263 | ByteAlignment = |
264 | AcpiExGenerateAccess (ObjDesc->CommonField.StartFieldBitOffset, |
265 | ObjDesc->CommonField.BitLength, |
266 | 0xFFFFFFFF /* Temp until we pass RegionLength as parameter */); |
267 | BitLength = ByteAlignment * 8; |
268 | #endif |
269 | |
270 | ByteAlignment = 1; |
271 | BitLength = 8; |
272 | break; |
273 | |
274 | case AML_FIELD_ACCESS_BYTE: |
275 | case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ |
276 | |
277 | ByteAlignment = 1; |
278 | BitLength = 8; |
279 | break; |
280 | |
281 | case AML_FIELD_ACCESS_WORD: |
282 | |
283 | ByteAlignment = 2; |
284 | BitLength = 16; |
285 | break; |
286 | |
287 | case AML_FIELD_ACCESS_DWORD: |
288 | |
289 | ByteAlignment = 4; |
290 | BitLength = 32; |
291 | break; |
292 | |
293 | case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ |
294 | |
295 | ByteAlignment = 8; |
296 | BitLength = 64; |
297 | break; |
298 | |
299 | default: |
300 | |
301 | /* Invalid field access type */ |
302 | |
303 | ACPI_ERROR ((AE_INFO, |
304 | "Unknown field access type 0x%X" , |
305 | Access)); |
306 | |
307 | return_UINT32 (0); |
308 | } |
309 | |
310 | if (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD) |
311 | { |
312 | /* |
313 | * BufferField access can be on any byte boundary, so the |
314 | * ByteAlignment is always 1 byte -- regardless of any ByteAlignment |
315 | * implied by the field access type. |
316 | */ |
317 | ByteAlignment = 1; |
318 | } |
319 | |
320 | *ReturnByteAlignment = ByteAlignment; |
321 | return_UINT32 (BitLength); |
322 | } |
323 | |
324 | |
325 | /******************************************************************************* |
326 | * |
327 | * FUNCTION: AcpiExPrepCommonFieldObject |
328 | * |
329 | * PARAMETERS: ObjDesc - The field object |
330 | * FieldFlags - Access, LockRule, and UpdateRule. |
331 | * The format of a FieldFlag is described |
332 | * in the ACPI specification |
333 | * FieldAttribute - Special attributes (not used) |
334 | * FieldBitPosition - Field start position |
335 | * FieldBitLength - Field length in number of bits |
336 | * |
337 | * RETURN: Status |
338 | * |
339 | * DESCRIPTION: Initialize the areas of the field object that are common |
340 | * to the various types of fields. Note: This is very "sensitive" |
341 | * code because we are solving the general case for field |
342 | * alignment. |
343 | * |
344 | ******************************************************************************/ |
345 | |
346 | ACPI_STATUS |
347 | AcpiExPrepCommonFieldObject ( |
348 | ACPI_OPERAND_OBJECT *ObjDesc, |
349 | UINT8 FieldFlags, |
350 | UINT8 FieldAttribute, |
351 | UINT32 FieldBitPosition, |
352 | UINT32 FieldBitLength) |
353 | { |
354 | UINT32 AccessBitWidth; |
355 | UINT32 ByteAlignment; |
356 | UINT32 NearestByteAddress; |
357 | |
358 | |
359 | ACPI_FUNCTION_TRACE (ExPrepCommonFieldObject); |
360 | |
361 | |
362 | /* |
363 | * Note: the structure being initialized is the |
364 | * ACPI_COMMON_FIELD_INFO; No structure fields outside of the common |
365 | * area are initialized by this procedure. |
366 | */ |
367 | ObjDesc->CommonField.FieldFlags = FieldFlags; |
368 | ObjDesc->CommonField.Attribute = FieldAttribute; |
369 | ObjDesc->CommonField.BitLength = FieldBitLength; |
370 | |
371 | /* |
372 | * Decode the access type so we can compute offsets. The access type gives |
373 | * two pieces of information - the width of each field access and the |
374 | * necessary ByteAlignment (address granularity) of the access. |
375 | * |
376 | * For AnyAcc, the AccessBitWidth is the largest width that is both |
377 | * necessary and possible in an attempt to access the whole field in one |
378 | * I/O operation. However, for AnyAcc, the ByteAlignment is always one |
379 | * byte. |
380 | * |
381 | * For all Buffer Fields, the ByteAlignment is always one byte. |
382 | * |
383 | * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is |
384 | * the same (equivalent) as the ByteAlignment. |
385 | */ |
386 | AccessBitWidth = AcpiExDecodeFieldAccess ( |
387 | ObjDesc, FieldFlags, &ByteAlignment); |
388 | if (!AccessBitWidth) |
389 | { |
390 | return_ACPI_STATUS (AE_AML_OPERAND_VALUE); |
391 | } |
392 | |
393 | /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */ |
394 | |
395 | ObjDesc->CommonField.AccessByteWidth = (UINT8) |
396 | ACPI_DIV_8 (AccessBitWidth); |
397 | |
398 | /* |
399 | * BaseByteOffset is the address of the start of the field within the |
400 | * region. It is the byte address of the first *datum* (field-width data |
401 | * unit) of the field. (i.e., the first datum that contains at least the |
402 | * first *bit* of the field.) |
403 | * |
404 | * Note: ByteAlignment is always either equal to the AccessBitWidth or 8 |
405 | * (Byte access), and it defines the addressing granularity of the parent |
406 | * region or buffer. |
407 | */ |
408 | NearestByteAddress = |
409 | ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition); |
410 | ObjDesc->CommonField.BaseByteOffset = (UINT32) |
411 | ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment); |
412 | |
413 | /* |
414 | * StartFieldBitOffset is the offset of the first bit of the field within |
415 | * a field datum. |
416 | */ |
417 | ObjDesc->CommonField.StartFieldBitOffset = (UINT8) |
418 | (FieldBitPosition - ACPI_MUL_8 (ObjDesc->CommonField.BaseByteOffset)); |
419 | |
420 | return_ACPI_STATUS (AE_OK); |
421 | } |
422 | |
423 | |
424 | /******************************************************************************* |
425 | * |
426 | * FUNCTION: AcpiExPrepFieldValue |
427 | * |
428 | * PARAMETERS: Info - Contains all field creation info |
429 | * |
430 | * RETURN: Status |
431 | * |
432 | * DESCRIPTION: Construct an object of type ACPI_OPERAND_OBJECT with a |
433 | * subtype of DefField and connect it to the parent Node. |
434 | * |
435 | ******************************************************************************/ |
436 | |
437 | ACPI_STATUS |
438 | AcpiExPrepFieldValue ( |
439 | ACPI_CREATE_FIELD_INFO *Info) |
440 | { |
441 | ACPI_OPERAND_OBJECT *ObjDesc; |
442 | ACPI_OPERAND_OBJECT *SecondDesc = NULL; |
443 | ACPI_STATUS Status; |
444 | UINT32 AccessByteWidth; |
445 | UINT32 Type; |
446 | |
447 | |
448 | ACPI_FUNCTION_TRACE (ExPrepFieldValue); |
449 | |
450 | |
451 | /* Parameter validation */ |
452 | |
453 | if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD) |
454 | { |
455 | if (!Info->RegionNode) |
456 | { |
457 | ACPI_ERROR ((AE_INFO, "Null RegionNode" )); |
458 | return_ACPI_STATUS (AE_AML_NO_OPERAND); |
459 | } |
460 | |
461 | Type = AcpiNsGetType (Info->RegionNode); |
462 | if (Type != ACPI_TYPE_REGION) |
463 | { |
464 | ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)" , |
465 | Type, AcpiUtGetTypeName (Type))); |
466 | |
467 | return_ACPI_STATUS (AE_AML_OPERAND_TYPE); |
468 | } |
469 | } |
470 | |
471 | /* Allocate a new field object */ |
472 | |
473 | ObjDesc = AcpiUtCreateInternalObject (Info->FieldType); |
474 | if (!ObjDesc) |
475 | { |
476 | return_ACPI_STATUS (AE_NO_MEMORY); |
477 | } |
478 | |
479 | /* Initialize areas of the object that are common to all fields */ |
480 | |
481 | ObjDesc->CommonField.Node = Info->FieldNode; |
482 | Status = AcpiExPrepCommonFieldObject (ObjDesc, |
483 | Info->FieldFlags, Info->Attribute, |
484 | Info->FieldBitPosition, Info->FieldBitLength); |
485 | if (ACPI_FAILURE (Status)) |
486 | { |
487 | AcpiUtDeleteObjectDesc (ObjDesc); |
488 | return_ACPI_STATUS (Status); |
489 | } |
490 | |
491 | /* Initialize areas of the object that are specific to the field type */ |
492 | |
493 | switch (Info->FieldType) |
494 | { |
495 | case ACPI_TYPE_LOCAL_REGION_FIELD: |
496 | |
497 | ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); |
498 | |
499 | /* Fields specific to GenericSerialBus fields */ |
500 | |
501 | ObjDesc->Field.AccessLength = Info->AccessLength; |
502 | |
503 | if (Info->ConnectionNode) |
504 | { |
505 | SecondDesc = Info->ConnectionNode->Object; |
506 | if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID)) |
507 | { |
508 | Status = AcpiDsGetBufferArguments (SecondDesc); |
509 | if (ACPI_FAILURE (Status)) |
510 | { |
511 | AcpiUtDeleteObjectDesc (ObjDesc); |
512 | return_ACPI_STATUS (Status); |
513 | } |
514 | } |
515 | |
516 | ObjDesc->Field.ResourceBuffer = |
517 | SecondDesc->Buffer.Pointer; |
518 | ObjDesc->Field.ResourceLength = |
519 | (UINT16) SecondDesc->Buffer.Length; |
520 | } |
521 | else if (Info->ResourceBuffer) |
522 | { |
523 | ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer; |
524 | ObjDesc->Field.ResourceLength = Info->ResourceLength; |
525 | } |
526 | |
527 | ObjDesc->Field.PinNumberIndex = Info->PinNumberIndex; |
528 | |
529 | /* Allow full data read from EC address space */ |
530 | |
531 | if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && |
532 | (ObjDesc->CommonField.BitLength > 8)) |
533 | { |
534 | AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES ( |
535 | ObjDesc->CommonField.BitLength); |
536 | |
537 | /* Maximum byte width supported is 255 */ |
538 | |
539 | if (AccessByteWidth < 256) |
540 | { |
541 | ObjDesc->CommonField.AccessByteWidth = |
542 | (UINT8) AccessByteWidth; |
543 | } |
544 | } |
545 | |
546 | /* An additional reference for the container */ |
547 | |
548 | AcpiUtAddReference (ObjDesc->Field.RegionObj); |
549 | |
550 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
551 | "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n" , |
552 | ObjDesc->Field.StartFieldBitOffset, |
553 | ObjDesc->Field.BaseByteOffset, |
554 | ObjDesc->Field.AccessByteWidth, |
555 | ObjDesc->Field.RegionObj)); |
556 | break; |
557 | |
558 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
559 | |
560 | ObjDesc->BankField.Value = Info->BankValue; |
561 | ObjDesc->BankField.RegionObj = |
562 | AcpiNsGetAttachedObject (Info->RegionNode); |
563 | ObjDesc->BankField.BankObj = |
564 | AcpiNsGetAttachedObject (Info->RegisterNode); |
565 | |
566 | /* An additional reference for the attached objects */ |
567 | |
568 | AcpiUtAddReference (ObjDesc->BankField.RegionObj); |
569 | AcpiUtAddReference (ObjDesc->BankField.BankObj); |
570 | |
571 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
572 | "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n" , |
573 | ObjDesc->BankField.StartFieldBitOffset, |
574 | ObjDesc->BankField.BaseByteOffset, |
575 | ObjDesc->Field.AccessByteWidth, |
576 | ObjDesc->BankField.RegionObj, |
577 | ObjDesc->BankField.BankObj)); |
578 | |
579 | /* |
580 | * Remember location in AML stream of the field unit |
581 | * opcode and operands -- since the BankValue |
582 | * operands must be evaluated. |
583 | */ |
584 | SecondDesc = ObjDesc->Common.NextObject; |
585 | SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, |
586 | Info->DataRegisterNode)->Named.Data; |
587 | SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, |
588 | Info->DataRegisterNode)->Named.Length; |
589 | |
590 | break; |
591 | |
592 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
593 | |
594 | /* Get the Index and Data registers */ |
595 | |
596 | ObjDesc->IndexField.IndexObj = |
597 | AcpiNsGetAttachedObject (Info->RegisterNode); |
598 | ObjDesc->IndexField.DataObj = |
599 | AcpiNsGetAttachedObject (Info->DataRegisterNode); |
600 | |
601 | if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj) |
602 | { |
603 | ACPI_ERROR ((AE_INFO, "Null Index Object during field prep" )); |
604 | AcpiUtDeleteObjectDesc (ObjDesc); |
605 | return_ACPI_STATUS (AE_AML_INTERNAL); |
606 | } |
607 | |
608 | /* An additional reference for the attached objects */ |
609 | |
610 | AcpiUtAddReference (ObjDesc->IndexField.DataObj); |
611 | AcpiUtAddReference (ObjDesc->IndexField.IndexObj); |
612 | |
613 | /* |
614 | * April 2006: Changed to match MS behavior |
615 | * |
616 | * The value written to the Index register is the byte offset of the |
617 | * target field in units of the granularity of the IndexField |
618 | * |
619 | * Previously, the value was calculated as an index in terms of the |
620 | * width of the Data register, as below: |
621 | * |
622 | * ObjDesc->IndexField.Value = (UINT32) |
623 | * (Info->FieldBitPosition / ACPI_MUL_8 ( |
624 | * ObjDesc->Field.AccessByteWidth)); |
625 | * |
626 | * February 2006: Tried value as a byte offset: |
627 | * ObjDesc->IndexField.Value = (UINT32) |
628 | * ACPI_DIV_8 (Info->FieldBitPosition); |
629 | */ |
630 | ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN ( |
631 | ACPI_DIV_8 (Info->FieldBitPosition), |
632 | ObjDesc->IndexField.AccessByteWidth); |
633 | |
634 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
635 | "IndexField: BitOff %X, Off %X, Value %X, " |
636 | "Gran %X, Index %p, Data %p\n" , |
637 | ObjDesc->IndexField.StartFieldBitOffset, |
638 | ObjDesc->IndexField.BaseByteOffset, |
639 | ObjDesc->IndexField.Value, |
640 | ObjDesc->Field.AccessByteWidth, |
641 | ObjDesc->IndexField.IndexObj, |
642 | ObjDesc->IndexField.DataObj)); |
643 | break; |
644 | |
645 | default: |
646 | |
647 | /* No other types should get here */ |
648 | |
649 | break; |
650 | } |
651 | |
652 | /* |
653 | * Store the constructed descriptor (ObjDesc) into the parent Node, |
654 | * preserving the current type of that NamedObj. |
655 | */ |
656 | Status = AcpiNsAttachObject ( |
657 | Info->FieldNode, ObjDesc, AcpiNsGetType (Info->FieldNode)); |
658 | |
659 | ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, |
660 | "Set NamedObj %p [%4.4s], ObjDesc %p\n" , |
661 | Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc)); |
662 | |
663 | /* Remove local reference to the object */ |
664 | |
665 | AcpiUtRemoveReference (ObjDesc); |
666 | return_ACPI_STATUS (Status); |
667 | } |
668 | |