svf: fix warnings
[openocd.git] / src / svf / svf.c
index 3cad4c7e96e0970725345755652b75064273553a..936a0242675dbdaa48a7b2550f1a370a7313ab48 100644 (file)
@@ -1,22 +1,21 @@
-/***************************************************************************
- *      Copyright (C) 2009 by Simon Qian                                                                          *
- *      SimonQian@SimonQian.com                                                                                           *
- *                                                                         *
- *      This program is free software; you can redistribute it and/or modify  *
- *      it under the terms of the GNU General Public License as published by  *
- *      the Free Software Foundation; either version 2 of the License, or         *
- *      (at your option) any later version.                                                               *
- *                                                                                                                                                *
- *      This program is distributed in the hope that it will be useful,           *
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of            *
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
- *      GNU General Public License for more details.                                              *
- *                                                                                                                                                *
- *      You should have received a copy of the GNU General Public License         *
- *      along with this program; if not, write to the                                             *
- *      Free Software Foundation, Inc.,                                                                           *
- *      59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                         *
- ***************************************************************************/
+/*
+ * Copyright (C) 2009 by Simon Qian
+ * SimonQian@SimonQian.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
 
 
 /* The specification for SVF is available here:
@@ -32,9 +31,9 @@
 #include "config.h"
 #endif
 
+#include <jtag/jtag.h>
 #include "svf.h"
-#include "jtag.h"
-#include "time_support.h"
+#include <helper/time_support.h>
 
 
 // SVF command
@@ -56,7 +55,7 @@ typedef enum
        TRST,
 }svf_command_t;
 
-const char *svf_command_name[14] =
+static const char *svf_command_name[14] =
 {
        "ENDDR",
        "ENDIR",
@@ -82,7 +81,7 @@ typedef enum
        TRST_ABSENT
 }trst_mode_t;
 
-const char *svf_trst_mode_name[4] =
+static const char *svf_trst_mode_name[4] =
 {
        "ON",
        "OFF",
@@ -90,23 +89,69 @@ const char *svf_trst_mode_name[4] =
        "ABSENT"
 };
 
-char *svf_tap_state_name[TAP_NUM_STATES];
+struct svf_statemove
+{
+       tap_state_t from;
+       tap_state_t to;
+       uint32_t num_of_moves;
+       tap_state_t paths[8];
+};
+
+/*
+ * These paths are from the SVF specification for the STATE command, to be
+ * used when the STATE command only includes the final state.  The first
+ * element of the path is the "from" (current) state, and the last one is
+ * the "to" (target) state.
+ *
+ * All specified paths are the shortest ones in the JTAG spec, and are thus
+ * not (!!) exact matches for the paths used elsewhere in OpenOCD.  Note
+ * that PAUSE-to-PAUSE transitions all go through UPDATE and then CAPTURE,
+ * which has specific effects on the various registers; they are not NOPs.
+ *
+ * Paths to RESET are disabled here.  As elsewhere in OpenOCD, and in XSVF
+ * and many SVF implementations, we don't want to risk missing that state.
+ * To get to RESET, always we ignore the current state.
+ */
+static const struct svf_statemove svf_statemoves[] =
+{
+       // from                 to                              num_of_moves,   paths[8]
+//     {TAP_RESET,             TAP_RESET,              1,                              {TAP_RESET}},
+       {TAP_RESET,             TAP_IDLE,               2,                              {TAP_RESET, TAP_IDLE}},
+       {TAP_RESET,             TAP_DRPAUSE,    6,                              {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+       {TAP_RESET,             TAP_IRPAUSE,    7,                              {TAP_RESET, TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
+
+//     {TAP_IDLE,              TAP_RESET,              4,                              {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
+       {TAP_IDLE,              TAP_IDLE,               1,                              {TAP_IDLE}},
+       {TAP_IDLE,              TAP_DRPAUSE,    5,                              {TAP_IDLE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+       {TAP_IDLE,              TAP_IRPAUSE,    6,                              {TAP_IDLE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
+
+//     {TAP_DRPAUSE,   TAP_RESET,              6,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
+       {TAP_DRPAUSE,   TAP_IDLE,               4,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE}},
+       {TAP_DRPAUSE,   TAP_DRPAUSE,    7,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+       {TAP_DRPAUSE,   TAP_IRPAUSE,    8,                              {TAP_DRPAUSE, TAP_DREXIT2, TAP_DRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}},
+
+//     {TAP_IRPAUSE,   TAP_RESET,              6,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_RESET}},
+       {TAP_IRPAUSE,   TAP_IDLE,               4,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_IDLE}},
+       {TAP_IRPAUSE,   TAP_DRPAUSE,    7,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_DRCAPTURE, TAP_DREXIT1, TAP_DRPAUSE}},
+       {TAP_IRPAUSE,   TAP_IRPAUSE,    8,                              {TAP_IRPAUSE, TAP_IREXIT2, TAP_IRUPDATE, TAP_DRSELECT, TAP_IRSELECT, TAP_IRCAPTURE, TAP_IREXIT1, TAP_IRPAUSE}}
+};
+
 
 #define XXR_TDI                                                (1 << 0)
 #define XXR_TDO                                                (1 << 1)
 #define XXR_MASK                                       (1 << 2)
 #define XXR_SMASK                                      (1 << 3)
-typedef struct
+struct svf_xxr_para
 {
        int len;
        int data_mask;
-       u8 *tdi;
-       u8 *tdo;
-       u8 *mask;
-       u8 *smask;
-}svf_xxr_para_t;
+       uint8_t *tdi;
+       uint8_t *tdo;
+       uint8_t *mask;
+       uint8_t *smask;
+};
 
-typedef struct
+struct svf_para
 {
        float frequency;
        tap_state_t ir_end_state;
@@ -115,16 +160,16 @@ typedef struct
        tap_state_t runtest_end_state;
        trst_mode_t trst_mode;
 
-       svf_xxr_para_t hir_para;
-       svf_xxr_para_t hdr_para;
-       svf_xxr_para_t tir_para;
-       svf_xxr_para_t tdr_para;
-       svf_xxr_para_t sir_para;
-       svf_xxr_para_t sdr_para;
-}svf_para_t;
+       struct svf_xxr_para hir_para;
+       struct svf_xxr_para hdr_para;
+       struct svf_xxr_para tir_para;
+       struct svf_xxr_para tdr_para;
+       struct svf_xxr_para sir_para;
+       struct svf_xxr_para sdr_para;
+};
 
-svf_para_t svf_para;
-const svf_para_t svf_para_init =
+static struct svf_para svf_para;
+static const struct svf_para svf_para_init =
 {
 //     frequency,      ir_end_state,   dr_end_state,   runtest_run_state,      runtest_end_state,      trst_mode
        0,                      TAP_IDLE,               TAP_IDLE,               TAP_IDLE,                       TAP_IDLE,                       TRST_Z,
@@ -148,50 +193,49 @@ const svf_para_t svf_para_init =
        {0,             0,                      NULL,   NULL,   NULL,   NULL},
 };
 
-typedef struct
+struct svf_check_tdo_para
 {
        int line_num;           // used to record line number of the check operation
                                                // so more information could be printed
        int enabled;            // check is enabled or not
        int buffer_offset;      // buffer_offset to buffers
        int bit_len;            // bit length to check
-}svf_check_tdo_para_t;
+};
 
 #define SVF_CHECK_TDO_PARA_SIZE        1024
-static svf_check_tdo_para_t *svf_check_tdo_para = NULL;
+static struct svf_check_tdo_para *svf_check_tdo_para = NULL;
 static int svf_check_tdo_para_index = 0;
 
-#define dimof(a)                                       (sizeof(a) / sizeof((a)[0]))
-
-static int svf_read_command_from_file(int fd);
+static int svf_read_command_from_file(FILE * fd);
 static int svf_check_tdo(void);
-static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len);
-static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str);
-static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len);
+static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str);
 
