FreeBSD/sys/contrib/dev/acpica/components/dispatcher/dscontrol.c
/*******************************************************************************
 *
 * FUNCTION:    AcpiDsExecEndControlOp
 *
 * PARAMETERS:  WalkList        - The list that owns the walk stack
 *              Op              - The control Op
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handles all control ops encountered during control method
 *              execution.
 *
 ******************************************************************************/
AcpiDsExecEndControlOp
PARAMETERS:  WalkList        - The list that owns the walk stack
Op              - The control Op

Status

Handles all control ops encountered during control method
execution.
AcpiDsExecEndControlOp PARAMETERS : WalkList - The list that owns the walk stack Op - The control Op Status Handles all control ops encountered during control method execution .
ACPI_STATUS
AcpiDsExecEndControlOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_GENERIC_STATE      *ControlState;
    ACPI_FUNCTION_NAME (DsExecEndControlOp);
    switch (Op->Common.AmlOpcode)
    {
    case AML_IF_OP:
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op));
        WalkState->LastPredicate =
            (BOOLEAN) WalkState->ControlState->Common.Value;
        ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
        AcpiUtDeleteGenericState (ControlState);
        break;
    case AML_ELSE_OP:
        break;
    case AML_WHILE_OP:
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op));
        ControlState = WalkState->ControlState;
        if (ControlState->Common.Value)
        {
            ControlState->Control.LoopCount++;
            if (ControlState->Control.LoopCount > AcpiGbl_MaxLoopIterations)
            {
                Status = AE_AML_INFINITE_LOOP;
                break;
            }
            Status = AE_CTRL_PENDING;
            WalkState->AmlLastWhile =
                ControlState->Control.AmlPredicateStart;
            break;
        }
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "[WHILE_OP] termination! Op=%p\n",Op));
        ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
        AcpiUtDeleteGenericState (ControlState);
        break;
    case AML_RETURN_OP:
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg));
        if (Op->Common.Value.Arg)
        {
            AcpiDsClearImplicitReturn (WalkState);
            Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
            Status = AcpiExResolveToValue (
                &WalkState->Operands [0], WalkState);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
            WalkState->ReturnDesc = WalkState->Operands[0];
        }
        else if (WalkState->ResultCount)
        {
            AcpiDsClearImplicitReturn (WalkState);
            if ((ACPI_GET_DESCRIPTOR_TYPE (WalkState->Results->Results.ObjDesc[0]) ==
                    ACPI_DESC_TYPE_OPERAND) &&
                ((WalkState->Results->Results.ObjDesc [0])->Common.Type ==
                    ACPI_TYPE_LOCAL_REFERENCE) &&
                ((WalkState->Results->Results.ObjDesc [0])->Reference.Class !=
                    ACPI_REFCLASS_INDEX))
            {
                Status = AcpiExResolveToValue (
                    &WalkState->Results->Results.ObjDesc [0], WalkState);
                if (ACPI_FAILURE (Status))
                {
                    return (Status);
                }
            }
            WalkState->ReturnDesc = WalkState->Results->Results.ObjDesc [0];
        }
        else
        {
            if (WalkState->NumOperands)
            {
                AcpiUtRemoveReference (WalkState->Operands [0]);
            }
            WalkState->Operands[0] = NULL;
            WalkState->NumOperands = 0;
            WalkState->ReturnDesc = NULL;
        }
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "Completed RETURN_OP State=%p, RetVal=%p\n",
            WalkState, WalkState->ReturnDesc));
        Status = AE_CTRL_TERMINATE;
        break;
    case AML_NOOP_OP:
        break;
    case AML_BREAK_POINT_OP:
        AcpiDbSignalBreakPoint (WalkState);
        Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT,
            "Executed AML Breakpoint opcode");
        break;
    case AML_BREAK_OP:
    case AML_CONTINUE_OP: 
        while (WalkState->ControlState &&
                (WalkState->ControlState->Control.Opcode != AML_WHILE_OP))
        {
            ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
            AcpiUtDeleteGenericState (ControlState);
        }
        if (!WalkState->ControlState)
        {
            return (AE_AML_NO_WHILE);
        }
        WalkState->AmlLastWhile =
            WalkState->ControlState->Control.PackageEnd;
        if (Op->Common.AmlOpcode == AML_BREAK_OP)
        {
            Status = AE_CTRL_BREAK;
        }
        else
        {
            Status = AE_CTRL_CONTINUE;
        }
        break;
    default:
        ACPI_ERROR ((AE_INFO, "Unknown control opcode=0x%X Op=%p",
            Op->Common.AmlOpcode, Op));
        Status = AE_AML_BAD_OPCODE;
        break;
    }
    return (Status);
}
ACPI_STATUS AcpiDsExecEndControlOp ( ACPI_WALK_STATE * WalkState , ACPI_PARSE_OBJECT * Op ) { ACPI_STATUS Status = AE_OK ; ACPI_GENERIC_STATE * ControlState ; ACPI_FUNCTION_NAME ( DsExecEndControlOp ) ; switch ( Op -> Common . AmlOpcode ) { case AML_IF_OP : ACPI_DEBUG_PRINT ( ( ACPI_DB_DISPATCH , " \n " , Op ) ) ; WalkState -> LastPredicate = ( BOOLEAN ) WalkState -> ControlState -> Common . Value ; ControlState = AcpiUtPopGenericState ( & WalkState -> ControlState ) ; AcpiUtDeleteGenericState ( ControlState ) ; break ; case AML_ELSE_OP : break ; case AML_WHILE_OP : ACPI_DEBUG_PRINT ( ( ACPI_DB_DISPATCH , " \n " , Op ) ) ; ControlState = WalkState -> ControlState ; if ( ControlState -> Common . Value ) { ControlState -> Control . LoopCount ++ ; if ( ControlState -> Control . LoopCount > AcpiGbl_MaxLoopIterations ) { Status = AE_AML_INFINITE_LOOP ; break ; } Status = AE_CTRL_PENDING ; WalkState -> AmlLastWhile = ControlState -> Control . AmlPredicateStart ; break ; } ACPI_DEBUG_PRINT ( ( ACPI_DB_DISPATCH , " \n " , Op ) ) ; ControlState = AcpiUtPopGenericState ( & WalkState -> ControlState ) ; AcpiUtDeleteGenericState ( ControlState ) ; break ; case AML_RETURN_OP : ACPI_DEBUG_PRINT ( ( ACPI_DB_DISPATCH , " \n " , Op , Op -> Common . Value . Arg ) ) ; if ( Op -> Common . Value . Arg ) { AcpiDsClearImplicitReturn ( WalkState ) ; Status = AcpiDsCreateOperands ( WalkState , Op -> Common . Value . Arg ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } Status = AcpiExResolveToValue ( & WalkState -> Operands [ 0 ] , WalkState ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } WalkState -> ReturnDesc = WalkState -> Operands [ 0 ] ; } else if ( WalkState -> ResultCount ) { AcpiDsClearImplicitReturn ( WalkState ) ; if ( ( ACPI_GET_DESCRIPTOR_TYPE ( WalkState -> Results -> Results . ObjDesc [ 0 ] ) == ACPI_DESC_TYPE_OPERAND ) && ( ( WalkState -> Results -> Results . ObjDesc [ 0 ] ) -> Common . Type == ACPI_TYPE_LOCAL_REFERENCE ) && ( ( WalkState -> Results -> Results . ObjDesc [ 0 ] ) -> Reference . Class != ACPI_REFCLASS_INDEX ) ) { Status = AcpiExResolveToValue ( & WalkState -> Results -> Results . ObjDesc [ 0 ] , WalkState ) ; if ( ACPI_FAILURE ( Status ) ) { return ( Status ) ; } } WalkState -> ReturnDesc = WalkState -> Results -> Results . ObjDesc [ 0 ] ; } else { if ( WalkState -> NumOperands ) { AcpiUtRemoveReference ( WalkState -> Operands [ 0 ] ) ; } WalkState -> Operands [ 0 ] = NULL ; WalkState -> NumOperands = 0 ; WalkState -> ReturnDesc = NULL ; } ACPI_DEBUG_PRINT ( ( ACPI_DB_DISPATCH , " \n " , WalkState , WalkState -> ReturnDesc ) ) ; Status = AE_CTRL_TERMINATE ; break ; case AML_NOOP_OP : break ; case AML_BREAK_POINT_OP : AcpiDbSignalBreakPoint ( WalkState ) ; Status = AcpiOsSignal ( ACPI_SIGNAL_BREAKPOINT , " " ) ; break ; case AML_BREAK_OP : case AML_CONTINUE_OP : while ( WalkState -> ControlState && ( WalkState -> ControlState -> Control . Opcode != AML_WHILE_OP ) ) { ControlState = AcpiUtPopGenericState ( & WalkState -> ControlState ) ; AcpiUtDeleteGenericState ( ControlState ) ; } if ( ! WalkState -> ControlState ) { return ( AE_AML_NO_WHILE ) ; } WalkState -> AmlLastWhile = WalkState -> ControlState -> Control . PackageEnd ; if ( Op -> Common . AmlOpcode == AML_BREAK_OP ) { Status = AE_CTRL_BREAK ; } else { Status = AE_CTRL_CONTINUE ; } break ; default : ACPI_ERROR ( ( AE_INFO , " " , Op -> Common . AmlOpcode , Op ) ) ; Status = AE_AML_BAD_OPCODE ; break ; } return ( Status ) ; }
FUNCTION:    AcpiDsExecEndControlOp
 PARAMETERS:  WalkList        - The list that owns the walk stack
              Op              - The control Op
