STATUS determine_shift_end_state()

in common/recipes-core/asd_1.4.7/files/daemon/asd_msg.c [1621:1757]


STATUS determine_shift_end_state(ASD_MSG* state, ScanType scan_type,
                                 struct packet_data* packet,
                                 enum jtag_states* end_state)
{
    unsigned char* next_cmd_ptr = NULL;
    unsigned char* next_cmd2_ptr = NULL;
    unsigned int next_cmd2_counter = 0;
    STATUS status;

    if (!state || !packet || !end_state)
        return ST_ERR;

    // First we will get the default end_state, to use if there are
    // no more bytes to read from the packet.
    status = JTAG_get_tap_state(state->jtag_handler, end_state);

    if (status == ST_OK)
    {
        // Peek ahead to get next command byte
        next_cmd_ptr = get_packet_data(packet, 1);
        if (next_cmd_ptr != NULL)
        {
            if (*next_cmd_ptr >= TAP_STATE_MIN &&
                *next_cmd_ptr <= TAP_STATE_MAX)
            {
                // Next command is a tap state command
                *end_state = (enum jtag_states)(*next_cmd_ptr & TAP_STATE_MASK);

                // In hardware mode, we must peek ahead for the next tap state
                // to determine the end state
                if (state->asd_cfg->jtag.mode == JTAG_DRIVER_MODE_HARDWARE)
                {
                    next_cmd2_ptr = get_packet_data(packet, 1);
                    next_cmd2_counter++;
                    while (packet->used < packet->total)
                    {
                        if (next_cmd2_ptr == NULL)
                            break;
                        if (*next_cmd2_ptr >= TAP_STATE_MIN &&
                            *next_cmd2_ptr <= TAP_STATE_MAX)
                        {
                            break;
                        }
                        else if (*next_cmd2_ptr == WRITE_EVENT_CONFIG ||
                                 *next_cmd2_ptr == DR_PREFIX ||
                                 *next_cmd2_ptr == DR_POSTFIX ||
                                 *next_cmd2_ptr == WAIT_CYCLES_TCK_DISABLE ||
                                 *next_cmd2_ptr == WAIT_CYCLES_TCK_ENABLE ||
                                 *next_cmd2_ptr == JTAG_FREQ)
                        {
                            next_cmd2_ptr = get_packet_data(packet, 1);
                            next_cmd2_counter++;
                            continue;
                        }
                        else if (*next_cmd2_ptr == IR_PREFIX ||
                                 *next_cmd2_ptr == IR_POSTFIX)
                        {
                            next_cmd2_ptr = get_packet_data(packet, 2);
                            next_cmd2_counter = next_cmd2_counter + 2;
                            continue;
                        }
                        else
                        {
                            ASD_log(ASD_LogLevel_Warning, ASD_LogStream_SDK,
                                    ASD_LogOption_None,
                                    "Not expected Next2 command 0x%x",
                                    *next_cmd2_ptr);
                            break;
                        }
                    }
                }

                if (next_cmd2_ptr)
                {
                    if (*next_cmd2_ptr >= TAP_STATE_MIN &&
                        *next_cmd2_ptr <= TAP_STATE_MAX)
                    {
                        if ((*next_cmd2_ptr & TAP_STATE_MASK) == jtag_pau_dr ||
                            (*next_cmd2_ptr & TAP_STATE_MASK) == jtag_pau_ir)
                        {
                            *end_state = (enum jtag_states)(*next_cmd2_ptr &
                                                            TAP_STATE_MASK);
#ifdef ENABLE_DEBUG_LOGGING
                            ASD_log(ASD_LogLevel_Debug, ASD_LogStream_SDK,
                                    ASD_LogOption_None,
                                    "Staying in state: 0x%02x", *end_state);
#endif
                        }
                        else if ((*next_cmd2_ptr & TAP_STATE_MASK) == jtag_rti)
                        {
                            *end_state = jtag_rti;
                        }
                    }
                }
            }
            else if (scan_type == ScanType_Read &&
                     (*next_cmd_ptr < READ_SCAN_MIN ||
                      *next_cmd_ptr > READ_SCAN_MAX))
            {
                ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
                        ASD_LogOption_None,
                        "Unexpected sequence during read scan: 0x%02x",
                        *next_cmd_ptr);
                status = ST_ERR;
            }
            else if (scan_type == ScanType_Write &&
                     (*next_cmd_ptr < WRITE_SCAN_MIN ||
                      *next_cmd_ptr > WRITE_SCAN_MAX))
            {
                ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
                        ASD_LogOption_None,
                        "Unexpected sequence during write scan: 0x%02x",
                        *next_cmd_ptr);
                status = ST_ERR;
            }
            else if (scan_type == ScanType_ReadWrite &&
                     (*next_cmd_ptr < READ_WRITE_SCAN_MIN ||
                      *next_cmd_ptr > READ_WRITE_SCAN_MAX))
            {
                ASD_log(ASD_LogLevel_Error, ASD_LogStream_SDK,
                        ASD_LogOption_None,
                        "Unexpected sequence during read write scan: 0x%02x",
                        *next_cmd_ptr);
                status = ST_ERR;
            }

            packet->next_data--; // Un-peek next_cmd_ptr
            packet->used--;
            if (next_cmd2_ptr)
            {
                packet->next_data -= next_cmd2_counter; // Un-peek next_cmd2_ptr
                packet->used -= next_cmd2_counter;
            }
        }
    }
    return status;
}