-static int svf_fd = 0;
+static FILE * svf_fd = NULL;
+static char * svf_read_line = NULL;
+static size_t svf_read_line_size = 0;
 static char *svf_command_buffer = NULL;
-static int svf_command_buffer_size = 0;
+static size_t svf_command_buffer_size = 0;
 static int svf_line_number = 1;
+static int svf_getline (char **lineptr, size_t *n, FILE *stream);
 
-static jtag_tap_t *tap = NULL;
-static tap_state_t last_state = TAP_RESET;
-
-#define SVF_MAX_BUFFER_SIZE_TO_COMMIT  (4 * 1024)
-static u8 *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
+#define SVF_MAX_BUFFER_SIZE_TO_COMMIT  (1024 * 1024)
+static uint8_t *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
 static int svf_buffer_index = 0, svf_buffer_size = 0;
 static int svf_quiet = 0;
+static int svf_nil = 0;
 
+// Targetting particular tap
+static int svf_tap_is_specified = 0;
+static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi);
 
-int svf_register_commands(struct command_context_s *cmd_ctx)
-{
-       register_command(cmd_ctx, NULL, "svf", handle_svf_command,
-               COMMAND_EXEC, "run svf <file>");
+// Progress Indicator
+static int svf_progress_enabled = 0;
+static long svf_total_lines = 0;
+static int svf_percentage = 0;
+static int svf_last_printed_percentage = -1;
 
-       return ERROR_OK;
-}
-
-void svf_free_xxd_para(svf_xxr_para_t *para)
+static void svf_free_xxd_para(struct svf_xxr_para *para)
 {
        if (NULL != para)
        {
@@ -218,55 +262,137 @@ void svf_free_xxd_para(svf_xxr_para_t *para)
        }
 }
 
