SVF player courtesy of Simon Qian <simonqian@SimonQian.com>
authorkc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 19 Jan 2009 07:13:02 +0000 (07:13 +0000)
committerkc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 19 Jan 2009 07:13:02 +0000 (07:13 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@1339 b42882b7-edfa-0310-969c-e2dbd0fdcd60

configure.in
src/Makefile.am
src/ecosboard.c
src/jtag/vsllink.c
src/openocd.c
src/svf/Makefile.am [new file with mode: 0644]
src/svf/Makefile.in [new file with mode: 0644]
src/svf/svf.c [new file with mode: 0644]
src/svf/svf.h [new file with mode: 0644]

index f00119891249d3fd7889336b100a97708805ffc3..79e546e8aebe49d590e228834bd0fa083950d217 100644 (file)
@@ -705,4 +705,4 @@ fi
 AC_MSG_RESULT([$EXEEXT_FOR_BUILD])
 AC_SUBST(EXEEXT_FOR_BUILD)
 
-AC_OUTPUT(Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/xsvf/Makefile src/target/Makefile src/server/Makefile src/flash/Makefile src/pld/Makefile doc/Makefile)
+AC_OUTPUT(Makefile src/Makefile src/helper/Makefile src/jtag/Makefile src/xsvf/Makefile src/svf/Makefile src/target/Makefile src/server/Makefile src/flash/Makefile src/pld/Makefile doc/Makefile)
index 0e0f50e480e713e181ec55af7d679833b3971ccf..24333e31221c50ff92787d3484cec0a81e91bb91 100644 (file)
@@ -11,8 +11,8 @@ openocd_SOURCES = $(MAINFILE) openocd.c
 
 # set the include path found by configure
 INCLUDES = -I$(top_srcdir)/src -I$(top_srcdir)/src/helper \
-       -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target -I$(top_srcdir)/src/xsvf -I$(top_srcdir)/src/server \
-       -I$(top_srcdir)/src/flash -I$(top_srcdir)/src/pld $(all_includes)
+       -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target -I$(top_srcdir)/src/xsvf -I$(top_srcdir)/src/svf \
+       -I$(top_srcdir)/src/server -I$(top_srcdir)/src/flash -I$(top_srcdir)/src/pld $(all_includes)
 
 # pass path to prefix path
 openocd_CPPFLAGS = \
@@ -23,7 +23,7 @@ openocd_CPPFLAGS = \
 
 # the library search path.
 openocd_LDFLAGS = $(all_libraries) 
-SUBDIRS = helper jtag xsvf target server flash pld
+SUBDIRS = helper jtag xsvf svf target server flash pld
 
 if IS_MINGW
 MINGWLDADD = -lwsock32
@@ -61,7 +61,7 @@ endif
 
 
 
-openocd_LDADD = $(top_builddir)/src/xsvf/libxsvf.a \
+openocd_LDADD = $(top_builddir)/src/xsvf/libxsvf.a $(top_builddir)/src/svf/libsvf.a \
        $(top_builddir)/src/target/libtarget.a $(top_builddir)/src/jtag/libjtag.a \
        $(top_builddir)/src/helper/libhelper.a \
        $(top_builddir)/src/server/libserver.a $(top_builddir)/src/helper/libhelper.a \
index 725a3f3640b9fae3270ed6bda381d7f6e984d04c..859d045b7bb89875a185980ee0c0547d1cb5aaf7 100644 (file)
@@ -26,6 +26,7 @@
 #include "jtag.h"
 #include "configuration.h"
 #include "xsvf.h"
+#include "svf.h"
 #include "target.h"
 #include "flash.h"
 #include "nand.h"
index 88a59d787b93f21225fa7931b5d019de9f098385..de4220f798af8a38b6697ce73c2f478e60e3960b 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2007 by Simon Qian <SimonQian@SimonQian.com>            *
+ *   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  *
 #define DEBUG_JTAG_IO(expr ...)
 #endif
 
-#define VID                                                    0x03EB
-#define PID                                                    0x2103
-#define VSLLINK_WRITE_ENDPOINT         0x02
-#define VSLLINK_READ_ENDPOINT          0x82
+u16 vsllink_vid;
+u16 vsllink_pid;
+u8 vsllink_bulkout;
+u8 vsllink_bulkin;
 
-u16 vsllink_vid = VID;
-u16 vsllink_pid = PID;
-u8 vsllink_bulkout = VSLLINK_WRITE_ENDPOINT;
-u8 vsllink_bulkin = VSLLINK_READ_ENDPOINT;
-
-#define VSLLINK_USB_TIMEOUT                    1000
+#define VSLLINK_USB_TIMEOUT                    5000
 
 static int VSLLINK_BufferSize = 1024;
 
@@ -77,8 +72,11 @@ static u8* vsllink_usb_out_buffer = NULL;
 #define VSLLINK_CMD_GET_PORT           0x91
 #define VSLLINK_CMD_SET_PORTDIR                0x92
 #define VSLLINK_CMD_HW_JTAGSEQCMD      0xA0
+#define VSLLINK_CMD_HW_JTAGHLCMD       0xA1
+#define VSLLINK_CMD_HW_SWDCMD          0xA2
 
 #define VSLLINK_CMDJTAGSEQ_TMSBYTE     0x00
+#define VSLLINK_CMDJTAGSEQ_TMS0BYTE    0x40
 #define VSLLINK_CMDJTAGSEQ_SCAN                0x80
 
 #define VSLLINK_CMDJTAGSEQ_CMDMSK      0xC0
@@ -109,21 +107,21 @@ static u8* vsllink_usb_out_buffer = NULL;
 u8 VSLLINK_tap_move[6][6] =
 {
 /*       TLR   RTI   SD    PD    SI    PI             */
-       {0xff, 0x00, 0x2f, 0x0a, 0x37, 0x16},   /* TLR */
+       {0xff, 0x7f, 0x2f, 0x0a, 0x37, 0x16},   /* TLR */
        {0xff, 0x00, 0x45, 0x05, 0x4b, 0x0b},   /* RTI */
        {0xff, 0x61, 0x00, 0x01, 0x0f, 0x2f},   /* SD  */
-       {0xff, 0x60, 0x40, 0x17, 0x3c, 0x2f},   /* PD  */
+       {0xff, 0x60, 0x40, 0x5c, 0x3c, 0x5e},   /* PD  */
        {0xff, 0x61, 0x07, 0x17, 0x00, 0x01},   /* SI  */
-       {0xff, 0x60, 0x38, 0x17, 0x40, 0x2f}    /* PI  */
+       {0xff, 0x60, 0x38, 0x5c, 0x40, 0x5e}    /* PI  */
 };
 
-u8 VSLLINK_TAP_MOVE_FROM_E1[6] =
+typedef struct insert_insignificant_operation
 {
-//     TLR             RTI             SD              PD              SI              PI
-       0xff,   0x60,   0x38,   0x5c,   0x3c,   0x5E
-};
+       unsigned char insert_value;
+       unsigned char insert_position;
+}insert_insignificant_operation_t;
 