FUNCTION : AcpiDsExecEndControlOp PARAMETERS : WalkList - The list that owns the walk stack Op - The control Op
/*
         * Save the result of the predicate in case there is an
         * ELSE to come
         */ /*
         * Pop the control state that was created at the start
         * of the IF and free it
         */ /* Predicate was true, the body of the loop was just executed */ /*
             * This loop counter mechanism allows the interpreter to escape
             * possibly infinite loops. This can occur in poorly written AML
             * when the hardware does not respond within a while loop and the
             * loop does not implement a timeout.
             */ /*
             * Go back and evaluate the predicate and maybe execute the loop
             * another time
             */ /* Predicate was false, terminate this while loop */ /* Pop this control state and free it */ /*
         * One optional operand -- the return value
         * It can be either an immediate operand or a result that
         * has been bubbled up the tree
         */ /* Since we have a real Return(), delete any implicit return */ /* Return statement has an immediate operand */ /*
             * If value being returned is a Reference (such as
             * an arg or local), resolve it now because it may
             * cease to exist at the end of the method.
             */ /*
             * Get the return value and save as the last result
             * value. This is the only place where WalkState->ReturnDesc
             * is set to anything other than zero!
             */ /* Since we have a real Return(), delete any implicit return */ /*
             * The return value has come from a previous calculation.
             *
             * If value being returned is a Reference (such as
             * an arg or local), resolve it now because it may
             * cease to exist at the end of the method.
             *
             * Allow references created by the Index operator to return
             * unchanged.
             */ /* No return operand */ /* End the control method execution right now */ /* Just do nothing! */ /* Call to the OSL in case OS wants a piece of the action */ /* ACPI 2.0 */ /* Pop and delete control states until we find a while */ /* No while found? */ /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */ /* Return status depending on opcode */