-static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static unsigned svf_get_mask_u32(int bitlen)
+{
+       uint32_t bitmask;
+
+       if (bitlen < 0)
+       {
+               bitmask = 0;
+       }
+       else if (bitlen >= 32)
+       {
+               bitmask = 0xFFFFFFFF;
+       }
+       else
+       {
+               bitmask = (1 << bitlen) - 1;
+       }
+
+       return bitmask;
+}
+
+int svf_add_statemove(tap_state_t state_to)
+{
+       tap_state_t state_from = cmd_queue_cur_state;
+       unsigned index_var;
+
+       /* when resetting, be paranoid and ignore current state */
+       if (state_to == TAP_RESET) {
+               if (svf_nil)
+                       return ERROR_OK;
+
+               jtag_add_tlr();
+               return ERROR_OK;
+       }
+
+       for (index_var = 0; index_var < ARRAY_SIZE(svf_statemoves); index_var++)
+       {
+               if ((svf_statemoves[index_var].from == state_from)
+                       && (svf_statemoves[index_var].to == state_to))
+               {
+                       if (svf_nil)
+                       {
+                               continue;
+                       }
+                       /* recorded path includes current state ... avoid extra TCKs! */
+                       if (svf_statemoves[index_var].num_of_moves > 1)
+                               jtag_add_pathmove(svf_statemoves[index_var].num_of_moves - 1,
+                                               svf_statemoves[index_var].paths + 1);
+                       else
+                               jtag_add_pathmove(svf_statemoves[index_var].num_of_moves,
+                                               svf_statemoves[index_var].paths);
+                       return ERROR_OK;
+               }
+       }
+       LOG_ERROR("SVF: can not move to %s", tap_state_name(state_to));
+       return ERROR_FAIL;
+}
+
+COMMAND_HANDLER(handle_svf_command)
 {
-#define SVF_NUM_OF_OPTIONS                     1
-       int command_num = 0, i;
+#define SVF_MIN_NUM_OF_OPTIONS                 1
+#define SVF_MAX_NUM_OF_OPTIONS                 5
+       int command_num = 0;
        int ret = ERROR_OK;
-       long long time_ago;
+       long long time_measure_ms;
+       int time_measure_s, time_measure_m;
+
+       /* use NULL to indicate a "plain" svf file which accounts for
+          any additional devices in the scan chain, otherwise the device
+          that should be affected
+       */
+       struct jtag_tap *tap = NULL;
 
-       if ((argc < 1) || (argc > (1 + SVF_NUM_OF_OPTIONS)))
+       if ((CMD_ARGC < SVF_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > SVF_MAX_NUM_OF_OPTIONS))
        {
-               command_print(cmd_ctx, "usage: svf <file> [quiet]");
-               return ERROR_FAIL;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       // parse variant
+       // parse command line
        svf_quiet = 0;
-       for (i = 1; i < argc; i++)
+       svf_nil = 0;
+       for (unsigned int i = 0; i < CMD_ARGC; i++)
        {
-               if (!strcmp(args[i], "quiet"))
+               if (strcmp(CMD_ARGV[i], "-tap") == 0)
+               {
+                       tap = jtag_tap_by_string(CMD_ARGV[i+1]);
+                       if (!tap)
+                       {
+                               command_print(CMD_CTX, "Tap: %s unknown", CMD_ARGV[i+1]);
+                               return ERROR_FAIL;
+                       }
+                       i++;
+               }
+               else if ((strcmp(CMD_ARGV[i], "quiet") == 0) || (strcmp(CMD_ARGV[i], "-quiet") == 0))
                {
                        svf_quiet = 1;
                }
-               else
+               else if ((strcmp(CMD_ARGV[i], "nil") == 0) || (strcmp(CMD_ARGV[i], "-nil") == 0))
                {
-                       LOG_ERROR("unknown variant for svf: %s", args[i]);
-
+                       svf_nil = 1;
+               }
+               else if ((strcmp(CMD_ARGV[i], "progress") == 0) || (strcmp(CMD_ARGV[i], "-progress") == 0))
+               {
+                       svf_progress_enabled = 1;
+               }
+               else if ((svf_fd = fopen(CMD_ARGV[i], "r")) == NULL)
+               {
+                       int err = errno;
+                       command_print(CMD_CTX, "open(\"%s\"): %s", CMD_ARGV[i], strerror(err));
                        // no need to free anything now
-                       return ERROR_FAIL;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+               else
+               {
+                       LOG_USER("svf processing file: \"%s\"", CMD_ARGV[i]);
                }
        }
 
-       if ((svf_fd = open(args[0], O_RDONLY)) < 0)
+       if (svf_fd == NULL)
        {
-               command_print(cmd_ctx, "file \"%s\" not found", args[0]);
-
-               // no need to free anything now
-               return ERROR_FAIL;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       LOG_USER("svf processing file: \"%s\"", args[0]);
-
        // get time
-       time_ago = timeval_ms();
+       time_measure_ms = timeval_ms();
 
        // init
        svf_line_number = 1;
        svf_command_buffer_size = 0;
 
        svf_check_tdo_para_index = 0;
-       svf_check_tdo_para = malloc(sizeof(svf_check_tdo_para_t) * SVF_CHECK_TDO_PARA_SIZE);
+       svf_check_tdo_para = malloc(sizeof(struct svf_check_tdo_para) * SVF_CHECK_TDO_PARA_SIZE);
        if (NULL == svf_check_tdo_para)
        {
                LOG_ERROR("not enough memory");
@@ -276,24 +402,24 @@ static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char
 
        svf_buffer_index = 0;
        // double the buffer size
-       // in case current command cannot be commited, and next command is a bit scan command
+       // in case current command cannot be committed, and next command is a bit scan command
        // here is 32K bits for this big scan command, it should be enough
        // buffer will be reallocated if buffer size is not enough
-       svf_tdi_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT);
+       svf_tdi_buffer = (uint8_t *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT);
        if (NULL == svf_tdi_buffer)
        {
                LOG_ERROR("not enough memory");
                ret = ERROR_FAIL;
                goto free_all;
        }
-       svf_tdo_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT);
+       svf_tdo_buffer = (uint8_t *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT);
        if (NULL == svf_tdo_buffer)
        {
                LOG_ERROR("not enough memory");
                ret = ERROR_FAIL;
                goto free_all;
        }
-       svf_mask_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT);
+       svf_mask_buffer = (uint8_t *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT);
        if (NULL == svf_mask_buffer)
        {
                LOG_ERROR("not enough memory");
@@ -303,16 +429,105 @@ static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char
        svf_buffer_size = 2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT;
 
        memcpy(&svf_para, &svf_para_init, sizeof(svf_para));
-       for (i = 0; i < (int)dimof(svf_tap_state_name); i++)
+
+       if (!svf_nil)
        {
-               svf_tap_state_name[i] = (char *)tap_state_name(i);
+               // TAP_RESET
+               jtag_add_tlr();
+       }
+
+       if (tap)
+       {
+               /* Tap is specified, set header/trailer paddings */
+               int header_ir_len = 0, header_dr_len = 0, trailer_ir_len = 0, trailer_dr_len = 0;
+               struct jtag_tap *check_tap;
+
+               svf_tap_is_specified = 1;
+
+               for (check_tap = jtag_all_taps(); check_tap; check_tap = check_tap->next_tap) {
+                       if (check_tap->abs_chain_position < tap->abs_chain_position)
+                       {
+                               //Header
+                               header_ir_len += check_tap->ir_length;
+                               header_dr_len ++;
+                       }
+                       else if (check_tap->abs_chain_position > tap->abs_chain_position)
+                       {
+                               //Trailer
+                               trailer_ir_len += check_tap->ir_length;
+                               trailer_dr_len ++;
+                       }
+               }
+
+               // HDR %d TDI (0)
+               if (ERROR_OK != svf_set_padding(&svf_para.hdr_para, header_dr_len, 0))
+               {
+                       LOG_ERROR("failed to set data header");
+                       return ERROR_FAIL;
+               }
+
+               // HIR %d TDI (0xFF)
+               if (ERROR_OK != svf_set_padding(&svf_para.hir_para, header_ir_len, 0xFF))
+               {
+                       LOG_ERROR("failed to set instruction header");
+                       return ERROR_FAIL;
+               }
+
+               // TDR %d TDI (0)
+               if (ERROR_OK != svf_set_padding(&svf_para.tdr_para, trailer_dr_len, 0))
+               {
+                       LOG_ERROR("failed to set data trailer");
+                       return ERROR_FAIL;
+               }
+
+               // TIR %d TDI (0xFF)
+               if (ERROR_OK != svf_set_padding(&svf_para.tir_para, trailer_ir_len, 0xFF))
+               {
+                       LOG_ERROR("failed to set instruction trailer");
+                       return ERROR_FAIL;
+               }
+
        }
-       // TAP_RESET
-       jtag_add_tlr();
 
-       while ( ERROR_OK == svf_read_command_from_file(svf_fd) )
+       if (svf_progress_enabled)
        {
-               if (ERROR_OK != svf_run_command(cmd_ctx, svf_command_buffer))
+               // Count total lines in file.
+               while ( ! feof (svf_fd) )
+                {
+                  svf_getline (&svf_command_buffer, &svf_command_buffer_size, svf_fd);
+                  svf_total_lines++;
+                }
+               rewind(svf_fd);
+       }
+       while (ERROR_OK == svf_read_command_from_file(svf_fd))
+       {
+               // Log Output
+               if (svf_quiet)
+               {
+                       if (svf_progress_enabled)
+                       {
+                               svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5;
+                               if (svf_last_printed_percentage != svf_percentage)
+                               {
+                                       LOG_USER_N("\r%d%%    ", svf_percentage);
+                                       svf_last_printed_percentage = svf_percentage;
+                               }
+                       }
+               }
+               else
+               {
+                       if (svf_progress_enabled)
+                       {
+                               svf_percentage = ((svf_line_number * 20) / svf_total_lines) * 5;
+                               LOG_USER_N("%3d%%  %s", svf_percentage, svf_read_line);
+                       }
+                       else
+                       {
+                               LOG_USER_N("%s",svf_read_line);
+                       }
+               }
+                       // Run Command
+               if (ERROR_OK != svf_run_command(CMD_CTX, svf_command_buffer))
                {
                        LOG_ERROR("fail to run command at line %d", svf_line_number);
                        ret = ERROR_FAIL;
@@ -320,7 +535,8 @@ static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char
                }
                command_num++;
        }
-       if (ERROR_OK != jtag_execute_queue())
+
+       if ((!svf_nil) && (ERROR_OK != jtag_execute_queue()))
        {
                ret = ERROR_FAIL;
        }
@@ -330,11 +546,19 @@ static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char
        }
 
        // print time
-       command_print(cmd_ctx, "%lld ms used", timeval_ms() - time_ago);
+       time_measure_ms = timeval_ms() - time_measure_ms;
+       time_measure_s = time_measure_ms / 1000;
+       time_measure_ms %= 1000;
+       time_measure_m = time_measure_s / 60;
+       time_measure_s %= 60;
+       if (time_measure_ms < 1000)
+       {
+               command_print(CMD_CTX, "\r\nTime used: %dm%ds%lldms ", time_measure_m, time_measure_s, time_measure_ms);
+       }
 
 free_all:
 
-       close(svf_fd);
+       fclose(svf_fd);
        svf_fd = 0;
 
        // free buffers
@@ -377,76 +601,142 @@ free_all:
 
        if (ERROR_OK == ret)
        {
-               command_print(cmd_ctx, "svf file programmed successfully for %d commands", command_num);
+               command_print(CMD_CTX, "svf file programmed successfully for %d commands", command_num);
        }
        else
        {
-               command_print(cmd_ctx, "svf file programmed failed");
+               command_print(CMD_CTX, "svf file programmed failed");
        }
 
        return ret;
 }
 
+static int svf_getline (char **lineptr, size_t *n, FILE *stream)
+{
+#define MIN_CHUNK 16   //Buffer is increased by this size each time as required
+  size_t i = 0;
+
+  if (*lineptr == NULL)
+    {
+      *n = MIN_CHUNK;
+      *lineptr = (char *)malloc (*n);
+      if (!*lineptr)
+        {
+                 return -1;
+        }
+    }
+
+       (*lineptr)[0] = fgetc(stream);
+       while ((*lineptr)[i] != '\n')
+       {
+               (*lineptr)[++i] = fgetc(stream);
+               if (feof(stream))
+               {
+                       (*lineptr)[0] = 0;
+                       return -1;
+               }
+               if ((i + 2) > *n)
+               {
+                       *n += MIN_CHUNK;
+                       *lineptr = realloc(*lineptr, *n);
+               }
+       }
+
+       (*lineptr)[++i] = 0;
+
+       return sizeof(*lineptr);
+}
+
 #define SVFP_CMD_INC_CNT                       1024
-static int svf_read_command_from_file(int fd)
+static int svf_read_command_from_file(FILE * fd)
 {
-       char ch, *tmp_buffer = NULL;
-       int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
+       unsigned char ch;
+       int i = 0;
+       size_t cmd_pos = 0;
+       int cmd_ok = 0, slash = 0;
 
-       while (!cmd_ok && (read(fd, &ch, 1) > 0) )
+       if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+       {
+               return ERROR_FAIL;
+       }
+       svf_line_number++;
+       ch = svf_read_line[0];
+       while (!cmd_ok && (ch != 0))
        {
-               switch(ch)
+               switch (ch)
                {
                case '!':
                        slash = 0;
-                       comment = 1;
+                       if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+                       {
+                               return ERROR_FAIL;
+                       }
+                       svf_line_number++;
+                       i = -1;
                        break;
                case '/':
                        if (++slash == 2)
                        {
-                               comment = 1;
+                               slash = 0;
+                               if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+                               {
+                                       return ERROR_FAIL;
+                               }
+                               svf_line_number++;
+                               i = -1;
                        }
                        break;
                case ';':
                        slash = 0;
-                       if (!comment)
-                       {
-                               cmd_ok = 1;
-                       }
+                       cmd_ok = 1;
                        break;
                case '\n':
                        svf_line_number++;
+                       if (svf_getline (&svf_read_line, &svf_read_line_size, svf_fd) <= 0)
+                       {
+                               return ERROR_FAIL;
+                       }
+                       i = -1;
                case '\r':
                        slash = 0;
-                       comment = 0;
-                       break;
+                       /* Don't save '\r' and '\n' if no data is parsed */
+                       if (!cmd_pos)
+                               break;
                default:
-                       if (!comment)
+                       /* The parsing code currently expects a space
+                        * before parentheses -- "TDI (123)".  Also a
+                        * space afterwards -- "TDI (123) TDO(456)".
+                        * But such spaces are optional... instead of
+                        * parser updates, cope with that by adding the
+                        * spaces as needed.
+                        *
+                        * Ensure there are 3 bytes available, for:
+                        *  - current character
+                        *  - added space.
+                        *  - terminating NUL ('\0')
+                        */
+                       if ((cmd_pos + 2) >= svf_command_buffer_size)
                        {
-                               if (cmd_pos >= svf_command_buffer_size - 1)
+                               svf_command_buffer = realloc(svf_command_buffer, (cmd_pos + 2));
+                               if (svf_command_buffer == NULL)
                                {
-                                       tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT);         // 1 more byte for '\0'
-                                       if (NULL == tmp_buffer)
-                                       {
-                                               LOG_ERROR("not enough memory");
-                                               return ERROR_FAIL;
-                                       }
-                                       if (svf_command_buffer_size > 0)
-                                       {
-                                               memcpy(tmp_buffer, svf_command_buffer, svf_command_buffer_size);
-                                       }
-                                       if (svf_command_buffer != NULL)
-                                       {
-                                               free(svf_command_buffer);
-                                       }
-                                       svf_command_buffer = tmp_buffer;
-                                       svf_command_buffer_size += SVFP_CMD_INC_CNT;
-                                       tmp_buffer = NULL;
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
                                }
-                               svf_command_buffer[cmd_pos++] = (char)toupper(ch);
                        }
+
+                       /* insert a space before '(' */
+                       if ('(' == ch)
+                               svf_command_buffer[cmd_pos++] = ' ';
+
+                       svf_command_buffer[cmd_pos++] = (char)toupper(ch);
+
+                       /* insert a space after ')' */
+                       if (')' == ch)
+                               svf_command_buffer[cmd_pos++] = ' ';
                        break;
                }
+               ch = svf_read_line[++i];
        }
 
        if (cmd_ok)
@@ -462,25 +752,30 @@ static int svf_read_command_from_file(int fd)
 
 static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
 {
-       int pos = 0, num = 0, space_found = 1;
+       int pos = 0, num = 0, space_found = 1, in_bracket = 0;
 
        while (pos < len)
        {
-               switch(str[pos])
+               switch (str[pos])
                {
-               case '\n':
-               case '\r':
                case '!':
                case '/':
                        LOG_ERROR("fail to parse svf command");
                        return ERROR_FAIL;
-                       break;
-               case ' ':
-                       space_found = 1;
-                       str[pos] = '\0';
-                       break;
+               case '(':
+                       in_bracket = 1;
+                       goto parse_char;
+               case ')':
+                       in_bracket = 0;
+                       goto parse_char;
                default:
-                       if (space_found)
+parse_char:
+                       if (!in_bracket && isspace((int) str[pos]))
+                       {
+                               space_found = 1;
+                               str[pos] = '\0';
+                       }
+                       else if (space_found)
                        {
                                argus[num++] = &str[pos];
                                space_found = 0;
@@ -495,14 +790,10 @@ static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_ar
        return ERROR_OK;
 }
 
-static int svf_tap_state_is_stable(tap_state_t state)
+bool svf_tap_state_is_stable(tap_state_t state)
 {
-       return ((TAP_RESET == state) || (TAP_IDLE == state) || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state));
-}
-
-static int svf_tap_state_is_valid(tap_state_t state)
-{
-       return state >= 0 && state < TAP_NUM_STATES;
+       return (TAP_RESET == state) || (TAP_IDLE == state)
+                       || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state);
 }
 
 static int svf_find_string_in_array(char *str, char **strs, int num_of_element)
@@ -519,7 +810,7 @@ static int svf_find_string_in_array(char *str, char **strs, int num_of_element)
        return 0xFF;
 }
 
-static int svf_adjust_array_length(u8 **arr, int orig_bit_len, int new_bit_len)
+static int svf_adjust_array_length(uint8_t **arr, int orig_bit_len, int new_bit_len)
 {
        int new_byte_len = (new_bit_len + 7) >> 3;
 
@@ -530,7 +821,7 @@ static int svf_adjust_array_length(u8 **arr, int orig_bit_len, int new_bit_len)
                        free(*arr);
                        *arr = NULL;
                }
-               *arr = (u8*)malloc(new_byte_len);
+               *arr = (uint8_t*)malloc(new_byte_len);
                if (NULL == *arr)
                {
                        LOG_ERROR("not enough memory");
@@ -541,10 +832,23 @@ static int svf_adjust_array_length(u8 **arr, int orig_bit_len, int new_bit_len)
        return ERROR_OK;
 }
 
-static int svf_copy_hexstring_to_binary(char *str, u8 **bin, int orig_bit_len, int bit_len)
+static int svf_set_padding(struct svf_xxr_para *para, int len, unsigned char tdi)
+{
+       int error = ERROR_OK;
+       error |= svf_adjust_array_length(&para->tdi, para->len, len);
+       memset(para->tdi, tdi, (len + 7) >> 3);
+       error |= svf_adjust_array_length(&para->tdo, para->len, len);
+       error |= svf_adjust_array_length(&para->mask, para->len, len);
+       para->len = len;
+       para->data_mask = XXR_TDI;
+
+       return error;
+}
+
+static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_len, int bit_len)
 {
-       int i, str_len = strlen(str), str_byte_len = (bit_len + 3) >> 2, loop_cnt;
-       u8 ch, need_write = 1;
+       int i, str_len = strlen(str), str_hbyte_len = (bit_len + 3) >> 2;
+       uint8_t ch = 0;
 
        if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len))
        {
@@ -552,75 +856,66 @@ static int svf_copy_hexstring_to_binary(char *str, u8 **bin, int orig_bit_len, i
                return ERROR_FAIL;
        }
 
-       if (str_byte_len > str_len)
+       /* fill from LSB (end of str) to MSB (beginning of str) */
+       for (i = 0; i < str_hbyte_len; i++)
        {
-               loop_cnt = str_byte_len;
-       }
-       else
-       {
-               loop_cnt = str_len;
-       }
-
-       for (i = 0; i < loop_cnt; i++)
-       {
-               if (i < str_len)
+               ch = 0;
+               while (str_len > 0)
                {
-                       ch = str[str_len - i - 1];
-                       if ((ch >= '0') && (ch <= '9'))
-                       {
-                               ch = ch - '0';
-                       }
-                       else if ((ch >= 'A') && (ch <= 'F'))
-                       {
-                               ch = ch - 'A' + 10;
-                       }
-                       else
+                       ch = str[--str_len];
+
+                       /* Skip whitespace.  The SVF specification (rev E) is
+                        * deficient in terms of basic lexical issues like
+                        * where whitespace is allowed.  Long bitstrings may
+                        * require line ends for correctness, since there is
+                        * a hard limit on line length.
+                        */
+                       if (!isspace(ch))
                        {
-                               LOG_ERROR("invalid hex string");
-                               return ERROR_FAIL;
+                               if ((ch >= '0') && (ch <= '9'))
+                               {
+                                       ch = ch - '0';
+                                       break;
+                               }
+                               else if ((ch >= 'A') && (ch <= 'F'))
+                               {
+                                       ch = ch - 'A' + 10;
+                                       break;
+                               }
+                               else
+                               {
+                                       LOG_ERROR("invalid hex string");
+                                       return ERROR_FAIL;
+                               }
                        }
-               }
-               else
-               {
+
                        ch = 0;
                }
 
-               // check valid
-               if (i >= str_byte_len)
+               // write bin
+               if (i % 2)
                {
-                       // all data written, other data should be all '0's and needn't to be written
-                       need_write = 0;
-                       if (ch != 0)
-                       {
-                               LOG_ERROR("value execede length");
-                               return ERROR_FAIL;
-                       }
+                       // MSB
+                       (*bin)[i / 2] |= ch << 4;
                }
-               else if (i == (str_byte_len - 1))
+               else
                {
-                       // last data byte, written if valid
-                       if ((ch & ~((1 << (bit_len - 4 * i)) - 1)) != 0)
-                       {
-                               LOG_ERROR("value execede length");
-                               return ERROR_FAIL;
-                       }
+                       // LSB
+                       (*bin)[i / 2] = 0;
+                       (*bin)[i / 2] |= ch;
                }
+       }
 
-               if (need_write)
-               {
-                       // write bin
-                       if (i % 2)
-                       {
-                               // MSB
-                               (*bin)[i / 2] |= ch << 4;
-                       }
-                       else
-                       {
-                               // LSB
-                               (*bin)[i / 2] = 0;
-                               (*bin)[i / 2] |= ch;
-                       }
-               }
+       /* consume optional leading '0' MSBs or whitespace */
+       while (str_len > 0 && ((str[str_len - 1] == '0')
+                               || isspace((int) str[str_len - 1])))
+               str_len--;
+
+       /* check validity: we must have consumed everything */
+       if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0)
+       {
+               LOG_ERROR("value execeeds length");
+               return ERROR_FAIL;
        }
 
        return ERROR_OK;