-u8 VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[7][6][2] =
+insert_insignificant_operation_t VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[6][6] =
 {
 /*      stuff  offset   */
        {/*     TLR     */
@@ -175,6 +173,19 @@ u8 VSLLINK_BIT_MSK[8] =
        0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f
 };
 
+typedef struct
+{
+       int length; /* Number of bits to read */
+       int offset;
+       scan_command_t *command; /* Corresponding scan command */
+       u8 *buffer;
+} pending_scan_result_t;
+
+#define MAX_PENDING_SCAN_RESULTS 256
+
+static int pending_scan_results_length;
+static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
+
 /* External interface functions */
 int vsllink_execute_queue(void);
 int vsllink_speed(int speed);
@@ -219,8 +230,8 @@ int vsllink_usb_read(vsllink_jtag_t *vsllink_jtag);
 
 void vsllink_debug_buffer(u8 *buffer, int length);
 
-int vsllink_tms_data_len = 0;
-u8* vsllink_tms_cmd_pos;
+static int vsllink_tms_data_len = 0;
+static u8* vsllink_tms_cmd_pos;
 
 vsllink_jtag_t* vsllink_jtag_handle;
 
@@ -255,7 +266,7 @@ int vsllink_execute_queue(void)
                switch (cmd->type)
                {
                        case JTAG_END_STATE:
-                               DEBUG_JTAG_IO("end_state: %i", cmd->cmd.end_state->end_state);
+                               DEBUG_JTAG_IO("end_state: %s", jtag_state_name(cmd->cmd.end_state->end_state));
                        
                                if (cmd->cmd.end_state->end_state != -1)
                                {
@@ -264,9 +275,9 @@ int vsllink_execute_queue(void)
                                break;
        
                        case JTAG_RUNTEST:
-                               DEBUG_JTAG_IO( "runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \
-                                       cmd->cmd.runtest->end_state);
-                               
+                               DEBUG_JTAG_IO( "runtest %i cycles, end in %s", cmd->cmd.runtest->num_cycles, \
+                                       jtag_state_name(cmd->cmd.runtest->end_state));
+
                                if (cmd->cmd.runtest->end_state != -1)
                                {
                                        vsllink_end_state(cmd->cmd.runtest->end_state);
@@ -275,7 +286,7 @@ int vsllink_execute_queue(void)
                                break;
        
                        case JTAG_STATEMOVE:
-                               DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+                               DEBUG_JTAG_IO("statemove end in %s", jtag_state_name(cmd->cmd.statemove->end_state));
                        
                                if (cmd->cmd.statemove->end_state != -1)
                                {
@@ -285,9 +296,9 @@ int vsllink_execute_queue(void)
                                break;
        
                        case JTAG_PATHMOVE:
-                               DEBUG_JTAG_IO("pathmove: %i states, end in %i", \
+                               DEBUG_JTAG_IO("pathmove: %i states, end in %s", \
                                        cmd->cmd.pathmove->num_states, \
-                                       cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+                                       jtag_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
                        
                                vsllink_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
                                break;
@@ -301,11 +312,11 @@ int vsllink_execute_queue(void)
                                scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
                                if (cmd->cmd.scan->ir_scan)
                                {
-                                       DEBUG_JTAG_IO("JTAG Scan write IR(%d bits), end in %d:", scan_size, cmd->cmd.scan->end_state);
+                                       DEBUG_JTAG_IO("JTAG Scan write IR(%d bits), end in %s:", scan_size, jtag_state_name(cmd->cmd.scan->end_state));
                                }
                                else
                                {
-                                       DEBUG_JTAG_IO("JTAG Scan write DR(%d bits), end in %d:", scan_size, cmd->cmd.scan->end_state);
+                                       DEBUG_JTAG_IO("JTAG Scan write DR(%d bits), end in %s:", scan_size, jtag_state_name(cmd->cmd.scan->end_state));
                                }
 
 #ifdef _DEBUG_JTAG_IO_
@@ -470,8 +481,7 @@ int vsllink_init(void)
        vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORTDIR;
        vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST | JTAG_PINMSK_USR1 | JTAG_PINMSK_USR2;
        vsllink_usb_out_buffer[2] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST;
-       result = vsllink_usb_write(vsllink_jtag_handle, 3);
-       if (result != 3)
+       if (vsllink_usb_write(vsllink_jtag_handle, 3) != 3)
        {
                LOG_ERROR("VSLLink USB send data error");
                exit(-1);
@@ -490,6 +500,17 @@ int vsllink_quit(void)
 {
        if ((vsllink_usb_in_buffer != NULL) && (vsllink_usb_out_buffer != NULL))
        {
+               // Set all pins to input
+               vsllink_usb_out_buffer[0] = VSLLINK_CMD_SET_PORTDIR;
+               vsllink_usb_out_buffer[1] = JTAG_PINMSK_SRST | JTAG_PINMSK_TRST | JTAG_PINMSK_USR1 | JTAG_PINMSK_USR2;
+               vsllink_usb_out_buffer[2] = 0;
+               if (vsllink_usb_write(vsllink_jtag_handle, 3) != 3)
+               {
+                       LOG_ERROR("VSLLink USB send data error");
+                       exit(-1);
+               }
+
+               // disconnect
                vsllink_simple_command(VSLLINK_CMD_DISCONN);
                vsllink_usb_close(vsllink_jtag_handle);
        }
@@ -506,24 +527,29 @@ int vsllink_quit(void)
 }
 
 // when vsllink_tms_data_len > 0, vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] is the byte that need to be appended.
-// length of VSLLINK_CMDJTAGSEQ_TMSBYTE has been set.
-void VSLLINK_add_tms_from_RTI(enum tap_state state)
+// length of VSLLINK_CMDJTAGSEQ_TMSBYTE has been set, no need to set it here.
+void vsllink_append_tms(void)
 {
-       u8 tms_scan = VSLLINK_TAP_MOVE(TAP_IDLE, state);
+       u8 tms_scan = VSLLINK_TAP_MOVE(cur_state, end_state);
        u16 tms2;
 
-       if ((cur_state != TAP_IDLE) || (state == TAP_IDLE) || (vsllink_tms_data_len <= 0) || (vsllink_tms_data_len >= 8) || (vsllink_tms_cmd_pos == NULL))
+       if (((cur_state != TAP_RESET) && (cur_state != TAP_IDLE) && (cur_state != TAP_DRPAUSE) && (cur_state != TAP_IRPAUSE)) || \
+                       (vsllink_tms_data_len <= 0) || (vsllink_tms_data_len >= 8) || \
+                       (vsllink_tms_cmd_pos == NULL))
        {
                LOG_ERROR("There MUST be some bugs in the driver");
                exit(-1);
        }
 
-       tms2 = (tms_scan & VSLLINK_BIT_MSK[VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]]) << vsllink_tms_data_len;
-       if (VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][0] == 1)
+       tms2 = (tms_scan & VSLLINK_BIT_MSK[VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position]) << \
+                               vsllink_tms_data_len;
+       if (VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_value == 1)
        {
-               tms2 |= VSLLINK_BIT_MSK[8 - vsllink_tms_data_len] << (vsllink_tms_data_len + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]);
+               tms2 |= VSLLINK_BIT_MSK[8 - vsllink_tms_data_len] << \
+                               (vsllink_tms_data_len + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position);
        }
-       tms2 |= (tms_scan >> VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]) << (8 + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[1][tap_move_map[state]][1]);
+       tms2 |= (tms_scan >> VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position) << \
+                               (8 + VSLLINK_TAP_MOVE_INSERT_INSIGNIFICANT[tap_move_map[cur_state]][tap_move_map[end_state]].insert_position);
 
        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= (tms2 >> 0) & 0xff;
        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms2 >> 8) & 0xff;
@@ -553,7 +579,7 @@ void vsllink_state_move(void)
 {
        if (vsllink_tms_data_len > 0)
        {
-               VSLLINK_add_tms_from_RTI(end_state);
+               vsllink_append_tms();
        }
        else
        {
@@ -577,26 +603,32 @@ void vsllink_add_path(int start, int num, enum tap_state *path)
                {
                        if (i > 0)
                        {
-                               vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0;
-                       }
-                       else
-                       {
-                               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0;
+                               vsllink_usb_out_buffer_idx++;
                        }
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0;
                }
 
                if (path[i - start] == tap_transitions[cur_state].high)
                {
                        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] |= 1 << (i & 7);
                }
+               else if (path[i - start] == tap_transitions[cur_state].low)
+               {
+                       // nothing to do
+               }
                else
                {
-                       LOG_ERROR("BUG: %d -> %d isn't a valid TAP transition", cur_state, path[i]);
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", jtag_state_name(cur_state), jtag_state_name(path[i]));
                        exit(-1);
                }
-
-               cur_state = path[i];
+               cur_state = path[i - start];
        }
+       if ((i > 0) && ((i & 7) == 0))
+       {
+               vsllink_usb_out_buffer_idx++;
+               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0;
+       }
+
        end_state = cur_state;
 }
 
@@ -606,42 +638,68 @@ void vsllink_path_move(int num_states, enum tap_state *path)
 
        if (vsllink_tms_data_len > 0)
        {
-               if ((vsllink_tms_data_len + num_states) < 8)
-               {
-                       vsllink_add_path(vsllink_tms_data_len, num_states, path);
-                       num_states = 0;
-               }
-               else if ((vsllink_tms_data_len + num_states) < 16)
+               // there are vsllink_tms_data_len more tms bits to be shifted
+               // so there are vsllink_tms_data_len + num_states tms bits in all
+               tms_len = vsllink_tms_data_len + num_states;
+               if (tms_len <= 16)
                {
-                       if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) \
-                                       < VSLLINK_CMDJTAGSEQ_LENMSK)
+                       // merge into last tms shift
+                       if (tms_len < 8)
                        {
-                               *vsllink_tms_cmd_pos++;
+                               // just append tms data to the last tms byte
                                vsllink_add_path(vsllink_tms_data_len, num_states, path);
                        }
-                       else
+                       else if (tms_len == 8)
                        {
-                               // need a new VSLLINK_CMDJTAGSEQ_TMSBYTE command
-                               // if vsllink_tms_data_len > 0, length of VSLLINK_CMDJTAGSEQ_TMSBYTE MUST be > 1(tms_len > 2)
-                               *vsllink_tms_cmd_pos--;
-                               vsllink_add_path(vsllink_tms_data_len, 8 - vsllink_tms_data_len, path);
-                               vsllink_usb_out_buffer_idx++;
-                               vsllink_tap_ensure_space(0, 3);
-                               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1;
-                               vsllink_tms_cmd_pos = vsllink_usb_out_buffer + vsllink_usb_out_buffer_idx;
-                               vsllink_add_path(vsllink_tms_data_len, num_states + vsllink_tms_data_len - 8, path + 8 - vsllink_tms_data_len);
+                               // end last tms shift command
+                               (*vsllink_tms_cmd_pos)--;
+                               vsllink_add_path(vsllink_tms_data_len, num_states, path);
+                       }
+                       else if (tms_len < 16)
+                       {
+                               if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) < VSLLINK_CMDJTAGSEQ_LENMSK)
+                               {
+                                       // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most
+                                       // there is enought tms length in the current tms shift command
+                                       (*vsllink_tms_cmd_pos)++;
+                                       vsllink_add_path(vsllink_tms_data_len, num_states, path);
+                               }
+                               else
+                               {
+                                       // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most
+                                       // not enough tms length in the current tms shift command
+                                       // so a new command should be added
+                                       // first decrease byte length of last tms shift command
+                                       (*vsllink_tms_cmd_pos)--;
+                                       // append tms data to the last tms byte
+                                       vsllink_add_path(vsllink_tms_data_len, 8 - vsllink_tms_data_len, path);
+                                       path += 8 - vsllink_tms_data_len;
+                                       // add new command(3 bytes)
+                                       vsllink_tap_ensure_space(0, 3);
+                                       vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
+                                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1;
+                                       vsllink_add_path(0, num_states - (8 - vsllink_tms_data_len), path);
+                               }
                        }
+                       else if (tms_len == 16)
+                       {
+                               // end last tms shift command
+                               vsllink_add_path(vsllink_tms_data_len, num_states, path);
+                       }
+
                        vsllink_tms_data_len = (vsllink_tms_data_len + num_states) & 7;
+                       if (vsllink_tms_data_len == 0)
+                       {
+                               vsllink_tms_cmd_pos = NULL;
+                       }
                        num_states = 0;
                }
                else
                {
                        vsllink_add_path(vsllink_tms_data_len, 16 - vsllink_tms_data_len, path);
-                       path_idx = 16 - vsllink_tms_data_len;
-                       vsllink_usb_out_buffer_idx++;
 
-                       num_states -= 16 - vsllink_tms_data_len;
                        path += 16 - vsllink_tms_data_len;
+                       num_states -= 16 - vsllink_tms_data_len;
                        vsllink_tms_data_len = 0;
                        vsllink_tms_cmd_pos = NULL;
                }
@@ -677,14 +735,16 @@ void vsllink_path_move(int num_states, enum tap_state *path)
                {
                        if (tms_len < (VSLLINK_CMDJTAGSEQ_LENMSK + 1))
                        {
-                               vsllink_usb_out_buffer[tms_cmd_pos]++;
-                               vsllink_usb_out_buffer = vsllink_usb_out_buffer + tms_cmd_pos;
+                               vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[tms_cmd_pos];
+                               (*vsllink_tms_cmd_pos)++;
                        }
                        else
                        {
                                vsllink_usb_out_buffer[tms_cmd_pos]--;
+
                                tms_len = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
                                vsllink_tap_ensure_space(0, 3);
+                               vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
                                vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1;
                                vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = tms_len;
                        }
@@ -694,164 +754,147 @@ void vsllink_path_move(int num_states, enum tap_state *path)
 
 void vsllink_runtest(int num_cycles)
 {
-       int i = 0, j;
-       int tms_len, first_tms = 0, tms_cmd_pos = 0;
+       int tms_len;
        enum tap_state saved_end_state = end_state;
 
        if (cur_state != TAP_IDLE)
        {
+               // enter into IDLE state
                vsllink_end_state(TAP_IDLE);
-
-               if (vsllink_tms_data_len > 0)
-               {
-                       VSLLINK_add_tms_from_RTI(end_state);
-               }
-               else
-               {
-                       first_tms = 1;
-               }
+               vsllink_state_move();
        }
-
-       if (vsllink_tms_data_len > 0)
+       else
        {
                // cur_state == TAP_IDLE
-               if ((vsllink_tms_data_len + num_cycles) < 8)
-               {
-                       vsllink_tms_data_len += num_cycles;
-                       num_cycles = 0;
-               }
-               else if ((vsllink_tms_data_len + num_cycles) < 16)
-               {
-                       if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) \
-                                       < VSLLINK_CMDJTAGSEQ_LENMSK)
-                       {
-                               *vsllink_tms_cmd_pos++;
-                               vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0;
-                       }
-                       else
-                       {
-                               // need a new VSLLINK_CMDJTAGSEQ_TMSBYTE command
-                               // if vsllink_tms_data_len > 0, length of VSLLINK_CMDJTAGSEQ_TMSBYTE MUST be > 1(tms_len > 2)
-                               *vsllink_tms_cmd_pos--;
-                               vsllink_tap_ensure_space(0, 3);
-                               vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1;
-                               vsllink_tms_cmd_pos = vsllink_usb_out_buffer + vsllink_usb_out_buffer_idx;
-                               vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0;
-                       }
-                       vsllink_tms_data_len = (vsllink_tms_data_len + num_cycles) & 7;
-                       num_cycles = 0;
-               }
-               else
-               {
-                       vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0;
-                       vsllink_usb_out_buffer_idx++;
-
-                       num_cycles -= 16 - vsllink_tms_data_len;
-                       vsllink_tms_data_len = 0;
-                       vsllink_tms_cmd_pos = NULL;
-               }
-       }
-
-       tms_len = ((num_cycles + 7) >> 3) + first_tms;
-       if (tms_len > 0)
-       {
-               // Normal operation, don't need to append tms data
-               vsllink_tms_data_len = num_cycles & 7;
-
                if (vsllink_tms_data_len > 0)
                {
-                       tms_len += 1;
-               }
-               // tms_len includes the length of tms byte to append
-
-               // Make sure there is enough space
-               // 1 more byte maybe needed for the last tms move
-               vsllink_tap_ensure_space(0, (tms_len / VSLLINK_CMDJTAGSEQ_LENMSK) + tms_len + 1);
-
-               while(tms_len > 0)
-               {
-                       if (tms_len > (VSLLINK_CMDJTAGSEQ_LENMSK + 1))
+                       // there are vsllink_tms_data_len more tms bits to be shifted
+                       // so there are vsllink_tms_data_len + num_cycles tms bits in all
+                       tms_len = vsllink_tms_data_len + num_cycles;
+                       if (tms_len <= 16)
                        {
-                               i = VSLLINK_CMDJTAGSEQ_LENMSK + 1;
-                       }
-                       else
-                       {
-                               i = tms_len;
-                       }
-
-                       tms_cmd_pos = vsllink_usb_out_buffer_idx;
-
-                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | (i - 1);
+                               // merge into last tms shift
+                               if (tms_len < 8)
+                               {
+                                       // just add to vsllink_tms_data_len
+                                       // same result if tun through
+                                       //vsllink_tms_data_len += num_cycles;
+                               }
+                               else if (tms_len == 8)
+                               {
+                                       // end last tms shift command
+                                       // just reduce it, no need to append_tms
+                                       (*vsllink_tms_cmd_pos)--;
+                                       vsllink_usb_out_buffer_idx++;
+                               }
+                               else if (tms_len < 16)
+                               {
+                                       if ((*vsllink_tms_cmd_pos & VSLLINK_CMDJTAGSEQ_LENMSK) < VSLLINK_CMDJTAGSEQ_LENMSK)
+                                       {
+                                               // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most
+                                               // there is enought tms length in the current tms shift command
+                                               // increase the tms byte length by 1 and set the last byte to 0
+                                               (*vsllink_tms_cmd_pos)++;
+                                               vsllink_usb_out_buffer_idx++;
+                                               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0;
+                                       }
+                                       else
+                                       {
+                                               // every tms shift command can contain VSLLINK_CMDJTAGSEQ_LENMSK + 1 bytes in most
+                                               // not enough tms length in the current tms shift command
+                                               // so a new command should be added
+                                               // first decrease byte length of last tms shift command
+                                               (*vsllink_tms_cmd_pos)--;
+                                               // move the command pointer to the next empty position
+                                               vsllink_usb_out_buffer_idx++;
+                                               // add new command(3 bytes)
+                                               vsllink_tap_ensure_space(0, 3);
+                                               vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
+                                               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1;
+                                               vsllink_usb_out_buffer[++vsllink_usb_out_buffer_idx] = 0;
+                                       }
+                               }
+                               else if (tms_len == 16)
+                               {
+                                       // end last tms shift command
+                                       vsllink_usb_out_buffer_idx++;
+                                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0;
+                               }
 
-                       if (first_tms)
-                       {
-                               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(cur_state, end_state);
-                               first_tms = 0;
-                               j = i - 1;
+                               vsllink_tms_data_len = (vsllink_tms_data_len + num_cycles) & 7;
+                               if (vsllink_tms_data_len == 0)
+                               {
+                                       vsllink_tms_cmd_pos = NULL;
+                               }
+                               num_cycles = 0;
                        }
                        else
                        {
-                               j = i;
-                       }
-
-                       while (j-- > 0)
-                       {
+                               vsllink_usb_out_buffer_idx++;
                                vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0;
-                       }
 
-                       tms_len -= i;
+                               num_cycles -= 16 - vsllink_tms_data_len;
+                               vsllink_tms_data_len = 0;
+                               vsllink_tms_cmd_pos = NULL;
+                       }
                }
+       }
+       // from here vsllink_tms_data_len == 0 or num_cycles == 0
 
