1 /******************************************************************************
3 * Module Name: dsfield - Dispatcher field routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2011, 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.
46 #include <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48 #include <contrib/dev/acpica/include/amlcode.h>
49 #include <contrib/dev/acpica/include/acdispat.h>
50 #include <contrib/dev/acpica/include/acinterp.h>
51 #include <contrib/dev/acpica/include/acnamesp.h>
52 #include <contrib/dev/acpica/include/acparser.h>
55 #define _COMPONENT ACPI_DISPATCHER
56 ACPI_MODULE_NAME ("dsfield")
58 /* Local prototypes */
62 ACPI_CREATE_FIELD_INFO *Info,
63 ACPI_WALK_STATE *WalkState,
64 ACPI_PARSE_OBJECT *Arg);
67 /*******************************************************************************
69 * FUNCTION: AcpiDsCreateBufferField
71 * PARAMETERS: Op - Current parse op (CreateXXField)
72 * WalkState - Current state
76 * DESCRIPTION: Execute the CreateField operators:
82 * CreateFieldOp (all of which define a field in a buffer)
84 ******************************************************************************/
87 AcpiDsCreateBufferField (
88 ACPI_PARSE_OBJECT *Op,
89 ACPI_WALK_STATE *WalkState)
91 ACPI_PARSE_OBJECT *Arg;
92 ACPI_NAMESPACE_NODE *Node;
94 ACPI_OPERAND_OBJECT *ObjDesc;
95 ACPI_OPERAND_OBJECT *SecondDesc = NULL;
99 ACPI_FUNCTION_TRACE (DsCreateBufferField);
103 * Get the NameString argument (name of the new BufferField)
105 if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)
107 /* For CreateField, name is the 4th argument */
109 Arg = AcpiPsGetArg (Op, 3);
113 /* For all other CreateXXXField operators, name is the 3rd argument */
115 Arg = AcpiPsGetArg (Op, 2);
120 return_ACPI_STATUS (AE_AML_NO_OPERAND);
123 if (WalkState->DeferredNode)
125 Node = WalkState->DeferredNode;
130 /* Execute flag should always be set when this function is entered */
132 if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE))
134 return_ACPI_STATUS (AE_AML_INTERNAL);
137 /* Creating new namespace node, should not already exist */
139 Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
140 ACPI_NS_ERROR_IF_FOUND;
143 * Mark node temporary if we are executing a normal control
144 * method. (Don't mark if this is a module-level code method)
146 if (WalkState->MethodNode &&
147 !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL))
149 Flags |= ACPI_NS_TEMPORARY;
152 /* Enter the NameString into the namespace */
154 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
155 ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
156 Flags, WalkState, &Node);
157 if (ACPI_FAILURE (Status))
159 ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status);
160 return_ACPI_STATUS (Status);
165 * We could put the returned object (Node) on the object stack for later,
166 * but for now, we will put it in the "op" object that the parser uses,
167 * so we can get it again at the end of this scope.
169 Op->Common.Node = Node;
172 * If there is no object attached to the node, this node was just created
173 * and we need to create the field object. Otherwise, this was a lookup
174 * of an existing node and we don't want to create the field object again.
176 ObjDesc = AcpiNsGetAttachedObject (Node);
179 return_ACPI_STATUS (AE_OK);
183 * The Field definition is not fully parsed at this time.
184 * (We must save the address of the AML for the buffer and index operands)
187 /* Create the buffer field object */
189 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER_FIELD);
192 Status = AE_NO_MEMORY;
197 * Remember location in AML stream of the field unit opcode and operands --
198 * since the buffer and index operands must be evaluated.
200 SecondDesc = ObjDesc->Common.NextObject;
201 SecondDesc->Extra.AmlStart = Op->Named.Data;
202 SecondDesc->Extra.AmlLength = Op->Named.Length;
203 ObjDesc->BufferField.Node = Node;
205 /* Attach constructed field descriptors to parent node */
207 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_BUFFER_FIELD);
208 if (ACPI_FAILURE (Status))
216 /* Remove local reference to the object */
218 AcpiUtRemoveReference (ObjDesc);
219 return_ACPI_STATUS (Status);
223 /*******************************************************************************
225 * FUNCTION: AcpiDsGetFieldNames
227 * PARAMETERS: Info - CreateField info structure
228 * ` WalkState - Current method state
229 * Arg - First parser arg for the field name list
233 * DESCRIPTION: Process all named fields in a field declaration. Names are
234 * entered into the namespace.
236 ******************************************************************************/
239 AcpiDsGetFieldNames (
240 ACPI_CREATE_FIELD_INFO *Info,
241 ACPI_WALK_STATE *WalkState,
242 ACPI_PARSE_OBJECT *Arg)
248 ACPI_FUNCTION_TRACE_PTR (DsGetFieldNames, Info);
251 /* First field starts at bit zero */
253 Info->FieldBitPosition = 0;
255 /* Process all elements in the field list (of parse nodes) */
260 * Three types of field elements are handled:
261 * 1) Offset - specifies a bit offset
262 * 2) AccessAs - changes the access mode
263 * 3) Name - Enters a new named field into the namespace
265 switch (Arg->Common.AmlOpcode)
267 case AML_INT_RESERVEDFIELD_OP:
269 Position = (UINT64) Info->FieldBitPosition
270 + (UINT64) Arg->Common.Value.Size;
272 if (Position > ACPI_UINT32_MAX)
274 ACPI_ERROR ((AE_INFO,
275 "Bit offset within field too large (> 0xFFFFFFFF)"));
276 return_ACPI_STATUS (AE_SUPPORT);
279 Info->FieldBitPosition = (UINT32) Position;
283 case AML_INT_ACCESSFIELD_OP:
286 * Get a new AccessType and AccessAttribute -- to be used for all
287 * field units that follow, until field end or another AccessAs
290 * In FieldFlags, preserve the flag bits other than the
293 Info->FieldFlags = (UINT8)
294 ((Info->FieldFlags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
295 ((UINT8) ((UINT32) Arg->Common.Value.Integer >> 8)));
297 Info->Attribute = (UINT8) (Arg->Common.Value.Integer);
301 case AML_INT_NAMEDFIELD_OP:
303 /* Lookup the name, it should already exist */
305 Status = AcpiNsLookup (WalkState->ScopeInfo,
306 (char *) &Arg->Named.Name, Info->FieldType,
307 ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
308 WalkState, &Info->FieldNode);
309 if (ACPI_FAILURE (Status))
311 ACPI_ERROR_NAMESPACE ((char *) &Arg->Named.Name, Status);
312 return_ACPI_STATUS (Status);
316 Arg->Common.Node = Info->FieldNode;
317 Info->FieldBitLength = Arg->Common.Value.Size;
320 * If there is no object attached to the node, this node was
321 * just created and we need to create the field object.
322 * Otherwise, this was a lookup of an existing node and we
323 * don't want to create the field object again.
325 if (!AcpiNsGetAttachedObject (Info->FieldNode))
327 Status = AcpiExPrepFieldValue (Info);
328 if (ACPI_FAILURE (Status))
330 return_ACPI_STATUS (Status);
335 /* Keep track of bit position for the next field */
337 Position = (UINT64) Info->FieldBitPosition
338 + (UINT64) Arg->Common.Value.Size;
340 if (Position > ACPI_UINT32_MAX)
342 ACPI_ERROR ((AE_INFO,
343 "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)",
344 ACPI_CAST_PTR (char, &Info->FieldNode->Name)));
345 return_ACPI_STATUS (AE_SUPPORT);
348 Info->FieldBitPosition += Info->FieldBitLength;
354 ACPI_ERROR ((AE_INFO,
355 "Invalid opcode in field list: 0x%X", Arg->Common.AmlOpcode));
356 return_ACPI_STATUS (AE_AML_BAD_OPCODE);
359 Arg = Arg->Common.Next;
362 return_ACPI_STATUS (AE_OK);
366 /*******************************************************************************
368 * FUNCTION: AcpiDsCreateField
370 * PARAMETERS: Op - Op containing the Field definition and args
371 * RegionNode - Object for the containing Operation Region
372 * ` WalkState - Current method state
376 * DESCRIPTION: Create a new field in the specified operation region
378 ******************************************************************************/
382 ACPI_PARSE_OBJECT *Op,
383 ACPI_NAMESPACE_NODE *RegionNode,
384 ACPI_WALK_STATE *WalkState)
387 ACPI_PARSE_OBJECT *Arg;
388 ACPI_CREATE_FIELD_INFO Info;
391 ACPI_FUNCTION_TRACE_PTR (DsCreateField, Op);
394 /* First arg is the name of the parent OpRegion (must already exist) */
396 Arg = Op->Common.Value.Arg;
399 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name,
400 ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
401 ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode);
402 if (ACPI_FAILURE (Status))
404 ACPI_ERROR_NAMESPACE (Arg->Common.Value.Name, Status);
405 return_ACPI_STATUS (Status);
409 /* Second arg is the field flags */
411 Arg = Arg->Common.Next;
412 Info.FieldFlags = (UINT8) Arg->Common.Value.Integer;
415 /* Each remaining arg is a Named Field */
417 Info.FieldType = ACPI_TYPE_LOCAL_REGION_FIELD;
418 Info.RegionNode = RegionNode;
420 Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next);
422 return_ACPI_STATUS (Status);
426 /*******************************************************************************
428 * FUNCTION: AcpiDsInitFieldObjects
430 * PARAMETERS: Op - Op containing the Field definition and args
431 * ` WalkState - Current method state
435 * DESCRIPTION: For each "Field Unit" name in the argument list that is
436 * part of the field declaration, enter the name into the
439 ******************************************************************************/
442 AcpiDsInitFieldObjects (
443 ACPI_PARSE_OBJECT *Op,
444 ACPI_WALK_STATE *WalkState)
447 ACPI_PARSE_OBJECT *Arg = NULL;
448 ACPI_NAMESPACE_NODE *Node;
453 ACPI_FUNCTION_TRACE_PTR (DsInitFieldObjects, Op);
456 /* Execute flag should always be set when this function is entered */
458 if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE))
460 if (WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP)
462 /* BankField Op is deferred, just return OK */
464 return_ACPI_STATUS (AE_OK);
467 return_ACPI_STATUS (AE_AML_INTERNAL);
471 * Get the FieldList argument for this opcode. This is the start of the
472 * list of field elements.
474 switch (WalkState->Opcode)
477 Arg = AcpiPsGetArg (Op, 2);
478 Type = ACPI_TYPE_LOCAL_REGION_FIELD;
481 case AML_BANK_FIELD_OP:
482 Arg = AcpiPsGetArg (Op, 4);
483 Type = ACPI_TYPE_LOCAL_BANK_FIELD;
486 case AML_INDEX_FIELD_OP:
487 Arg = AcpiPsGetArg (Op, 3);
488 Type = ACPI_TYPE_LOCAL_INDEX_FIELD;
492 return_ACPI_STATUS (AE_BAD_PARAMETER);
495 /* Creating new namespace node(s), should not already exist */
497 Flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
498 ACPI_NS_ERROR_IF_FOUND;
501 * Mark node(s) temporary if we are executing a normal control
502 * method. (Don't mark if this is a module-level code method)
504 if (WalkState->MethodNode &&
505 !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL))
507 Flags |= ACPI_NS_TEMPORARY;
511 * Walk the list of entries in the FieldList
512 * Note: FieldList can be of zero length. In this case, Arg will be NULL.
517 * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
518 * field names in order to enter them into the namespace.
520 if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
522 Status = AcpiNsLookup (WalkState->ScopeInfo,
523 (char *) &Arg->Named.Name, Type, ACPI_IMODE_LOAD_PASS1,
524 Flags, WalkState, &Node);
525 if (ACPI_FAILURE (Status))
527 ACPI_ERROR_NAMESPACE ((char *) &Arg->Named.Name, Status);
528 if (Status != AE_ALREADY_EXISTS)
530 return_ACPI_STATUS (Status);
533 /* Name already exists, just ignore this error */
538 Arg->Common.Node = Node;
541 /* Get the next field element in the list */
543 Arg = Arg->Common.Next;
546 return_ACPI_STATUS (AE_OK);
550 /*******************************************************************************
552 * FUNCTION: AcpiDsCreateBankField
554 * PARAMETERS: Op - Op containing the Field definition and args
555 * RegionNode - Object for the containing Operation Region
556 * WalkState - Current method state
560 * DESCRIPTION: Create a new bank field in the specified operation region
562 ******************************************************************************/
565 AcpiDsCreateBankField (
566 ACPI_PARSE_OBJECT *Op,
567 ACPI_NAMESPACE_NODE *RegionNode,
568 ACPI_WALK_STATE *WalkState)
571 ACPI_PARSE_OBJECT *Arg;
572 ACPI_CREATE_FIELD_INFO Info;
575 ACPI_FUNCTION_TRACE_PTR (DsCreateBankField, Op);
578 /* First arg is the name of the parent OpRegion (must already exist) */
580 Arg = Op->Common.Value.Arg;
583 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.Name,
584 ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
585 ACPI_NS_SEARCH_PARENT, WalkState, &RegionNode);
586 if (ACPI_FAILURE (Status))
588 ACPI_ERROR_NAMESPACE (Arg->Common.Value.Name, Status);
589 return_ACPI_STATUS (Status);
593 /* Second arg is the Bank Register (Field) (must already exist) */
595 Arg = Arg->Common.Next;
596 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
597 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
598 ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode);
599 if (ACPI_FAILURE (Status))
601 ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status);
602 return_ACPI_STATUS (Status);
606 * Third arg is the BankValue
607 * This arg is a TermArg, not a constant
608 * It will be evaluated later, by AcpiDsEvalBankFieldOperands
610 Arg = Arg->Common.Next;
612 /* Fourth arg is the field flags */
614 Arg = Arg->Common.Next;
615 Info.FieldFlags = (UINT8) Arg->Common.Value.Integer;
617 /* Each remaining arg is a Named Field */
619 Info.FieldType = ACPI_TYPE_LOCAL_BANK_FIELD;
620 Info.RegionNode = RegionNode;
623 * Use Info.DataRegisterNode to store BankField Op
624 * It's safe because DataRegisterNode will never be used when create bank field
625 * We store AmlStart and AmlLength in the BankField Op for late evaluation
626 * Used in AcpiExPrepFieldValue(Info)
628 * TBD: Or, should we add a field in ACPI_CREATE_FIELD_INFO, like "void *ParentOp"?
630 Info.DataRegisterNode = (ACPI_NAMESPACE_NODE*) Op;
632 Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next);
633 return_ACPI_STATUS (Status);
637 /*******************************************************************************
639 * FUNCTION: AcpiDsCreateIndexField
641 * PARAMETERS: Op - Op containing the Field definition and args
642 * RegionNode - Object for the containing Operation Region
643 * ` WalkState - Current method state
647 * DESCRIPTION: Create a new index field in the specified operation region
649 ******************************************************************************/
652 AcpiDsCreateIndexField (
653 ACPI_PARSE_OBJECT *Op,
654 ACPI_NAMESPACE_NODE *RegionNode,
655 ACPI_WALK_STATE *WalkState)
658 ACPI_PARSE_OBJECT *Arg;
659 ACPI_CREATE_FIELD_INFO Info;
662 ACPI_FUNCTION_TRACE_PTR (DsCreateIndexField, Op);
665 /* First arg is the name of the Index register (must already exist) */
667 Arg = Op->Common.Value.Arg;
668 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
669 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
670 ACPI_NS_SEARCH_PARENT, WalkState, &Info.RegisterNode);
671 if (ACPI_FAILURE (Status))
673 ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status);
674 return_ACPI_STATUS (Status);
677 /* Second arg is the data register (must already exist) */
679 Arg = Arg->Common.Next;
680 Status = AcpiNsLookup (WalkState->ScopeInfo, Arg->Common.Value.String,
681 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
682 ACPI_NS_SEARCH_PARENT, WalkState, &Info.DataRegisterNode);
683 if (ACPI_FAILURE (Status))
685 ACPI_ERROR_NAMESPACE (Arg->Common.Value.String, Status);
686 return_ACPI_STATUS (Status);
689 /* Next arg is the field flags */
691 Arg = Arg->Common.Next;
692 Info.FieldFlags = (UINT8) Arg->Common.Value.Integer;
694 /* Each remaining arg is a Named Field */
696 Info.FieldType = ACPI_TYPE_LOCAL_INDEX_FIELD;
697 Info.RegionNode = RegionNode;
699 Status = AcpiDsGetFieldNames (&Info, WalkState, Arg->Common.Next);
701 return_ACPI_STATUS (Status);