@@ -628,32 +923,29 @@ static int svf_copy_hexstring_to_binary(char *str, u8 **bin, int orig_bit_len, i
 
 static int svf_check_tdo(void)
 {
-       int i, j, byte_len, index;
+       int i, len, index_var;
 
        for (i = 0; i < svf_check_tdo_para_index; i++)
        {
-               if (svf_check_tdo_para[i].enabled)
+               index_var = svf_check_tdo_para[i].buffer_offset;
+               len = svf_check_tdo_para[i].bit_len;
+               if ((svf_check_tdo_para[i].enabled)
+                       && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len))
                {
-                       byte_len = (svf_check_tdo_para[i].bit_len + 7) >> 3;
-                       index = svf_check_tdo_para[i].buffer_offset;
-                       for (j = 0; j < byte_len; j++)
-                       {
-                               if ((svf_tdi_buffer[index + j] & svf_mask_buffer[index + j]) != svf_tdo_buffer[index + j])
-                               {
-                                       unsigned bitmask = (1 << svf_check_tdo_para[i].bit_len) - 1;
-                                       unsigned received, expected, tapmask;
-                                       memcpy(&received, svf_tdi_buffer + index, sizeof(unsigned));
-                                       memcpy(&expected, svf_tdo_buffer + index, sizeof(unsigned));
-                                       memcpy(&tapmask, svf_mask_buffer + index, sizeof(unsigned));
-                                       LOG_ERROR("tdo check error at line %d, "
-                                               "read = 0x%X, want = 0x%X, mask = 0x%X",
-                                                               svf_check_tdo_para[i].line_num,
-                                                               received & bitmask,
-                                                               expected & bitmask,
-                                                               tapmask & bitmask);
-                                       return ERROR_FAIL;
-                               }
-                       }
+                       unsigned bitmask;
+                       unsigned received, expected, tapmask;
+                       bitmask = svf_get_mask_u32(svf_check_tdo_para[i].bit_len);
+
+                       memcpy(&received, svf_tdi_buffer + index_var, sizeof(unsigned));
+                       memcpy(&expected, svf_tdo_buffer + index_var, sizeof(unsigned));
+                       memcpy(&tapmask, svf_mask_buffer + index_var, sizeof(unsigned));
+                       LOG_ERROR("tdo check error at line %d",
+                                         svf_check_tdo_para[i].line_num);
+                       LOG_ERROR("read = 0x%X, want = 0x%X, mask = 0x%X",
+                                         received & bitmask,
+                                         expected & bitmask,
+                                         tapmask & bitmask);
+                       return ERROR_FAIL;
                }
        }
        svf_check_tdo_para_index = 0;
@@ -661,7 +953,7 @@ static int svf_check_tdo(void)
        return ERROR_OK;
 }
 
