* Intel ACPI 20030228 distribution with local DragonFly changes.
[dragonfly.git] / sys / contrib / dev / acpica / dmwalk.c
1 /*******************************************************************************
2  *
3  * Module Name: dmwalk - AML disassembly tree walk
4  *              $Revision: 9 $
5  *
6  ******************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 /* $DragonFly: src/sys/contrib/dev/acpica/Attic/dmwalk.c,v 1.1 2003/09/24 03:32:15 drhodus Exp $                                                               */
117
118
119 #include "acpi.h"
120 #include "acparser.h"
121 #include "amlcode.h"
122 #include "acdisasm.h"
123 #include "acdebug.h"
124
125
126 #ifdef ACPI_DISASSEMBLER
127
128 #define _COMPONENT          ACPI_CA_DEBUGGER
129         ACPI_MODULE_NAME    ("dmwalk")
130
131
132 #define DB_FULL_OP_INFO     "%5.5X #%4.4hX "
133
134
135 /*******************************************************************************
136  *
137  * FUNCTION:    AcpiDmDisassemble
138  *
139  * PARAMETERS:  Origin          - Starting object
140  *              NumOpcodes      - Max number of opcodes to be displayed
141  *
142  * RETURN:      None
143  *
144  * DESCRIPTION: Disassemble parser object and its children.  This is the
145  *              main entry point of the disassembler.
146  *
147  ******************************************************************************/
148
149 void
150 AcpiDmDisassemble (
151     ACPI_WALK_STATE         *WalkState,
152     ACPI_PARSE_OBJECT       *Origin,
153     UINT32                  NumOpcodes)
154 {
155     ACPI_PARSE_OBJECT       *Op = Origin;
156     ACPI_OP_WALK_INFO       Info;
157
158
159     if (!Op)
160     {
161         return;
162     }
163
164     Info.Level = 0;
165     AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
166
167     return;
168 }
169
170
171 /*******************************************************************************
172  *
173  * FUNCTION:    AcpiDmWalkParseTree
174  *
175  * PARAMETERS:  DescendingCallback      - Called during tree descent
176  *              AscendingCallback       - Called during tree ascent
177  *              Context                 - To be passed to the callbacks
178  *
179  * RETURN:      Status from callback(s)
180  *
181  * DESCRIPTION: Walk the entire parse tree.
182  *
183  ******************************************************************************/
184
185 void
186 AcpiDmWalkParseTree (
187     ACPI_PARSE_OBJECT       *Op,
188     ASL_WALK_CALLBACK       DescendingCallback,
189     ASL_WALK_CALLBACK       AscendingCallback,
190     void                    *Context)
191 {
192     BOOLEAN                 NodePreviouslyVisited;
193     ACPI_PARSE_OBJECT       *StartOp = Op;
194     ACPI_STATUS             Status;
195     ACPI_PARSE_OBJECT       *Next;
196     ACPI_OP_WALK_INFO       *Info = Context;
197
198
199     Info->Level = 0;
200     NodePreviouslyVisited = FALSE;
201
202     while (Op)
203     {
204         if (NodePreviouslyVisited)
205         {
206             Status = AscendingCallback (Op, Info->Level, Context);
207             if (ACPI_FAILURE (Status))
208             {
209                 return;
210             }
211         }
212         else
213         {
214             /*
215              * Let the callback process the node.
216              */
217             Status = DescendingCallback (Op, Info->Level, Context);
218             if (ACPI_SUCCESS (Status))
219             {
220                 /* Visit children first, once */
221
222                 Next = AcpiPsGetArg (Op, 0);
223                 if (Next)
224                 {
225                     Info->Level++;
226                     Op = Next;
227                     continue;
228                 }
229             }
230             else if (Status != AE_CTRL_DEPTH)
231             {
232                 /* Exit immediately on any error */
233
234                 return;
235             }
236         }
237
238         /* Terminate walk at start op */
239
240         if (Op == StartOp)
241         {
242             break;
243         }
244
245         /* No more children, re-visit this node */
246
247         if (!NodePreviouslyVisited)
248         {
249             NodePreviouslyVisited = TRUE;
250             continue;
251         }
252
253         /* No more children, visit peers */
254
255         if (Op->Common.Next)
256         {
257             Op = Op->Common.Next;
258             NodePreviouslyVisited = FALSE;
259         }
260         else
261         {
262             /* No peers, re-visit parent */
263
264             if (Info->Level != 0 )
265             {
266                 Info->Level--;
267             }
268
269             Op = Op->Common.Parent;
270             NodePreviouslyVisited = TRUE;
271         }
272     }
273
274     /* If we get here, the walk completed with no errors */
275
276     return;
277 }
278
279
280 /*******************************************************************************
281  *
282  * FUNCTION:    AcpiDmBlockType
283  *
284  * PARAMETERS:  Op              - Object to be examined
285  *
286  * RETURN:      Status
287  *
288  * DESCRIPTION: Type of block for this op (parens or braces)
289  *
290  ******************************************************************************/
291
292 UINT32
293 AcpiDmBlockType (
294     ACPI_PARSE_OBJECT       *Op)
295 {
296     const ACPI_OPCODE_INFO  *OpInfo;
297
298
299     if (!Op)
300     {
301         return (BLOCK_NONE);
302     }
303
304     switch (Op->Common.AmlOpcode)
305     {
306     case AML_ELSE_OP:
307
308         return (BLOCK_BRACE);
309
310     case AML_METHOD_OP:
311     case AML_DEVICE_OP:
312     case AML_SCOPE_OP:
313     case AML_PROCESSOR_OP:
314     case AML_POWER_RES_OP:
315     case AML_THERMAL_ZONE_OP:
316     case AML_IF_OP:
317     case AML_WHILE_OP:
318     case AML_FIELD_OP:
319     case AML_INDEX_FIELD_OP:
320     case AML_BANK_FIELD_OP:
321
322         return (BLOCK_PAREN | BLOCK_BRACE);
323
324     case AML_BUFFER_OP:
325
326         if (Op->Common.DisasmOpcode == ACPI_DASM_UNICODE)
327         {
328             return (BLOCK_NONE);
329         }
330
331         /*lint -fallthrough */
332
333     case AML_PACKAGE_OP:
334     case AML_VAR_PACKAGE_OP:
335
336         return (BLOCK_PAREN | BLOCK_BRACE);
337
338     case AML_EVENT_OP:
339
340         return (BLOCK_PAREN);
341
342     default:
343
344         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
345         if (OpInfo->Flags & AML_HAS_ARGS)
346         {
347             return (BLOCK_PAREN);
348         }
349
350         return (BLOCK_NONE);
351     }
352 }
353
354
355 /*******************************************************************************
356  *
357  * FUNCTION:    AcpiDmListType
358  *
359  * PARAMETERS:  Op              - Object to be examined
360  *
361  * RETURN:      Status
362  *
363  * DESCRIPTION: Type of block for this op (parens or braces)
364  *
365  ******************************************************************************/
366
367 UINT32
368 AcpiDmListType (
369     ACPI_PARSE_OBJECT       *Op)
370 {
371     const ACPI_OPCODE_INFO  *OpInfo;
372
373
374     if (!Op)
375     {
376         return (BLOCK_NONE);
377     }
378
379     switch (Op->Common.AmlOpcode)
380     {
381
382     case AML_ELSE_OP:
383     case AML_METHOD_OP:
384     case AML_DEVICE_OP:
385     case AML_SCOPE_OP:
386     case AML_POWER_RES_OP:
387     case AML_PROCESSOR_OP:
388     case AML_THERMAL_ZONE_OP:
389     case AML_IF_OP:
390     case AML_WHILE_OP:
391     case AML_FIELD_OP:
392     case AML_INDEX_FIELD_OP:
393     case AML_BANK_FIELD_OP:
394
395         return (0);
396
397     case AML_BUFFER_OP:
398     case AML_PACKAGE_OP:
399     case AML_VAR_PACKAGE_OP:
400
401         return (BLOCK_COMMA_LIST);
402
403     default:
404
405         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
406         if (OpInfo->Flags & AML_HAS_ARGS)
407         {
408             return (BLOCK_COMMA_LIST);
409         }
410
411         return (BLOCK_NONE);
412     }
413 }
414
415
416 /*******************************************************************************
417  *
418  * FUNCTION:    AcpiDmDescendingOp
419  *
420  * PARAMETERS:  ASL_WALK_CALLBACK
421  *
422  * RETURN:      Status
423  *
424  * DESCRIPTION: First visitation of a parse object during tree descent.
425  *              Decode opcode name and begin parameter list(s), if any.
426  *
427  ******************************************************************************/
428
429 ACPI_STATUS
430 AcpiDmDescendingOp (
431     ACPI_PARSE_OBJECT       *Op,
432     UINT32                  Level,
433     void                    *Context)
434 {
435     ACPI_OP_WALK_INFO       *Info = Context;
436     const ACPI_OPCODE_INFO  *OpInfo;
437     UINT32                  Name;
438     ACPI_PARSE_OBJECT       *NextOp;
439
440
441     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
442     {
443         /* Ignore this op -- it was handled elsewhere */
444
445         return (AE_CTRL_DEPTH);
446     }
447
448
449     if (Level == 0)
450     {
451         /* In verbose mode, print the AML offset, opcode and depth count */
452
453         VERBOSE_PRINT ((DB_FULL_OP_INFO, (UINT32) Op->Common.AmlOffset,
454                     Op->Common.AmlOpcode));
455
456         if (Op->Common.AmlOpcode == AML_SCOPE_OP)
457         {
458             AcpiOsPrintf ("{\n");
459             return (AE_OK);
460         }
461     }
462     else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
463              (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
464              (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
465     {
466             /* This is a first-level element of a term list, indent a new line */
467
468             AcpiDmIndent (Level);
469     }
470
471     /* Print the opcode name */
472
473     AcpiDmDisassembleOneOp (NULL, Info, Op);
474
475     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
476         (Op->Common.AmlOpcode == AML_RETURN_OP))
477     {
478         Info->Level--;
479     }
480
481     /*
482      * Start the opcode argument list if necessary
483      */
484     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
485
486     if ((OpInfo->Flags & AML_HAS_ARGS) ||
487         (Op->Common.AmlOpcode == AML_EVENT_OP))
488     {
489         /* This opcode has an argument list */
490
491         if (AcpiDmBlockType (Op) & BLOCK_PAREN)
492         {
493             AcpiOsPrintf (" (");
494         }
495
496         /*
497          * If this is a named opcode, print the associated name value
498          */
499         if (OpInfo->Flags & AML_NAMED)
500         {
501             switch (Op->Common.AmlOpcode)
502             {
503             case AML_ALIAS_OP:
504
505                 NextOp = AcpiPsGetDepthNext (NULL, Op);
506                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
507                 AcpiDmNamestring (NextOp->Common.Value.Name);
508                 AcpiOsPrintf (", ");
509
510                 /*lint -fallthrough */
511
512             default:
513
514                 Name = AcpiPsGetName (Op);
515                 if (Op->Named.Path)
516                 {
517                     AcpiDmNamestring ((char *) Op->Named.Path);
518                 }
519                 else
520                 {
521                     AcpiDmDumpName ((char *) &Name);
522                 }
523
524
525                 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
526                 {
527                     AcpiDmValidateName ((char *) &Name, Op);
528                     if (AcpiGbl_DbOpt_verbose)
529                     {
530                         (void) AcpiPsDisplayObjectPathname (NULL, Op);
531                     }
532                 }
533                 break;
534             }
535
536             switch (Op->Common.AmlOpcode)
537             {
538             case AML_METHOD_OP:
539
540                 AcpiDmMethodFlags (Op);
541                 AcpiOsPrintf (")");
542                 break;
543
544
545             case AML_NAME_OP:
546
547                 /* Check for _HID and related EISAID() */
548
549                 AcpiIsEisaId (Op);
550                 AcpiOsPrintf (", ");
551                 break;
552
553
554             case AML_REGION_OP:
555
556                 AcpiDmRegionFlags (Op);
557                 break;
558
559
560             case AML_POWER_RES_OP:
561
562                 /* Mark the next two Ops as part of the parameter list */
563
564                 AcpiOsPrintf (", ");
565                 NextOp = AcpiPsGetDepthNext (NULL, Op);
566                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
567
568                 NextOp = NextOp->Common.Next;
569                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
570                 return (AE_OK);
571
572
573             case AML_PROCESSOR_OP:
574
575                 /* Mark the next three Ops as part of the parameter list */
576
577                 AcpiOsPrintf (", ");
578                 NextOp = AcpiPsGetDepthNext (NULL, Op);
579                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
580
581                 NextOp = NextOp->Common.Next;
582                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
583
584                 NextOp = NextOp->Common.Next;
585                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
586                 return (AE_OK);
587
588
589             case AML_MUTEX_OP:
590
591                 AcpiOsPrintf (", ");
592                 return (AE_OK);
593
594
595             case AML_EVENT_OP:
596             case AML_ALIAS_OP:
597
598                 return (AE_OK);
599
600
601             case AML_SCOPE_OP:
602             case AML_DEVICE_OP:
603             case AML_THERMAL_ZONE_OP:
604
605                 AcpiOsPrintf (")");
606                 break;
607
608
609             default:
610
611                 AcpiOsPrintf ("*** Unhandled named opcode\n");
612                 break;
613             }
614         }
615
616         else switch (Op->Common.AmlOpcode)
617         {
618         case AML_FIELD_OP:
619         case AML_BANK_FIELD_OP:
620         case AML_INDEX_FIELD_OP:
621
622             Info->BitOffset = 0;
623
624             /* Name of the parent OperationRegion */
625
626             NextOp = AcpiPsGetDepthNext (NULL, Op);
627             AcpiDmNamestring (NextOp->Common.Value.Name);
628             AcpiOsPrintf (", ");
629             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
630
631             switch (Op->Common.AmlOpcode)
632             {
633             case AML_BANK_FIELD_OP:
634
635                 /* Namestring */
636
637                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
638                 AcpiDmNamestring (NextOp->Common.Value.Name);
639                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
640                 AcpiOsPrintf (", ");
641
642
643                 NextOp = NextOp->Common.Next;
644                 AcpiDmDisassembleOneOp (NULL, Info, NextOp);
645                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
646                 AcpiOsPrintf (", ");
647                 break;
648
649             case AML_INDEX_FIELD_OP:
650
651                 /* Namestring */
652
653                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
654                 AcpiDmNamestring (NextOp->Common.Value.Name);
655                 AcpiOsPrintf (", ");
656                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
657                 break;
658
659             default:
660
661                 break;
662             }
663
664             AcpiDmFieldFlags (NextOp);
665             break;
666
667
668         case AML_BUFFER_OP:
669
670             /* The next op is the size parameter */
671
672             NextOp = AcpiPsGetDepthNext (NULL, Op);
673             if (!NextOp)
674             {
675                 /* Single-step support */
676
677                 return (AE_OK);
678             }
679
680             if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
681             {
682                 /*
683                  * We have a resource list.  Don't need to output
684                  * the buffer size Op.  Open up a new block
685                  */
686                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
687                 NextOp = NextOp->Common.Next;
688                 AcpiOsPrintf (")\n");
689                 AcpiDmIndent (Info->Level);
690                 AcpiOsPrintf ("{\n");
691                 return (AE_OK);
692             }
693
694             /* Normal Buffer, mark size as in the parameter list */
695
696             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
697             return (AE_OK);
698
699
700         case AML_VAR_PACKAGE_OP:
701         case AML_IF_OP:
702         case AML_WHILE_OP:
703
704             /* The next op is the size or predicate parameter */
705
706             NextOp = AcpiPsGetDepthNext (NULL, Op);
707             if (NextOp)
708             {
709                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
710             }
711             return (AE_OK);
712
713
714         case AML_PACKAGE_OP:
715
716             /* The next op is the size or predicate parameter */
717
718             NextOp = AcpiPsGetDepthNext (NULL, Op);
719             if (NextOp)
720             {
721                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
722             }
723             return (AE_OK);
724
725
726         case AML_MATCH_OP:
727
728             AcpiDmMatchOp (Op);
729             break;
730
731
732         default:
733
734             break;
735         }
736
737         if (AcpiDmBlockType (Op) & BLOCK_BRACE)
738         {
739             AcpiOsPrintf ("\n");
740             AcpiDmIndent (Level);
741             AcpiOsPrintf ("{\n");
742         }
743     }
744
745     return (AE_OK);
746 }
747
748
749 /*******************************************************************************
750  *
751  * FUNCTION:    AcpiDmAscendingOp
752  *
753  * PARAMETERS:  ASL_WALK_CALLBACK
754  *
755  * RETURN:      Status
756  *
757  * DESCRIPTION: Second visitation of a parse object, during ascent of parse
758  *              tree.  Close out any parameter lists and complete the opcode.
759  *
760  ******************************************************************************/
761
762 ACPI_STATUS
763 AcpiDmAscendingOp (
764     ACPI_PARSE_OBJECT       *Op,
765     UINT32                  Level,
766     void                    *Context)
767 {
768     ACPI_OP_WALK_INFO       *Info = Context;
769
770
771     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
772     {
773         /* Ignore this op -- it was handled elsewhere */
774
775         return (AE_OK);
776     }
777
778     if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
779     {
780         /* Indicates the end of the current descriptor block (table) */
781
782         AcpiOsPrintf ("}\n\n");
783         return (AE_OK);
784     }
785
786     switch (AcpiDmBlockType (Op))
787     {
788     case BLOCK_PAREN:
789
790         /* Completed an op that has arguments, add closing paren */
791
792         AcpiOsPrintf (")");
793
794         /* Could be a nested operator, check if comma required */
795
796         if (!AcpiDmCommaIfListMember (Op))
797         {
798             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
799                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
800                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
801             {
802                 /* This is a first-level element of a term list, start a new line */
803
804                 AcpiOsPrintf ("\n");
805             }
806         }
807         break;
808
809
810     case BLOCK_BRACE:
811     case (BLOCK_BRACE | BLOCK_PAREN):
812
813         /* Completed an op that has a term list, add closing brace */
814
815         if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
816         {
817             AcpiOsPrintf ("}");
818         }
819         else
820         {
821             AcpiDmIndent (Level);
822             AcpiOsPrintf ("}");
823         }
824
825         AcpiDmCommaIfListMember (Op);
826
827         if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
828         {
829             AcpiOsPrintf ("\n");
830             if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
831             {
832                 if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
833                     (Op->Common.Next) &&
834                     (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
835                 {
836                     break;
837                 }
838
839                 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
840                     (!Op->Common.Next))
841                 {
842                     break;
843                 }
844                 AcpiOsPrintf ("\n");
845             }
846         }
847         break;
848
849
850     case BLOCK_NONE:
851     default:
852
853         /* Could be a nested operator, check if comma required */
854
855         if (!AcpiDmCommaIfListMember (Op))
856         {
857             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
858                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
859                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
860             {
861                 /* This is a first-level element of a term list, start a new line */
862
863                 AcpiOsPrintf ("\n");
864             }
865         }
866         else if (Op->Common.Parent)
867         {
868             switch (Op->Common.Parent->Common.AmlOpcode)
869             {
870             case AML_PACKAGE_OP:
871             case AML_VAR_PACKAGE_OP:
872
873                 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
874                 {
875                     AcpiOsPrintf ("\n");
876                 }
877                 break;
878
879             default:
880
881                 break;
882             }
883         }
884         break;
885     }
886
887     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
888     {
889         if ((Op->Common.Next) &&
890             (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
891         {
892             return (AE_OK);
893         }
894
895         /*
896          * Just completed a parameter node for something like "Buffer (param)".
897          * Close the paren and open up the term list block with a brace
898          */
899         if (Op->Common.Next)
900         {
901             AcpiOsPrintf (")\n");
902             AcpiDmIndent (Level - 1);
903             AcpiOsPrintf ("{\n");
904         }
905         else
906         {
907             Op->Common.Parent->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
908             AcpiOsPrintf (") {");
909         }
910     }
911
912     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
913         (Op->Common.AmlOpcode == AML_RETURN_OP))
914     {
915         Info->Level++;
916     }
917     return (AE_OK);
918 }
919
920
921 #endif  /* ACPI_DISASSEMBLER */