-               // post process vsllink_usb_out_buffer_idx
-               if (vsllink_tms_data_len > 0)
+       if (vsllink_tms_data_len > 0)
+       {
+               // num_cycles == 0
+               // no need to shift
+               if (num_cycles > 0)
                {
-                       vsllink_usb_out_buffer_idx -= 2;
+                       LOG_ERROR("There MUST be some bugs in the driver");
+                       exit(-1);
                }
-
-               // Set end_state
-               vsllink_end_state(saved_end_state);
-               cur_state = TAP_IDLE;
-               if (saved_end_state != TAP_IDLE)
+       }
+       else
+       {
+               // get number of bytes left to be sent
+               tms_len = num_cycles >> 3;
+               if (tms_len > 0)
                {
-                       if (vsllink_tms_data_len > 0)
-                       {
-                               VSLLINK_add_tms_from_RTI(end_state);
-                       }
-                       else
+                       vsllink_tap_ensure_space(1, 5);
+                       // if tms_len > 0, vsllink_tms_data_len == 0
+                       // so just add new command
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMS0BYTE;
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 0) & 0xff;
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 8) & 0xff;
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 16) & 0xff;
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = (tms_len >> 24) & 0xff;
+
+                       vsllink_usb_in_want_length += 1;
+                       pending_scan_results_buffer[pending_scan_results_length].buffer = NULL;
+                       pending_scan_results_length++;
+
+                       if (tms_len > 0xFFFF)
                        {
-                               if (i < (VSLLINK_CMDJTAGSEQ_LENMSK + 1))
-                               {
-                                       vsllink_usb_out_buffer[tms_cmd_pos]++;
-                                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(TAP_IDLE, end_state);
-                               }
-                               else
-                               {
-                                       vsllink_tap_ensure_space(0, 2);
-                                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE;
-                                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(TAP_IDLE, end_state);
-                               }
+                               vsllink_tap_execute();
+                               vsllink_usb_out_buffer[0] = VSLLINK_CMD_HW_JTAGSEQCMD;
+                               vsllink_usb_out_buffer_idx = 3;
                        }