-static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len)
+static int svf_add_check_para(uint8_t enabled, int buffer_offset, int bit_len)
 {
        if (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE)
        {
@@ -680,7 +972,7 @@ static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len)
 
 static int svf_execute_tap(void)
 {
-       if (ERROR_OK != jtag_execute_queue())
+       if ((!svf_nil) && (ERROR_OK != jtag_execute_queue()))
        {
                return ERROR_FAIL;
        }
@@ -694,11 +986,7 @@ static int svf_execute_tap(void)
        return ERROR_OK;
 }
 
-// not good to use this
-extern void* cmd_queue_alloc(size_t size);
-extern void jtag_queue_command(jtag_command_t * cmd);
-
-static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
+static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
 {
        char *argus[256], command;
        int num_of_argu = 0, i;
@@ -708,26 +996,28 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
 
        // for RUNTEST
        int run_count;
-       float min_time, max_time;
+       float min_time;
        // for XXR
-       svf_xxr_para_t *xxr_para_tmp;
-       u8 **pbuffer_tmp;
-       scan_field_t field;
+       struct svf_xxr_para *xxr_para_tmp;
+       uint8_t **pbuffer_tmp;
+       struct scan_field field;
        // for STATE
        tap_state_t *path = NULL, state;
-
-       if (!svf_quiet)
-       {
-               LOG_USER("%s", svf_command_buffer);
-       }
+       // flag padding commands skipped due to -tap command
+       int padding_command_skipped = 0;
 
        if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu))
        {
                return ERROR_FAIL;
        }
 
-       command = svf_find_string_in_array(argus[0], (char **)svf_command_name, dimof(svf_command_name));
-       switch(command)
+       /* NOTE: we're a bit loose here, because we ignore case in
+        * TAP state names (instead of insisting on uppercase).
+        */
+
+       command = svf_find_string_in_array(argus[0],
+                       (char **)svf_command_name, ARRAY_SIZE(svf_command_name));
+       switch (command)
        {
        case ENDDR:
        case ENDIR:
@@ -736,23 +1026,28 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        LOG_ERROR("invalid parameter of %s", argus[0]);
                        return ERROR_FAIL;
                }
-               i_tmp = svf_find_string_in_array(argus[1], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
+
+               i_tmp = tap_state_by_name(argus[1]);
+
                if (svf_tap_state_is_stable(i_tmp))
                {
                        if (command == ENDIR)
                        {
                                svf_para.ir_end_state = i_tmp;
-                               LOG_DEBUG("\tir_end_state = %s", svf_tap_state_name[svf_para.ir_end_state]);
+                               LOG_DEBUG("\tIR end_state = %s",
+                                               tap_state_name(i_tmp));
                        }
                        else
                        {
                                svf_para.dr_end_state = i_tmp;
-                               LOG_DEBUG("\tdr_end_state = %s", svf_tap_state_name[svf_para.dr_end_state]);
+                               LOG_DEBUG("\tDR end_state = %s",
+                                               tap_state_name(i_tmp));
                        }
                }
                else
                {
-                       LOG_ERROR("%s is not valid state", argus[1]);
+                       LOG_ERROR("%s: %s is not a stable state",
+                                       argus[0], argus[1]);
                        return ERROR_FAIL;
                }
                break;
@@ -782,21 +1077,41 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        // TODO: set jtag speed to
                        if (svf_para.frequency > 0)
                        {
-                               command_run_linef(cmd_ctx, "jtag_khz %d", (int)svf_para.frequency / 1000);
+                               command_run_linef(cmd_ctx, "adapter_khz %d", (int)svf_para.frequency / 1000);
                                LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
                        }
                }
                break;
        case HDR:
+               if (svf_tap_is_specified)
+               {
+                       padding_command_skipped = 1;
+                       break;
+               }
                xxr_para_tmp = &svf_para.hdr_para;
                goto XXR_common;
        case HIR:
+               if (svf_tap_is_specified)
+               {
+                       padding_command_skipped = 1;
+                       break;
+               }
                xxr_para_tmp = &svf_para.hir_para;
                goto XXR_common;
        case TDR:
+               if (svf_tap_is_specified)
+               {
+                       padding_command_skipped = 1;
+                       break;
+               }
                xxr_para_tmp = &svf_para.tdr_para;
                goto XXR_common;
        case TIR:
+               if (svf_tap_is_specified)
+               {
+                       padding_command_skipped = 1;
+                       break;
+               }
                xxr_para_tmp = &svf_para.tir_para;
                goto XXR_common;
        case SDR:
@@ -859,7 +1174,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                LOG_ERROR("fail to parse hex value");
                                return ERROR_FAIL;
                        }
-                       LOG_DEBUG("\t%s = 0x%X", argus[i], (**(int**)pbuffer_tmp) & ((1 << (xxr_para_tmp->len)) - 1));
+                       LOG_DEBUG("\t%s = 0x%X", argus[i], (**(int**)pbuffer_tmp) & svf_get_mask_u32(xxr_para_tmp->len));
                }
                // If a command changes the length of the last scan of the same type and the MASK parameter is absent,
                // the mask pattern used is all cares
@@ -873,6 +1188,27 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        }
                        buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len);
                }