-                       cur_state = saved_end_state;
                }
 
+               vsllink_tms_data_len = num_cycles & 7;
                if (vsllink_tms_data_len > 0)
                {
-                       vsllink_tms_cmd_pos = vsllink_usb_out_buffer + tms_cmd_pos;
+                       vsllink_tap_ensure_space(0, 3);
+                       vsllink_tms_cmd_pos = &vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE | 1;
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] = 0;
                }
        }
-       else
-       {
-               // Set end_state if no RTI shifts
-               vsllink_end_state(saved_end_state);
-               cur_state = TAP_IDLE;
-               if (saved_end_state != TAP_IDLE)
-               {
-                       vsllink_tap_ensure_space(0, 2);
-                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_TMSBYTE;
-                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(TAP_IDLE, end_state);
 
-                       cur_state = saved_end_state;
-               }
+       // post-process
+       // set end_state
+       vsllink_end_state(saved_end_state);
+       cur_state = TAP_IDLE;
+       if (end_state != TAP_IDLE)
+       {
+               vsllink_state_move();
        }
 }
 
@@ -861,6 +904,11 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s
        u8 bits_left, tms_tmp, tdi_len;
        int i;
 
+       if (0 == scan_size )
+       {
+               return;
+       }
+
        tdi_len = ((scan_size + 7) >> 3);
        if ((tdi_len + 7) > VSLLINK_BufferSize)
        {
@@ -877,10 +925,27 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s
        {
                if (cur_state == end_state)
                {
-                       *vsllink_tms_cmd_pos--;
-                       tms_tmp = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
-                       vsllink_tap_ensure_space(1, tdi_len + 7);
+                       // already in IRSHIFT or DRSHIFT state
+                       // merge tms data in the last tms shift command into next scan command
+                       if(*vsllink_tms_cmd_pos < 1)
+                       {
+                               LOG_ERROR("There MUST be some bugs in the driver");
+                               exit(-1);
+                       }
+                       else if(*vsllink_tms_cmd_pos < 2)
+                       {
+                               tms_tmp = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
+                               vsllink_usb_out_buffer_idx--;
+                       }
+                       else
+                       {
+                               tms_tmp = vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx];
+                               *vsllink_tms_cmd_pos -= 2;
+                       }
 
+                       vsllink_tap_ensure_space(1, tdi_len + 7);
+                       // VSLLINK_CMDJTAGSEQ_SCAN ored by 1 means that tms_before is valid 
+                       // which is merged from the last tms shift command
                        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_SCAN | 1;
                        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = ((tdi_len + 1) >> 0) & 0xff;
                        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = ((tdi_len + 1)>> 8) & 0xff;
@@ -898,10 +963,11 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s
 
                        vsllink_tap_append_scan(scan_size - vsllink_tms_data_len, buffer, command, vsllink_tms_data_len);
                        scan_size -= 8 - vsllink_tms_data_len;
+                       vsllink_tms_data_len = 0;
                }
                else
                {
-                       VSLLINK_add_tms_from_RTI(end_state);
+                       vsllink_append_tms();
                        vsllink_tap_ensure_space(1, tdi_len + 5);
 
                        vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_CMDJTAGSEQ_SCAN;
@@ -939,7 +1005,7 @@ void vsllink_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size, s
 
        if (cur_state != end_state)
        {
-               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE_FROM_E1[tap_move_map[end_state]];
+               vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = VSLLINK_TAP_MOVE(cur_state, end_state);
        }
        else
        {
@@ -1041,19 +1107,6 @@ int vsllink_handle_usb_bulkout_command(struct command_context_s *cmd_ctx, char *
 /***************************************************************************/
 /* VSLLink tap functions */
 
-typedef struct
-{
-       int length; /* Number of bits to read */
-       int offset;
-       scan_command_t *command; /* Corresponding scan command */
-       u8 *buffer;
-} pending_scan_result_t;
-
-#define MAX_PENDING_SCAN_RESULTS 256
-
-static int pending_scan_results_length;
-static pending_scan_result_t pending_scan_results_buffer[MAX_PENDING_SCAN_RESULTS];
-
 void vsllink_tap_init(void)
 {
        vsllink_usb_out_buffer_idx = 0;
@@ -1101,7 +1154,7 @@ void vsllink_tap_append_scan(int length, u8 *buffer, scan_command_t *command, in
 }
 
 /* Pad and send a tap sequence to the device, and receive the answer.
- * For the purpose of padding we assume that we are in idle or pause state. */
+ * For the purpose of padding we assume that we are in reset or idle or pause state. */
 int vsllink_tap_execute(void)
 {
        int i;
@@ -1110,13 +1163,17 @@ int vsllink_tap_execute(void)
 
        if (vsllink_tms_data_len > 0)
        {
+               if((cur_state != TAP_RESET) && (cur_state != TAP_IDLE) && (cur_state != TAP_IRPAUSE) && (cur_state != TAP_DRPAUSE))
+               {
+                       LOG_WARNING("%s is not in RESET or IDLE or PAUSR state", jtag_state_name(cur_state));
+               }
+
                if (vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx] & (1 << (vsllink_tms_data_len - 1)))
                {
                        // last tms bit is '1'
-                       // the only possible state is TLR, no need to control the number of shifts in RLT
-                       // There MUST be some errors in the code
-                       LOG_ERROR("last tms bit is '1'");
-                       exit(-1);
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] |= 0xFF << vsllink_tms_data_len;
+                       vsllink_usb_out_buffer[vsllink_usb_out_buffer_idx++] = 0xFF;
+                       vsllink_tms_data_len = 0;
                }
                else
                {
@@ -1146,27 +1203,31 @@ int vsllink_tap_execute(void)
                                int length = pending_scan_result->length;
                                int offset = pending_scan_result->offset;
                                scan_command_t *command = pending_scan_result->command;
+
+                               if (buffer != NULL)
+                               {
+                                       // IRSHIFT or DRSHIFT
+                                       buf_set_buf(vsllink_usb_in_buffer, first * 8 + offset, buffer, 0, length);
+                                       first += (length + offset + 7) >> 3;
        
-                               /* Copy to buffer */
-                               buf_set_buf(vsllink_usb_in_buffer, first * 8 + offset, buffer, 0, length);
-                               first += (length + offset + 7) >> 3;
-       
-                               DEBUG_JTAG_IO("JTAG scan read(%d bits):", length);
+                                       DEBUG_JTAG_IO("JTAG scan read(%d bits):", length);
 #ifdef _DEBUG_JTAG_IO_
-                               vsllink_debug_buffer(buffer, (length + 7) >> 3);
+                                       vsllink_debug_buffer(buffer, (length + 7) >> 3);
 #endif
 
-                               if (jtag_read_buffer(buffer, command) != ERROR_OK)
-                               {
-                                       vsllink_tap_init();
-                                       return ERROR_JTAG_QUEUE_FAILED;
-                               }
-               
-                               if (pending_scan_result->buffer != NULL)
-                               {
+                                       if (jtag_read_buffer(buffer, command) != ERROR_OK)
+                                       {
+                                               vsllink_tap_init();
+                                               return ERROR_JTAG_QUEUE_FAILED;
+                                       }
+
                                        free(pending_scan_result->buffer);
                                        pending_scan_result->buffer = NULL;
                                }
+                               else
+                               {
+                                       first++;
+                               }
                        }
                }
                else
index df4f8a9fc38fc11e0e57d3bee073ef7fe82223e0..96b48b80f5ef68f962ead2612f575e6c097acb68 100644 (file)
@@ -35,6 +35,7 @@
 #include "jtag.h"
 #include "configuration.h"
 #include "xsvf.h"
+#include "svf.h"
 #include "target.h"
 #include "flash.h"
 #include "nand.h"
@@ -209,6 +210,7 @@ command_context_t *setup_command_handler(void)
        log_register_commands(cmd_ctx);
        jtag_register_commands(cmd_ctx);
        xsvf_register_commands(cmd_ctx);
+       svf_register_commands(cmd_ctx);
        target_register_commands(cmd_ctx);
        flash_register_commands(cmd_ctx);
        nand_register_commands(cmd_ctx);
diff --git a/src/svf/Makefile.am b/src/svf/Makefile.am
new file mode 100644 (file)
index 0000000..fa789d6
--- /dev/null
@@ -0,0 +1,5 @@
+INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper       -I$(top_srcdir)/src/jtag $(all_includes)
+METASOURCES = AUTO
+noinst_LIBRARIES = libsvf.a
+noinst_HEADERS = svf.h
+libsvf_a_SOURCES = svf.c
diff --git a/src/svf/Makefile.in b/src/svf/Makefile.in
new file mode 100644 (file)
index 0000000..adb8545
--- /dev/null
@@ -0,0 +1,406 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/svf
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+libsvf_a_AR = $(AR) $(ARFLAGS)
+libsvf_a_LIBADD =
+am_libsvf_a_OBJECTS = svf.$(OBJEXT)
+libsvf_a_OBJECTS = $(am_libsvf_a_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libsvf_a_SOURCES)
+DIST_SOURCES = $(libsvf_a_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper       -I$(top_srcdir)/src/jtag $(all_includes)
+METASOURCES = AUTO
+noinst_LIBRARIES = libsvf.a
+noinst_HEADERS = svf.h
+libsvf_a_SOURCES = svf.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/svf/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/svf/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLIBRARIES:
+       -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libsvf.a: $(libsvf_a_OBJECTS) $(libsvf_a_DEPENDENCIES) 
+       -rm -f libsvf.a
+       $(libsvf_a_AR) libsvf.a $(libsvf_a_OBJECTS) $(libsvf_a_LIBADD)
+       $(RANLIB) libsvf.a
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svf.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-noinstLIBRARIES ctags distclean distclean-compile \
+       distclean-generic distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+       uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/svf/svf.c b/src/svf/svf.c
new file mode 100644 (file)
index 0000000..baa0088
--- /dev/null
@@ -0,0 +1,1305 @@
+/***************************************************************************
+ *      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:
+ * http://www.asset-intertech.com/support/svf.pdf
+ * Below, this document is refered to as the "SVF spec".
+ *
+ * The specification for XSVF is available here:
+ * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf
+ * Below, this document is refered to as the "XSVF spec".
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "svf.h"
+
+#include "jtag.h"
+#include "command.h"
+#include "log.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+// SVF command
+typedef enum
+{
+       ENDDR,
+       ENDIR,
+       FREQUENCY,
+       HDR,
+       HIR,
+       PIO,
+       PIOMAP,
+       RUNTEST,
+       SDR,
+       SIR,
+       STATE,
+       TDR,
+       TIR,
+       TRST,
+}svf_command_t;
+
+const char *svf_command_name[14] = 
+{
+       "ENDDR",
+       "ENDIR",
+       "FREQUENCY",
+       "HDR",
+       "HIR",
+       "PIO",
+       "PIOMAP",
+       "RUNTEST",
+       "SDR",
+       "SIR",
+       "STATE",
+       "TDR",
+       "TIR",
+       "TRST"
+};
+
+typedef enum
+{
+       TRST_ON,
+       TRST_OFF,
+       TRST_Z,
+       TRST_ABSENT
+}trst_mode_t;
+
+const char *svf_trst_mode_name[4] =
+{
+       "ON",
+       "OFF",
+       "Z",
+       "ABSENT"
+};
+
+char *svf_tap_state_name[16];
+
+#define XXR_TDI                                                (1 << 0)
+#define XXR_TDO                                                (1 << 1)
+#define XXR_MASK                                       (1 << 2)
+#define XXR_SMASK                                      (1 << 3)
+typedef struct
+{
+       int len;
+       int data_mask;
+       u8 *tdi;
+       u8 *tdo;
+       u8 *mask;
+       u8 *smask;
+}svf_xxr_para_t;
+
+typedef struct
+{
+       float frequency;
+       tap_state_t ir_end_state;
+       tap_state_t dr_end_state;
+       tap_state_t runtest_run_state;
+       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;
+
+svf_para_t svf_para;
+const svf_para_t 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,
+//     hir_para
+//     {len,   data_mask,      tdi,    tdo,    mask,   smask},
+       {0,             0,                      NULL,   NULL,   NULL,   NULL},
+//     hdr_para
+//     {len,   data_mask,      tdi,    tdo,    mask,   smask},
+       {0,             0,                      NULL,   NULL,   NULL,   NULL},
+//     tir_para
+//     {len,   data_mask,      tdi,    tdo,    mask,   smask},
+       {0,             0,                      NULL,   NULL,   NULL,   NULL},
+//     tdr_para
+//     {len,   data_mask,      tdi,    tdo,    mask,   smask},
+       {0,             0,                      NULL,   NULL,   NULL,   NULL},
+//     sir_para
+//     {len,   data_mask,      tdi,    tdo,    mask,   smask},
+       {0,             0,                      NULL,   NULL,   NULL,   NULL},
+//     sdr_para
+//     {len,   data_mask,      tdi,    tdo,    mask,   smask},
+       {0,             0,                      NULL,   NULL,   NULL,   NULL},
+};
+
+typedef struct
+{
+       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 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_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_fd = 0;
+static char *svf_command_buffer = NULL;
+static int svf_command_buffer_size = 0;
+static int svf_line_number = 1;
+
+static jtag_tap_t *tap = NULL;
+
+#define SVF_MAX_BUFFER_SIZE_TO_COMMIT  (4 * 1024)
+static u8 *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
+static int svf_buffer_index = 0, svf_buffer_size = 0;
+
+
+int svf_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "svf", handle_svf_command,
+               COMMAND_EXEC, "run svf <file>");
+
+       return ERROR_OK;
+}
+
+void svf_free_xxd_para(svf_xxr_para_t *para)
+{
+       if (NULL != para)
+       {
+               if (para->tdi != NULL)
+               {
+                       free(para->tdi);
+                       para->tdi = NULL;
+               }
+               if (para->tdo != NULL)
+               {
+                       free(para->tdo);
+                       para->tdo = NULL;
+               }
+               if (para->mask != NULL)
+               {
+                       free(para->mask);
+                       para->mask = NULL;
+               }
+               if (para->smask != NULL)
+               {
+                       free(para->smask);
+                       para->smask = NULL;
+               }
+       }
+}
+
+static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int command_num = 0, i;
+       int ret = ERROR_OK;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: svf <file>");
+               return ERROR_FAIL;
+       }
+
+       if ((svf_fd = open(args[0], O_RDONLY)) < 0)
+       {
+               command_print(cmd_ctx, "file \"%s\" not found", args[0]);
+               return ERROR_FAIL;
+       }
+
+       LOG_USER("svf processing file: \"%s\"", args[0]);
+
+       // 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);
+       if (NULL == svf_check_tdo_para)
+       {
+               LOG_ERROR("not enough memory");
+               ret = ERROR_FAIL;
+               goto free_all;
+       }
+
+       svf_buffer_index = 0;
+       // double the buffer size
+       // in case current command cannot be commited, 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);
+       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);
+       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);
+       if (NULL == svf_mask_buffer)
+       {
+               LOG_ERROR("not enough memory");
+               ret = ERROR_FAIL;
+               goto free_all;
+       }
+       svf_buffer_size = 2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT;
+
+       memcpy(&svf_para, &svf_para_init, sizeof(svf_para));
+       for (i = 0; i < dimof(svf_tap_state_name); i++)
+       {
+               svf_tap_state_name[i] = (char *)jtag_state_name(i);
+       }
+       // TAP_RESET
+       jtag_add_tlr();
+
+       while ( ERROR_OK == svf_read_command_from_file(svf_fd) )
+       {
+               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;
+                       break;
+               }
+               command_num++;
+       }
+       if (ERROR_OK != jtag_execute_queue())
+       {
+               ret = ERROR_FAIL;
+       }
+       else if (ERROR_OK != svf_check_tdo())
+       {
+               ret = ERROR_FAIL;
+       }
+
+free_all:
+
+       close(svf_fd);
+       svf_fd = 0;
+
+       // free buffers
+       if (svf_command_buffer)
+       {
+               free(svf_command_buffer);
+               svf_command_buffer = NULL;
+               svf_command_buffer_size = 0;
+       }
+       if (svf_check_tdo_para)
+       {
+               free(svf_check_tdo_para);
+               svf_check_tdo_para = NULL;
+               svf_check_tdo_para_index = 0;
+       }
+       if (svf_tdi_buffer)
+       {
+               free(svf_tdi_buffer);
+               svf_tdi_buffer = NULL;
+       }
+       if (svf_tdo_buffer)
+       {
+               free(svf_tdo_buffer);
+               svf_tdo_buffer = NULL;
+       }
+       if (svf_mask_buffer)
+       {
+               free(svf_mask_buffer);
+               svf_mask_buffer = NULL;
+       }
+       svf_buffer_index = 0;
+       svf_buffer_size = 0;
+
+       svf_free_xxd_para(&svf_para.hdr_para);
+       svf_free_xxd_para(&svf_para.hir_para);
+       svf_free_xxd_para(&svf_para.tdr_para);
+       svf_free_xxd_para(&svf_para.tir_para);
+       svf_free_xxd_para(&svf_para.sdr_para);
+       svf_free_xxd_para(&svf_para.sir_para);
+
+       if (ERROR_OK == ret)
+       {
+               command_print(cmd_ctx, "svf file programmed successfully for %d commands", command_num);
+       }
+       else
+       {
+               command_print(cmd_ctx, "svf file programmed failed");
+       }
+
+       return ret;
+}
+
+#define SVFP_CMD_INC_CNT                       1024
+static int svf_read_command_from_file(int fd)
+{
+       char ch, *tmp_buffer = NULL;
+       int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
+
+       while (!cmd_ok && (read(fd, &ch, 1) > 0) )
+       {
+               switch(ch)
+               {
+               case '!':
+                       slash = 0;
+                       comment = 1;
+                       break;
+               case '/':
+                       if (++slash == 2)
+                       {
+                               comment = 1;
+                       }
+                       break;
+               case ';':
+                       slash = 0;
+                       if (!comment)
+                       {
+                               cmd_ok = 1;
+                       }
+                       break;
+               case '\n':
+                       svf_line_number++;
+               case '\r':
+                       slash = 0;
+                       comment = 0;
+                       break;
+               default:
+                       if (!comment)
+                       {
+                               if (cmd_pos >= svf_command_buffer_size - 1)
+                               {
+                                       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;
+                               }
+                               svf_command_buffer[cmd_pos++] = (char)toupper(ch);
+                       }
+                       break;
+               }
+       }
+
+       if (cmd_ok)
+       {
+               svf_command_buffer[cmd_pos] = '\0';
+               return ERROR_OK;
+       }
+       else
+       {
+               return ERROR_FAIL;
+       }
+}
+
+static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
+{
+       int pos = 0, num = 0, space_found = 1;
+
+       while (pos < len)
+       {
+               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;
+               default:
+                       if (space_found)
+                       {
+                               argus[num++] = &str[pos];
+                               space_found = 0;
+                       }
+                       break;
+               }
+               pos++;
+       }
+
+       *num_of_argu = num;
+
+       return ERROR_OK;
+}
+
+static int 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 < sizeof(svf_tap_state_name)));
+}
+
+static int svf_find_string_in_array(char *str, char **strs, int num_of_element)
+{
+       int i;
+
+       for (i = 0; i < num_of_element; i++)
+       {
+               if (!strcmp(str, strs[i]))
+               {
+                       return i;
+               }
+       }
+       return 0xFF;
+}
+
+static int svf_adjust_array_length(u8 **arr, int orig_bit_len, int new_bit_len)
+{
+       int new_byte_len = (new_bit_len + 7) >> 3;
+
+       if ((NULL == *arr) || (((orig_bit_len + 7) >> 3) < ((new_bit_len + 7) >> 3)))
+       {
+               if (*arr != NULL)
+               {
+                       free(*arr);
+                       *arr = NULL;
+               }
+               *arr = (u8*)malloc(new_byte_len);
+               if (NULL == *arr)
+               {
+                       LOG_ERROR("not enough memory");
+                       return ERROR_FAIL;
+               }
+               memset(*arr, 0, new_byte_len);
+       }
+       return ERROR_OK;
+}
+
+static int svf_copy_hexstring_to_binary(char *str, u8 **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;
+
+       if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len))
+       {
+               LOG_ERROR("fail to adjust length of array");
+               return ERROR_FAIL;
+       }
+
+       if (str_byte_len > str_len)
+       {
+               loop_cnt = str_byte_len;
+       }
+       else
+       {
+               loop_cnt = str_len;
+       }
+
+       for (i = 0; i < loop_cnt; i++)
+       {
+               if (i < str_len)
+               {
+                       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
+                       {
+                               LOG_ERROR("invalid hex string");
+                               return ERROR_FAIL;
+                       }
+               }
+               else
+               {
+                       ch = 0;
+               }
+
+               // check valid
+               if (i >= str_byte_len)
+               {
+                       // 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;
+                       }
+               }
+               else if (i == (str_byte_len - 1))
+               {
+                       // last data byte, written if valid
+                       if ((ch & ~((1 << (bit_len - 4 * i)) - 1)) != 0)
+                       {
+                               LOG_ERROR("value execede length");
+                               return ERROR_FAIL;
+                       }
+               }
+
+               if (need_write)
+               {
+                       // write bin
+                       if (i % 2)
+                       {
+                               // MSB
+                               (*bin)[i / 2] |= ch << 4;
+                       }
+                       else
+                       {
+                               // LSB
+                               (*bin)[i / 2] = 0;
+                               (*bin)[i / 2] |= ch;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int svf_check_tdo(void)
+{
+       int i, j, byte_len, index;
+
+       for (i = 0; i < svf_check_tdo_para_index; i++)
+       {
+               if (svf_check_tdo_para[i].enabled)
+               {
+                       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])
+                               {
+                                       LOG_ERROR("tdo check error at line %d, read = 0x%X, want = 0x%X, mask = 0x%X", 
+                                                               svf_check_tdo_para[i].line_num, 
+                                                               (*(int*)(svf_tdi_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1), 
+                                                               (*(int*)(svf_tdo_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1), 
+                                                               (*(int*)(svf_mask_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1));
+                                       return ERROR_FAIL;
+                               }
+                       }
+               }
+       }
+       svf_check_tdo_para_index = 0;
+
+       return ERROR_OK;
+}
+
+static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len)
+{
+       if (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE)
+       {
+               LOG_ERROR("toooooo many operation undone");
+               return ERROR_FAIL;
+       }
+
+       svf_check_tdo_para[svf_check_tdo_para_index].line_num = svf_line_number;
+       svf_check_tdo_para[svf_check_tdo_para_index].bit_len = bit_len;
+       svf_check_tdo_para[svf_check_tdo_para_index].enabled = enabled;
+       svf_check_tdo_para[svf_check_tdo_para_index].buffer_offset = buffer_offset;
+       svf_check_tdo_para_index++;
+
+       return ERROR_OK;
+}
+
+// not good to use this
+extern jtag_command_t** jtag_get_last_command_p(void);
+extern void* cmd_queue_alloc(size_t size);
+extern jtag_command_t **last_comand_pointer;
+
+static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str)
+{
+       char *argus[256], command;
+       int num_of_argu = 0, i;
+
+       // tmp variable
+       int i_tmp;
+
+       // not good to use this
+       jtag_command_t **last_cmd;
+
+       // for RUNTEST
+       int run_count;
+       float min_time, max_time;
+       // for XXR
+       svf_xxr_para_t *xxr_para_tmp;
+       u8 **pbuffer_tmp;
+       scan_field_t field;
+       // for STATE
+       tap_state_t *path = NULL, state;
+
+       LOG_DEBUG("%s", cmd_str);
+
+       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)
+       {
+       case ENDDR:
+       case ENDIR:
+               if (num_of_argu != 2)
+               {
+                       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));
+               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]);
+                       }
+                       else
+                       {
+                               svf_para.dr_end_state = i_tmp;
+                               LOG_DEBUG("\tdr_end_state = %s", svf_tap_state_name[svf_para.dr_end_state]);
+                       }
+               }
+               else
+               {
+                       LOG_ERROR("%s is not valid state", argus[1]);
+                       return ERROR_FAIL;
+               }
+               break;
+       case FREQUENCY:
+               if ((num_of_argu != 1) && (num_of_argu != 3))
+               {
+                       LOG_ERROR("invalid parameter of %s", argus[0]);
+                       return ERROR_FAIL;
+               }
+               if (1 == num_of_argu)
+               {
+                       // TODO: set jtag speed to full speed
+                       svf_para.frequency = 0;
+               }
+               else
+               {
+                       if (strcmp(argus[2], "HZ"))
+                       {
+                               LOG_ERROR("HZ not found in FREQUENCY command");
+                               return ERROR_FAIL;
+                       }
+                       svf_para.frequency = atof(argus[1]);
+                       // TODO: set jtag speed to
+                       if (svf_para.frequency > 0)
+                       {
+                               command_run_linef(cmd_ctx, "jtag_khz %d", (int)svf_para.frequency / 1000);
+                               LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
+                       }
+               }
+               break;
+       case HDR:
+               xxr_para_tmp = &svf_para.hdr_para;
+               goto XXR_common;
+       case HIR:
+               xxr_para_tmp = &svf_para.hir_para;
+               goto XXR_common;
+       case TDR:
+               xxr_para_tmp = &svf_para.tdr_para;
+               goto XXR_common;
+       case TIR:
+               xxr_para_tmp = &svf_para.tir_para;
+               goto XXR_common;
+       case SDR:
+               xxr_para_tmp = &svf_para.sdr_para;
+               goto XXR_common;
+       case SIR:
+               xxr_para_tmp = &svf_para.sir_para;
+               goto XXR_common;
+               XXR_common:
+               // XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)]
+               if ((num_of_argu > 10) || (num_of_argu % 2))
+               {
+                       LOG_ERROR("invalid parameter of %s", argus[0]);
+                       return ERROR_FAIL;
+               }
+               i_tmp = xxr_para_tmp->len;
+               xxr_para_tmp->len = atoi(argus[1]);
+               LOG_DEBUG("\tlength = %d", xxr_para_tmp->len);
+               xxr_para_tmp->data_mask = 0;
+               for (i = 2; i < num_of_argu; i += 2)
+               {
+                       if ((argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')'))
+                       {
+                               LOG_ERROR("data section error");
+                               return ERROR_FAIL;
+                       }
+                       argus[i + 1][strlen(argus[i + 1]) - 1] = '\0';
+                       // TDI, TDO, MASK, SMASK
+                       if (!strcmp(argus[i], "TDI"))
+                       {
+                               // TDI
+                               pbuffer_tmp = &xxr_para_tmp->tdi;
+                               xxr_para_tmp->data_mask |= XXR_TDI;
+                       }
+                       else if (!strcmp(argus[i], "TDO"))
+                       {
+                               // TDO
+                               pbuffer_tmp = &xxr_para_tmp->tdo;
+                               xxr_para_tmp->data_mask |= XXR_TDO;
+                       }
+                       else if (!strcmp(argus[i], "MASK"))
+                       {
+                               // MASK
+                               pbuffer_tmp = &xxr_para_tmp->mask;
+                               xxr_para_tmp->data_mask |= XXR_MASK;
+                       }
+                       else if (!strcmp(argus[i], "SMASK"))
+                       {
+                               // SMASK
+                               pbuffer_tmp = &xxr_para_tmp->smask;
+                               xxr_para_tmp->data_mask |= XXR_SMASK;
+                       }
+                       else
+                       {
+                               LOG_ERROR("unknow parameter: %s", argus[i]);
+                               return ERROR_FAIL;
+                       }
+                       if (ERROR_OK != svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp, xxr_para_tmp->len))
+                       {
+                               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));
+               }
+               // 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
+               if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len))
+               {
+                       // MASK not defined and length changed
+                       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;
+                       }
+                       buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len);
+               }
+               // do scan if necessary
+               if (SDR == command)
+               {
+                       // check buffer size first, reallocate if necessary
+                       i = svf_para.hdr_para.len + svf_para.sdr_para.len + svf_para.tdr_para.len;
+                       if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3))
+                       {
+#if 1
+                               // simply print error message
+                               LOG_ERROR("buffer is not enough, report to author");
+                               return ERROR_FAIL;
+#else
+                               u8 *buffer_tmp;
+
+                               // reallocate buffer
+                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               if (NULL == buffer_tmp)
+                               {
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
+                               }
+                               memcpy(buffer_tmp, svf_tdi_buffer, svf_buffer_index);
+                               // svf_tdi_buffer isn't NULL here
+                               free(svf_tdi_buffer);
+                               svf_tdi_buffer = buffer_tmp;
+
+                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               if (NULL == buffer_tmp)
+                               {
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
+                               }
+                               memcpy(buffer_tmp, svf_tdo_buffer, svf_buffer_index);
+                               // svf_tdo_buffer isn't NULL here
+                               free(svf_tdo_buffer);
+                               svf_tdo_buffer = buffer_tmp;
+
+                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               if (NULL == buffer_tmp)
+                               {
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
+                               }
+                               memcpy(buffer_tmp, svf_mask_buffer, svf_buffer_index);
+                               // svf_mask_buffer isn't NULL here
+                               free(svf_mask_buffer);
+                               svf_mask_buffer = buffer_tmp;
+
+                               buffer_tmp = NULL;
+                               svf_buffer_size = svf_buffer_index + ((i + 7) >> 3);
+#endif
+                       }
+
+                       // assemble dr data
+                       i = 0;
+                       buf_set_buf(svf_para.hdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hdr_para.len);
+                       i += svf_para.hdr_para.len;
+                       buf_set_buf(svf_para.sdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sdr_para.len);
+                       i += svf_para.sdr_para.len;
+                       buf_set_buf(svf_para.tdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tdr_para.len);
+                       i += svf_para.tdr_para.len;
+
+                       // add check data
+                       if (svf_para.sdr_para.data_mask & XXR_TDO)
+                       {
+                               // assemble dr mask data
+                               i = 0;
+                               buf_set_buf(svf_para.hdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hdr_para.len);
+                               i += svf_para.hdr_para.len;
+                               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);
+                               i += svf_para.hdr_para.len;
+                               buf_set_buf(svf_para.sdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sdr_para.len);
+                               i += svf_para.sdr_para.len;
+                               buf_set_buf(svf_para.tdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tdr_para.len);
+                               i += svf_para.tdr_para.len;
+
+                               svf_add_check_para(1, svf_buffer_index, i);
+                       }
+                       else
+                       {
+                               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.out_mask = NULL;
+                       field.in_value = &svf_tdi_buffer[svf_buffer_index];
+                       field.in_check_value = NULL;
+                       field.in_check_mask = NULL;
+                       field.in_handler = NULL;
+                       field.in_handler_priv = NULL;
+                       jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state);
+
+                       svf_buffer_index += (i + 7) >> 3;
+               }
+               else if (SIR == command)
+               {
+                       // check buffer size first, reallocate if necessary
+                       i = svf_para.hir_para.len + svf_para.sir_para.len + svf_para.tir_para.len;
+                       if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3))
+                       {
+#if 1
+                               // simply print error message
+                               LOG_ERROR("buffer is not enough, report to author");
+                               return ERROR_FAIL;
+#else
+                               u8 *buffer_tmp;
+
+                               // reallocate buffer
+                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               if (NULL == buffer_tmp)
+                               {
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
+                               }
+                               memcpy(buffer_tmp, svf_tdi_buffer, svf_buffer_index);
+                               // svf_tdi_buffer isn't NULL here
+                               free(svf_tdi_buffer);
+                               svf_tdi_buffer = buffer_tmp;
+
+                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               if (NULL == buffer_tmp)
+                               {
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
+                               }
+                               memcpy(buffer_tmp, svf_tdo_buffer, svf_buffer_index);
+                               // svf_tdo_buffer isn't NULL here
+                               free(svf_tdo_buffer);
+                               svf_tdo_buffer = buffer_tmp;
+
+                               buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3));
+                               if (NULL == buffer_tmp)
+                               {
+                                       LOG_ERROR("not enough memory");
+                                       return ERROR_FAIL;
+                               }
+                               memcpy(buffer_tmp, svf_mask_buffer, svf_buffer_index);
+                               // svf_mask_buffer isn't NULL here
+                               free(svf_mask_buffer);
+                               svf_mask_buffer = buffer_tmp;
+
+                               buffer_tmp = NULL;
+                               svf_buffer_size = svf_buffer_index + ((i + 7) >> 3);
+#endif
+                       }
+
+                       // assemble ir data
+                       i = 0;
+                       buf_set_buf(svf_para.hir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hir_para.len);
+                       i += svf_para.hir_para.len;
+                       buf_set_buf(svf_para.sir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sir_para.len);
+                       i += svf_para.sir_para.len;
+                       buf_set_buf(svf_para.tir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tir_para.len);
+                       i += svf_para.tir_para.len;
+
+                       // add check data
+                       if (svf_para.sir_para.data_mask & XXR_TDO)
+                       {
+                               // assemble dr mask data
+                               i = 0;
+                               buf_set_buf(svf_para.hir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hir_para.len);
+                               i += svf_para.hir_para.len;
+                               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);
+                               i += svf_para.hir_para.len;
+                               buf_set_buf(svf_para.sir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sir_para.len);
+                               i += svf_para.sir_para.len;
+                               buf_set_buf(svf_para.tir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tir_para.len);
+                               i += svf_para.tir_para.len;
+
+                               svf_add_check_para(1, svf_buffer_index, i);
+                       }
+                       else
+                       {
+                               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.out_mask = NULL;
+                       field.in_value = &svf_tdi_buffer[svf_buffer_index];
+                       field.in_check_value = NULL;
+                       field.in_check_mask = NULL;
+                       field.in_handler = NULL;
+                       field.in_handler_priv = NULL;
+                       jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state);
+
+                       svf_buffer_index += (i + 7) >> 3;
+               }
+               break;
+       case PIO:
+       case PIOMAP:
+               LOG_ERROR("PIO and PIOMAP are not supported");
+               return ERROR_FAIL;
+               break;
+       case RUNTEST:
+               // RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time SEC]] [ENDSTATE end_state]
+               // RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE end_state]
+               if ((num_of_argu < 3) && (num_of_argu > 11))
+               {
+                       LOG_ERROR("invalid parameter of %s", argus[0]);
+                       return ERROR_FAIL;
+               }
+               // 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))
+               {
+                       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
+                               svf_para.runtest_end_state = i_tmp;
+                               LOG_DEBUG("\trun_state = %s", svf_tap_state_name[svf_para.runtest_run_state]);
+                               i++;
+                       }
+                       else
+                       {
+                               LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]);
+                               return ERROR_FAIL;
+                       }
+               }
+               // run_count run_clk
+               if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC"))
+               {
+                       if (!strcmp(argus[i + 1], "TCK"))
+                       {
+                               // clock source is TCK
+                               run_count = atoi(argus[i]);
+                               LOG_DEBUG("\trun_count@TCK = %d", run_count);
+                       }
+                       else
+                       {
+                               LOG_ERROR("%s not supported for clock", argus[i + 1]);
+                               return ERROR_FAIL;
+                       }
+                       i += 2;
+               }
+               // min_time SEC
+               if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC"))
+               {
+                       min_time = atof(argus[i]);
+                       LOG_DEBUG("\tmin_time = %fs", min_time);
+                       i += 2;
+               }
+               // MAXIMUM max_time SEC
+               if (((i + 3) <= num_of_argu) && !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC"))
+               {
+                       max_time = atof(argus[i + 1]);
+                       LOG_DEBUG("\tmax_time = %fs", max_time);
+                       i += 3;
+               }
+               // 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));
+                       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]);
+                       }
+                       else
+                       {
+                               LOG_ERROR("%s is not valid state", svf_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)
+                       {
+                               // TODO: do runtest
+                               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;
+                               }
+                               jtag_add_runtest(run_count, svf_para.runtest_end_state);
+                       }
+               }
+               else
+               {
+                       LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed", i, num_of_argu);
+                       return ERROR_FAIL;
+               }
+               break;
+       case STATE:
+               // STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state
+               if (num_of_argu < 2)
+               {
+                       LOG_ERROR("invalid parameter of %s", argus[0]);
+                       return ERROR_FAIL;
+               }
+               if (num_of_argu > 2)
+               {
+                       // STATE pathstate1 ... stable_state
+                       path = (tap_state_t *)malloc((num_of_argu - 1) * sizeof(tap_state_t));
+                       if (NULL == path)
+                       {
+                               LOG_ERROR("not enough memory");
+                               return ERROR_FAIL;
+                       }
+                       for (i = 1; i < num_of_argu; i++)
+                       {
+                               path[i - 1] = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name));
+                               if (!svf_tap_state_is_valid(path[i - 1]))
+                               {
+                                       LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i - 1]]);
+                                       return ERROR_FAIL;
+                               }
+                               if (TAP_RESET == path[i - 1])
+                               {
+                                       LOG_ERROR("TAP_RESET is not allowed in pathmove");
+                                       return ERROR_FAIL;
+                               }
+                       }
+                       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 - 1, path);
+                               LOG_DEBUG("\tmove to %s by path_move", svf_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]]);
+                               return ERROR_FAIL;
+                       }
+                       if (NULL != path)
+                       {
+                               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));
+                       if (svf_tap_state_is_stable(state))
+                       {
+                               // TODO: move to state
+                               last_cmd = jtag_get_last_command_p();
+                               *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+                               last_comand_pointer = &((*last_cmd)->next);
+                               (*last_cmd)->next = NULL;
+                               (*last_cmd)->type = JTAG_STATEMOVE;
+                               (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+                               (*last_cmd)->cmd.statemove->end_state = state;
+
+                               LOG_DEBUG("\tmove to %s by state_move", svf_tap_state_name[state]);
+                       }
+                       else
+                       {
+                               LOG_ERROR("%s is not valid state", svf_tap_state_name[state]);
+                               return ERROR_FAIL;
+                       }
+               }
+               break;
+       case TRST:
+               // TRST trst_mode
+               if (num_of_argu != 2)
+               {
+                       LOG_ERROR("invalid parameter of %s", argus[0]);
+                       return ERROR_FAIL;
+               }
+               if (svf_para.trst_mode != TRST_ABSENT)
+               {
+                       i_tmp = svf_find_string_in_array(argus[1], (char **)svf_trst_mode_name, dimof(svf_trst_mode_name));
+                       switch (i_tmp)
+                       {
+                       case TRST_ON:
+                               jtag_add_reset(1, 0);
+                               break;
+                       case TRST_OFF:
+                               jtag_add_reset(1, 1);
+                               break;
+                       case TRST_Z:
+                               break;
+                       case TRST_ABSENT:
+                               break;
+                       default:
+                               LOG_ERROR("unknown TRST mode: %s", argus[1]);
+                               return ERROR_FAIL;
+                       }
+                       svf_para.trst_mode = i_tmp;
+                       LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]);
+               }
+               else
+               {
+                       LOG_ERROR("can not accpet TRST command if trst_mode is ABSENT");
+                       return ERROR_FAIL;
+               }
+               break;
+       default:
+               LOG_ERROR("invalid svf command: %s", argus[0]);
+               return ERROR_FAIL;
+               break;
+       }
+
+       if (debug_level >= LOG_LVL_DEBUG)
+       {
+               // for convenient debugging, execute tap if possible
+               if ((svf_buffer_index > 0) && \
+                       (((command != STATE) && (command != RUNTEST)) || \
+                       ((command == STATE) && (num_of_argu == 2))))
+               {
+                       // there is data to be executed
+                       if (ERROR_OK != jtag_execute_queue())
+                       {
+                               return ERROR_FAIL;
+                       }
+                       // output debug info
+                       if ((SIR == command) || (SDR == command))
+                       {
+                               LOG_DEBUG("\tTDO read = 0x%X", (*(int*)svf_tdi_buffer) & ((1 << (svf_check_tdo_para[0].bit_len)) - 1));
+                       }
+                       if (ERROR_OK != svf_check_tdo())
+                       {
+                               return ERROR_FAIL;
+                       }
+
+                       svf_buffer_index = 0;
+               }
+       }
+       else
+       {
+               // for fast executing, execute tap if necessary
+               // half of the buffer is for the next command
+               if (((svf_buffer_index >= SVF_MAX_BUFFER_SIZE_TO_COMMIT) || (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE / 2)) && \
+                       (((command != STATE) && (command != RUNTEST)) || \
+                       ((command == STATE) && (num_of_argu == 2))))
+               {
+                       if (ERROR_OK != jtag_execute_queue())
+                       {
+                               return ERROR_FAIL;
+                       }
+                       else if (ERROR_OK != svf_check_tdo())
+                       {
+                               return ERROR_FAIL;
+                       }
+
+                       svf_buffer_index = 0;
+               }
+       }
+
+       return ERROR_OK;
+}
diff --git a/src/svf/svf.h b/src/svf/svf.h
new file mode 100644 (file)
index 0000000..822cad2
--- /dev/null
@@ -0,0 +1,27 @@
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifndef SVF_H
+#define SVF_H
+
+#include "command.h"
+
+extern int svf_register_commands(struct command_context_s *cmd_ctx);
+
+#endif /* SVF_H */

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)