+               // If TDO is absent, no comparison is needed, set the mask to 0
+               if (!(xxr_para_tmp->data_mask & XXR_TDO))
+               {
+                       if (NULL == xxr_para_tmp->tdo)
+                       {
+                               if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->tdo, i_tmp, xxr_para_tmp->len))
+                               {
+                                       LOG_ERROR("fail to adjust length of array");
+                                       return ERROR_FAIL;
+                               }
+                       }
+                       if (NULL == xxr_para_tmp->mask)
+                       {
+                               if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len))
+                               {
+                                       LOG_ERROR("fail to adjust length of array");
+                                       return ERROR_FAIL;
+                               }
+                       }
+                       memset(xxr_para_tmp->mask, 0, (xxr_para_tmp->len + 7) >> 3);
+               }
                // do scan if necessary
                if (SDR == command)
                {
@@ -885,10 +1221,10 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                LOG_ERROR("buffer is not enough, report to author");
                                return ERROR_FAIL;
 #else
-                               u8 *buffer_tmp;
+                               uint8_t *buffer_tmp;
 
                                // reallocate buffer
-                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               buffer_tmp = (uint8_t *)malloc(svf_buffer_index + ((i + 7) >> 3));
                                if (NULL == buffer_tmp)
                                {
                                        LOG_ERROR("not enough memory");
@@ -899,7 +1235,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                free(svf_tdi_buffer);
                                svf_tdi_buffer = buffer_tmp;
 
-                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               buffer_tmp = (uint8_t *)malloc(svf_buffer_index + ((i + 7) >> 3));
                                if (NULL == buffer_tmp)
                                {
                                        LOG_ERROR("not enough memory");
@@ -910,7 +1246,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                free(svf_tdo_buffer);
                                svf_tdo_buffer = buffer_tmp;
 
-                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               buffer_tmp = (uint8_t *)malloc(svf_buffer_index + ((i + 7) >> 3));
                                if (NULL == buffer_tmp)
                                {
                                        LOG_ERROR("not enough memory");
@@ -945,7 +1281,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                buf_set_buf(svf_para.sdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sdr_para.len);
                                i += svf_para.sdr_para.len;
                                buf_set_buf(svf_para.tdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tdr_para.len);
-                               i += svf_para.tdr_para.len;
+
                                // assemble dr check data
                                i = 0;
                                buf_set_buf(svf_para.hdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hdr_para.len);
@@ -961,19 +1297,16 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        {
                                svf_add_check_para(0, svf_buffer_index, i);
                        }
-                       field.tap = tap;
                        field.num_bits = i;
                        field.out_value = &svf_tdi_buffer[svf_buffer_index];
-                       
                        field.in_value = &svf_tdi_buffer[svf_buffer_index];
-                       
-                       
-                       
-                       
-                       jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state);
+                       if (!svf_nil)
+                       {
+                               /* NOTE:  doesn't use SVF-specified state paths */
+                               jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, svf_para.dr_end_state);
+                       }
 
                        svf_buffer_index += (i + 7) >> 3;
-                       last_state = svf_para.dr_end_state;
                }
                else if (SIR == command)
                {
@@ -986,10 +1319,10 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                LOG_ERROR("buffer is not enough, report to author");
                                return ERROR_FAIL;
 #else
-                               u8 *buffer_tmp;
+                               uint8_t *buffer_tmp;
 
                                // reallocate buffer
-                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               buffer_tmp = (uint8_t *)malloc(svf_buffer_index + ((i + 7) >> 3));
                                if (NULL == buffer_tmp)
                                {
                                        LOG_ERROR("not enough memory");
@@ -1000,7 +1333,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                free(svf_tdi_buffer);
                                svf_tdi_buffer = buffer_tmp;
 
-                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               buffer_tmp = (uint8_t *)malloc(svf_buffer_index + ((i + 7) >> 3));
                                if (NULL == buffer_tmp)
                                {
                                        LOG_ERROR("not enough memory");
@@ -1011,7 +1344,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                free(svf_tdo_buffer);
                                svf_tdo_buffer = buffer_tmp;
 
-                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               buffer_tmp = (uint8_t *)malloc(svf_buffer_index + ((i + 7) >> 3));
                                if (NULL == buffer_tmp)
                                {
                                        LOG_ERROR("not enough memory");
@@ -1046,7 +1379,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                buf_set_buf(svf_para.sir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sir_para.len);
                                i += svf_para.sir_para.len;
                                buf_set_buf(svf_para.tir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tir_para.len);
-                               i += svf_para.tir_para.len;
+
                                // assemble dr check data
                                i = 0;
                                buf_set_buf(svf_para.hir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hir_para.len);
@@ -1062,19 +1395,17 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        {
                                svf_add_check_para(0, svf_buffer_index, i);
                        }
-                       field.tap = tap;
                        field.num_bits = i;
                        field.out_value = &svf_tdi_buffer[svf_buffer_index];
-                       
                        field.in_value = &svf_tdi_buffer[svf_buffer_index];
-                       
-                       
-                       
-                       
-                       jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state);
+                       if (!svf_nil)
+                       {
+                               /* NOTE:  doesn't use SVF-specified state paths */
+                               jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value,
+                                               svf_para.ir_end_state);
+                       }
 
                        svf_buffer_index += (i + 7) >> 3;
-                       last_state = svf_para.ir_end_state;
                }
                break;
        case PIO:
@@ -1093,27 +1424,32 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                // init
                run_count = 0;
                min_time = 0;
-               max_time = 0;
                i = 1;
+
                // run_state
-               i_tmp = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
-               if (svf_tap_state_is_valid(i_tmp))
+               i_tmp = tap_state_by_name(argus[i]);
+               if (i_tmp != TAP_INVALID)
                {
                        if (svf_tap_state_is_stable(i_tmp))
                        {
                                svf_para.runtest_run_state = i_tmp;
 
-                               // When a run_state is specified, the new  run_state becomes the default end_state
+                               /* When a run_state is specified, the new
+                                * run_state becomes the default end_state.
+                                */
                                svf_para.runtest_end_state = i_tmp;
-                               LOG_DEBUG("\trun_state = %s", svf_tap_state_name[svf_para.runtest_run_state]);
+                               LOG_DEBUG("\trun_state = %s",
+                                               tap_state_name(i_tmp));
                                i++;
                        }
                        else
                        {
-                               LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]);
+                               LOG_ERROR("%s: %s is not a stable state",
+                                       argus[0], tap_state_name(i_tmp));
                                return ERROR_FAIL;
                        }
                }
+
                // run_count run_clk
                if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC"))
                {
@@ -1140,6 +1476,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                // MAXIMUM max_time SEC
                if (((i + 3) <= num_of_argu) && !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC"))
                {
+                       float max_time = 0;
                        max_time = atof(argus[i + 1]);
                        LOG_DEBUG("\tmax_time = %fs", max_time);
                        i += 3;
@@ -1147,73 +1484,63 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                // ENDSTATE end_state
                if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE"))
                {
-                       i_tmp = svf_find_string_in_array(argus[i + 1], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
+                       i_tmp = tap_state_by_name(argus[i + 1]);
+
                        if (svf_tap_state_is_stable(i_tmp))
                        {
                                svf_para.runtest_end_state = i_tmp;
-                               LOG_DEBUG("\tend_state = %s", svf_tap_state_name[svf_para.runtest_end_state]);
+                               LOG_DEBUG("\tend_state = %s",
+                                       tap_state_name(i_tmp));
                        }
                        else
                        {
-                               LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]);
+                               LOG_ERROR("%s: %s is not a stable state",
+                                       argus[0], tap_state_name(i_tmp));
                                return ERROR_FAIL;
                        }
                        i += 2;
                }
-               // calculate run_count
-               if ((0 == run_count) && (min_time > 0))
-               {
-                       run_count = min_time * svf_para.frequency;
-               }
+
                // all parameter should be parsed
                if (i == num_of_argu)
                {
-                       if (run_count > 0)
-                       {
-                               // run_state and end_state is checked to be stable state
-                               // TODO: do runtest
 #if 1
-                               // enter into run_state if necessary
-                               if (last_state != svf_para.runtest_run_state)
-                               {
-                                       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-                                       
-                                       jtag_queue_command(cmd);
-                               
-                                       cmd->type = JTAG_STATEMOVE;
-                                       cmd->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-                                       cmd->cmd.statemove->end_state = svf_para.runtest_run_state;
-
-                                       cmd_queue_end_state = cmd_queue_cur_state = cmd->cmd.statemove->end_state;
-                               }
+                       /* FIXME handle statemove failures */
+                       uint32_t min_usec = 1000000 * min_time;
 
-                               // call jtag_add_clocks
-                               jtag_add_clocks(run_count);
+                       // enter into run_state if necessary
+                       if (cmd_queue_cur_state != svf_para.runtest_run_state)
+                       {
+                               svf_add_statemove(svf_para.runtest_run_state);
+                       }
 
-                               if (svf_para.runtest_end_state != svf_para.runtest_run_state)
-                               {
-                                       // move to end_state
-                                       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-                                       
-                                       jtag_queue_command(cmd);
-                                       cmd->type = JTAG_STATEMOVE;
-                                       cmd->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-                                       cmd->cmd.statemove->end_state = svf_para.runtest_end_state;
-
-                                       cmd_queue_end_state = cmd_queue_cur_state = cmd->cmd.statemove->end_state;
-                               }
-                               last_state = svf_para.runtest_end_state;
+                       // add clocks and/or min wait
+                       if (run_count > 0) {
+                               if (!svf_nil)
+                                       jtag_add_clocks(run_count);
+                       }
+
+                       if (min_usec > 0) {
+                               if (!svf_nil)
+                                       jtag_add_sleep(min_usec);
+                       }
+
+                       // move to end_state if necessary
+                       if (svf_para.runtest_end_state != svf_para.runtest_run_state)
+                       {
+                               svf_add_statemove(svf_para.runtest_end_state);
+                       }
 #else
-                               if (svf_para.runtest_run_state != TAP_IDLE)
-                               {
-                                       // RUNTEST can only executed in TAP_IDLE
-                                       LOG_ERROR("cannot runtest in %s state", svf_tap_state_name[svf_para.runtest_run_state]);
-                                       return ERROR_FAIL;
-                               }
+                       if (svf_para.runtest_run_state != TAP_IDLE)
+                       {
+                               LOG_ERROR("cannot runtest in %s state",
+                                       tap_state_name(svf_para.runtest_run_state));
+                               return ERROR_FAIL;
+                       }
 
+                       if (!svf_nil)
                                jtag_add_runtest(run_count, svf_para.runtest_end_state);
 #endif
-                       }
                }
                else
                {
@@ -1238,22 +1565,28 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                return ERROR_FAIL;
                        }
                        num_of_argu--;          // num of path
-                       i_tmp = 1;                      // path is from patameter 1
-                       for (i = 0; i < num_of_argu; i++)
+                       i_tmp = 1;              /* path is from parameter 1 */
+                       for (i = 0; i < num_of_argu; i++, i_tmp++)
                        {
-                               path[i] = svf_find_string_in_array(argus[i_tmp++], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
-                               if (!svf_tap_state_is_valid(path[i]))
+                               path[i] = tap_state_by_name(argus[i_tmp]);
+                               if (path[i] == TAP_INVALID)
                                {
-                                       LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i]]);
+                                       LOG_ERROR("%s: %s is not a valid state",
+                                               argus[0], argus[i_tmp]);
+                                       free(path);
                                        return ERROR_FAIL;
                                }
+                               /* OpenOCD refuses paths containing TAP_RESET */
                                if (TAP_RESET == path[i])
                                {
+                                       /* FIXME last state MUST be stable! */
                                        if (i > 0)
                                        {
-                                               jtag_add_pathmove(i, path);
+                                               if (!svf_nil)
+                                                       jtag_add_pathmove(i, path);
                                        }
-                                       jtag_add_tlr();
+                                       if (!svf_nil)
+                                               jtag_add_tlr();
                                        num_of_argu -= i + 1;
                                        i = -1;
                                }
@@ -1264,47 +1597,39 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                if (svf_tap_state_is_stable(path[num_of_argu - 1]))
                                {
                                        // last state MUST be stable state
-                                       // TODO: call path_move
-                                       jtag_add_pathmove(num_of_argu, path);
-                                       last_state = path[num_of_argu - 1];
-                                       LOG_DEBUG("\tmove to %s by path_move", svf_tap_state_name[path[num_of_argu - 1]]);
+                                       if (!svf_nil)
+                                               jtag_add_pathmove(num_of_argu, path);
+                                       LOG_DEBUG("\tmove to %s by path_move",
+                                               tap_state_name(path[num_of_argu - 1]));
                                }
                                else
                                {
-                                       LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]);
+                                       LOG_ERROR("%s: %s is not a stable state",
+                                               argus[0],
+                                               tap_state_name(path[num_of_argu - 1]));
+                                       free(path);
                                        return ERROR_FAIL;
                                }
                        }
-                       // no need to keep this memory, in jtag_add_pathmove, path will be duplicated
-                       if (NULL != path)
-                       {
-                               free(path);
-                               path = NULL;
-                       }
+
+                       free(path);
+                       path = NULL;
                }
                else
                {
                        // STATE stable_state
-                       state = svf_find_string_in_array(argus[1], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
+                       state = tap_state_by_name(argus[1]);
                        if (svf_tap_state_is_stable(state))
                        {
-                               // TODO: move to state
-                               jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-                                       
-                               jtag_queue_command(cmd);
-                               
-                               cmd->type = JTAG_STATEMOVE;
-                               cmd->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-                               cmd->cmd.statemove->end_state = state;
-
-                               cmd_queue_end_state = cmd_queue_cur_state = cmd->cmd.statemove->end_state;
-                               last_state = state;
-
-                               LOG_DEBUG("\tmove to %s by state_move", svf_tap_state_name[state]);
+                               LOG_DEBUG("\tmove to %s by svf_add_statemove",
+                                               tap_state_name(state));
+                               /* FIXME handle statemove failures */
+                               svf_add_statemove(state);
                        }
                        else
                        {
-                               LOG_ERROR("%s is not valid state", svf_tap_state_name[state]);
+                               LOG_ERROR("%s: %s is not a stable state",
+                                       argus[0], tap_state_name(state));
                                return ERROR_FAIL;
                        }
                }
@@ -1322,16 +1647,19 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                        {
                                return ERROR_FAIL;
                        }
-                       i_tmp = svf_find_string_in_array(argus[1], (char **)svf_trst_mode_name, dimof(svf_trst_mode_name));
+                       i_tmp = svf_find_string_in_array(argus[1],
+                                       (char **)svf_trst_mode_name,
+                                       ARRAY_SIZE(svf_trst_mode_name));
                        switch (i_tmp)
                        {
                        case TRST_ON:
-                               last_state = TAP_RESET;
-                               jtag_add_reset(1, 0);
+                               if (!svf_nil)
+                                       jtag_add_reset(1, 0);
                                break;
                        case TRST_Z:
                        case TRST_OFF:
-                               jtag_add_reset(0, 0);
+                               if (!svf_nil)
+                                       jtag_add_reset(0, 0);
                                break;
                        case TRST_ABSENT:
                                break;
@@ -1354,6 +1682,14 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                break;
        }
 
+       if (!svf_quiet)
+       {
+               if (padding_command_skipped)
+               {
+                       LOG_USER("(Above Padding command skipped, as per -tap argument)");
+               }
+       }
+
        if (debug_level >= LOG_LVL_DEBUG)
        {
                // for convenient debugging, execute tap if possible
@@ -1372,7 +1708,7 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
                                int read_value;
                                memcpy(&read_value, svf_tdi_buffer, sizeof(int));
                                // in debug mode, data is from index 0
-                               int read_mask = (1 << (svf_check_tdo_para[0].bit_len)) - 1;
+                               int read_mask = svf_get_mask_u32(svf_check_tdo_para[0].bit_len);
                                LOG_DEBUG("\tTDO read = 0x%X", read_value & read_mask);
                        }
                }
@@ -1391,3 +1727,19 @@ static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
 
        return ERROR_OK;
 }
+
+static const struct command_registration svf_command_handlers[] = {
+       {
+               .name = "svf",
+               .handler = handle_svf_command,
+               .mode = COMMAND_EXEC,
+               .help = "Runs a SVF file.",
+               .usage = "svf [-tap device.tap] <file> [quiet] [nil] [progress]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+int svf_register_commands(struct command_context *cmd_ctx)
+{
+       return register_commands(cmd_ctx, NULL, svf_command_handlers);
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)