added jtag_add_statemove() helper fn(actual fn written by Dick Hollonbeck, I just...
[fw/openocd] / src / jtag / jtag.c
index 0be66c286cae10eca15ea59e95fa88d34d7c1ffb..4ed08971a47ae91737e8ddce79e60c84ddfc99e7 100644 (file)
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
-#include <assert.h>
+
 
 int jtag_flush_queue_count; /* count # of flushes for profiling / debugging purposes */
 
-static void jtag_add_scan_check(void (*jtag_add_scan)(int num_fields, scan_field_t *fields, tap_state_t state),
-               int num_fields, scan_field_t *fields, tap_state_t state);
+static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state),
+               int in_num_fields, scan_field_t *in_fields, tap_state_t state);
 
 /* note that this is not marked as static as it must be available from outside jtag.c for those
    that implement the jtag_xxx() minidriver layer
@@ -89,7 +89,7 @@ static struct jtag_callback_entry *jtag_callback_queue_tail = NULL;
 
 
 jtag_command_t *jtag_command_queue = NULL;
-jtag_command_t **last_comand_pointer = &jtag_command_queue;
+jtag_command_t **last_command_pointer = &jtag_command_queue;
 static jtag_tap_t *jtag_all_taps = NULL;
 
 enum reset_types jtag_reset_config = RESET_NONE;
@@ -97,6 +97,7 @@ tap_state_t cmd_queue_end_state = TAP_RESET;
 tap_state_t cmd_queue_cur_state = TAP_RESET;
 
 int jtag_verify_capture_ir = 1;
+int jtag_verify = 1;
 
 /* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */
 static int jtag_nsrst_delay = 0; /* default to no nSRST delay */
@@ -226,7 +227,7 @@ jtag_interface_t *jtag_interfaces[] = {
        NULL,
 };
 
-jtag_interface_t *jtag = NULL;
+static jtag_interface_t *jtag = NULL;
 
 /* configuration */
 static jtag_interface_t *jtag_interface = NULL;
@@ -259,6 +260,8 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *argv
 static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args);
 
 static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 jtag_tap_t *jtag_AllTaps(void)
 {
@@ -434,9 +437,24 @@ jtag_command_t** jtag_get_last_command_p(void)
 
        return &cmd->next;*/
 
-       return last_comand_pointer;
+       return last_command_pointer;
 }
 
+
+void jtag_queue_command(jtag_command_t * cmd)
+{
+       jtag_command_t **last_cmd;
+
+       last_cmd = jtag_get_last_command_p();
+
+       *last_cmd = cmd;
+
+       (*last_cmd)->next = NULL;
+
+       last_command_pointer = &((*last_cmd)->next);
+}
+
+
 void* cmd_queue_alloc(size_t size)
 {
        cmd_queue_page_t **p_page = &cmd_queue_pages;
@@ -513,6 +531,20 @@ void cmd_queue_free(void)
        cmd_queue_pages = NULL;
 }
 
+/**
+ * Copy a scan_field_t for insertion into the queue.
+ *
+ * This allocates a new copy of out_value using cmd_queue_alloc.
+ */
+static void cmd_queue_scan_field_clone(scan_field_t * dst, const scan_field_t * src)
+{
+       dst->tap                = src->tap;
+       dst->num_bits   = src->num_bits;
+       dst->out_value  = buf_cpy(src->out_value, cmd_queue_alloc(CEIL(src->num_bits, 8)), src->num_bits);
+       dst->in_value   = src->in_value;
+}
+
+
 static void jtag_prelude1(void)
 {
        if (jtag_trst == 1)
@@ -536,166 +568,171 @@ static void jtag_prelude(tap_state_t state)
        cmd_queue_cur_state = cmd_queue_end_state;
 }
 
-void jtag_add_ir_scan_noverify(int num_fields, scan_field_t *fields, tap_state_t state)
+void jtag_add_ir_scan_noverify(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
 {
        int retval;
        jtag_prelude(state);
 
-       retval=interface_jtag_add_ir_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 
 }
 
 
-void jtag_add_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state)
+/**
+ * Generate an IR SCAN with a list of scan fields with one entry for each enabled TAP.
+ *
+ * If the input field list contains an instruction value for a TAP then that is used
+ * otherwise the TAP is set to bypass.
+ *
+ * TAPs for which no fields are passed are marked as bypassed for subsequent DR SCANs.
+ *
+ */
+void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t state)
 {
-       /* 8 x 32 bit id's is enough for all invoations */
-       int j;
-       for (j = 0; j < num_fields; j++)
+       if (jtag_verify&&jtag_verify_capture_ir)
        {
-               fields[j].check_value=NULL;
-               fields[j].check_mask=NULL;
-               /* if we are to run a verification of the ir scan, we need to get the input back.
-                * We may have to allocate space if the caller didn't ask for the input back.
-                */
-               if (jtag_verify_capture_ir)
+               /* 8 x 32 bit id's is enough for all invoations */
+
+               for (int j = 0; j < in_num_fields; j++)
                {
-                       fields[j].check_value=fields[j].tap->expected;
-                       fields[j].check_mask=fields[j].tap->expected_mask;
-               }
+                       in_fields[j].check_value=NULL;
+                       in_fields[j].check_mask=NULL;
+                       /* if we are to run a verification of the ir scan, we need to get the input back.
+                        * We may have to allocate space if the caller didn't ask for the input back.
+                        */
+                       in_fields[j].check_value=in_fields[j].tap->expected;
+                       in_fields[j].check_mask=in_fields[j].tap->expected_mask;
+               }
+               jtag_add_scan_check(jtag_add_ir_scan_noverify, in_num_fields, in_fields, state);
+       } else
+       {
+               jtag_add_ir_scan_noverify(in_num_fields, in_fields, state);
        }
-
-       jtag_add_scan_check(jtag_add_ir_scan_noverify, num_fields, fields, state);
 }
 
-int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
+/**
+ * see jtag_add_ir_scan()
+ *
+ */
+int MINIDRIVER(interface_jtag_add_ir_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
 {
-       jtag_command_t **last_cmd;
-       jtag_tap_t *tap;
-       int j;
-       int x;
-       int nth_tap;
-       int scan_size = 0;
+       size_t num_taps = jtag_NumEnabledTaps();
 
-       last_cmd = jtag_get_last_command_p();
+       jtag_command_t * cmd            = cmd_queue_alloc(sizeof(jtag_command_t));
+       scan_command_t * scan           = cmd_queue_alloc(sizeof(scan_command_t));
+       scan_field_t * out_fields       = cmd_queue_alloc(num_taps  * sizeof(scan_field_t));
 
-       /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       (*last_cmd)->next = NULL;
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->type = JTAG_SCAN;
-
-       /* allocate memory for ir scan command */
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-       (*last_cmd)->cmd.scan->ir_scan = 1;
-       x = jtag_NumEnabledTaps();
-       (*last_cmd)->cmd.scan->num_fields = x;  /* one field per device */
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(x  * sizeof(scan_field_t));
-       (*last_cmd)->cmd.scan->end_state = state;
-
-       nth_tap = -1;
-       tap = NULL;
-       for(;;){
-               int found = 0;
+       jtag_queue_command(cmd);
 
-               /* do this here so it is not forgotten */
-               tap = jtag_NextEnabledTap(tap);
-               if( tap == NULL ){
-                       break;
-               }
-               nth_tap++;
+       cmd->type                               = JTAG_SCAN;
+       cmd->cmd.scan                   = scan;
 
-               assert(nth_tap < x );
+       scan->ir_scan                   = true;
+       scan->num_fields                = num_taps;     /* one field per device */
+       scan->fields                    = out_fields;
+       scan->end_state                 = state;
 
-               scan_size = tap->ir_length;
-               (*last_cmd)->cmd.scan->fields[nth_tap].tap = tap;
-               (*last_cmd)->cmd.scan->fields[nth_tap].num_bits = scan_size;
-               (*last_cmd)->cmd.scan->fields[nth_tap].in_value = NULL; /* do not collect input for tap's in bypass */
 
-               /* search the list */
-               for (j = 0; j < num_fields; j++)
+       scan_field_t * field = out_fields;      /* keep track where we insert data */
+
+       /* loop over all enabled TAPs */
+
+       for (jtag_tap_t * tap = jtag_NextEnabledTap(NULL); tap != NULL; tap = jtag_NextEnabledTap(tap))
+       {
+               /* search the input field list for fields for the current TAP */
+
+               bool found = false;
+
+               for (int j = 0; j < in_num_fields; j++)
                {
-                       if (tap == fields[j].tap)
-                       {
-                               found = 1;
-                               (*last_cmd)->cmd.scan->fields[nth_tap].in_value = fields[j].in_value;
-                               (*last_cmd)->cmd.scan->fields[nth_tap].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                       if (tap != in_fields[j].tap)
+                               continue;
 
-                               tap->bypass = 0;
-                               break;
-                       }
+                       /* if TAP is listed in input fields, copy the value */
+
+                       found = true;
+
+                       tap->bypass = 0;
+
+                       assert(in_fields[j].num_bits == tap->ir_length); /* input fields must have the same length as the TAP's IR */
+
+                       cmd_queue_scan_field_clone(field, in_fields + j);
+
+                       break;
                }
 
                if (!found)
                {
-                       /* if a tap isn't listed, set it to BYPASS */
-                       (*last_cmd)->cmd.scan->fields[nth_tap].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                       /* if a TAP isn't listed in input fields, set it to BYPASS */
+
                        tap->bypass = 1;
+
+                       field->tap                      = tap;
+                       field->num_bits         = tap->ir_length;
+                       field->out_value        = buf_set_ones(cmd_queue_alloc(CEIL(tap->ir_length, 8)), tap->ir_length);
+                       field->in_value         = NULL; /* do not collect input for tap's in bypass */
                }
 
                /* update device information */
-               buf_cpy((*last_cmd)->cmd.scan->fields[nth_tap].out_value, tap->cur_instr, scan_size);
+               buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
+
+               field++;
        }
-       assert(nth_tap == (x-1));
+
+       assert(field == out_fields + num_taps); /* paranoia: jtag_NumEnabledTaps() and jtag_NextEnabledTap() not in sync */
 
        return ERROR_OK;
 }
 
-void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state)
+/**
+ * Duplicate the scan fields passed into the function into an IR SCAN command
+ *
+ * This function assumes that the caller handles extra fields for bypassed TAPs
+ *
+ */
+void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
 {
        int retval;
 
        jtag_prelude(state);
 
-       retval=interface_jtag_add_plain_ir_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_plain_ir_scan(in_num_fields, in_fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
 
-int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
+
+/**
+ * see jtag_add_plain_ir_scan()
+ *
+ */
+int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
 {
-       int i;
-       jtag_command_t **last_cmd;
 
-       last_cmd = jtag_get_last_command_p();
+       jtag_command_t * cmd            = cmd_queue_alloc(sizeof(jtag_command_t));
+       scan_command_t * scan           = cmd_queue_alloc(sizeof(scan_command_t));
+       scan_field_t * out_fields       = cmd_queue_alloc(in_num_fields * sizeof(scan_field_t));
+       
+       jtag_queue_command(cmd);
 
-       /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       (*last_cmd)->next = NULL;
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->type = JTAG_SCAN;
-
-       /* allocate memory for ir scan command */
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-       (*last_cmd)->cmd.scan->ir_scan = 1;
-       (*last_cmd)->cmd.scan->num_fields = num_fields;
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
-       (*last_cmd)->cmd.scan->end_state = state;
-
-       for( i = 0 ; i < num_fields ; i++ ){
-               int num_bits = fields[i].num_bits;
-               int num_bytes = CEIL(fields[i].num_bits, 8);
-               (*last_cmd)->cmd.scan->fields[i].tap = fields[i].tap;
-               (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
-               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
-               (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
-       }
-       return ERROR_OK;
-}
+       cmd->type                               = JTAG_SCAN;
+       cmd->cmd.scan                   = scan;
 
-void jtag_add_dr_scan(int num_fields, scan_field_t *fields, tap_state_t state)
-{
-       int retval;
+       scan->ir_scan                   = true;
+       scan->num_fields                = in_num_fields;
+       scan->fields                    = out_fields;
+       scan->end_state                 = state;
 
-       jtag_prelude(state);
+       for (int i = 0; i < in_num_fields; i++)
+               cmd_queue_scan_field_clone(out_fields + i, in_fields + i);
 
-       retval=interface_jtag_add_dr_scan(num_fields, fields, cmd_queue_end_state);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
+       return ERROR_OK;
 }
 
 
+
 int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits);
 
 static int jtag_check_value_mask_callback(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
@@ -703,284 +740,303 @@ static int jtag_check_value_mask_callback(u8 *in, jtag_callback_data_t data1, jt
        return jtag_check_value_inner(in, (u8 *)data1, (u8 *)data2, (int)data3);
 }
 
-static void jtag_add_scan_check(void (*jtag_add_scan)(int num_fields, scan_field_t *fields, tap_state_t state),
-               int num_fields, scan_field_t *fields, tap_state_t state)
+static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state),
+               int in_num_fields, scan_field_t *in_fields, tap_state_t state)
 {
-       for (int i=0; i<num_fields; i++)
+       for (int i = 0; i < in_num_fields; i++)
        {
-               fields[i].allocated=0;
-               fields[i].modified=0;
-               if ((fields[i].check_value!=NULL)&&(fields[i].in_value==NULL))
+               in_fields[i].allocated = 0;
+               in_fields[i].modified = 0;
+               if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value == NULL))
                {
-                       fields[i].modified=1;
+                       in_fields[i].modified = 1;
                        /* we need storage space... */
 #ifdef HAVE_JTAG_MINIDRIVER_H
-                       if (fields[i].num_bits<=32)
+                       if (in_fields[i].num_bits <= 32)
                        {
                                /* This is enough space and we're executing this synchronously */
-                               fields[i].in_value=(u8 *)&fields[i].intmp;
+                               in_fields[i].in_value = in_fields[i].intmp;
                        } else
                        {
-                               fields[i].in_value=(u8 *)malloc(CEIL(fields[i].num_bits, 8));
-                               fields[i].allocated=1;
+                               in_fields[i].in_value = (u8 *)malloc(CEIL(in_fields[i].num_bits, 8));
+                               in_fields[i].allocated = 1;
                        }
 #else
-                       fields[i].in_value=(u8 *)cmd_queue_alloc(CEIL(fields[i].num_bits, 8));
+                       in_fields[i].in_value = (u8 *)cmd_queue_alloc(CEIL(in_fields[i].num_bits, 8));
 #endif
                }
        }
 
-       jtag_add_scan(num_fields, fields, state);
+       jtag_add_scan(in_num_fields, in_fields, state);
 
-       for (int i=0; i<num_fields; i++)
+       for (int i = 0; i < in_num_fields; i++)
        {
-               if ((fields[i].check_value!=NULL)&&(fields[i].in_value!=NULL))
+               if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL))
                {
                        /* this is synchronous for a minidriver */
-                       jtag_add_callback4(jtag_check_value_mask_callback, fields[i].in_value, fields[i].check_value, fields[i].check_mask, (jtag_callback_data_t)fields[i].num_bits);
+                       jtag_add_callback4(jtag_check_value_mask_callback, in_fields[i].in_value,
+                               (jtag_callback_data_t)in_fields[i].check_value,
+                               (jtag_callback_data_t)in_fields[i].check_mask,
+                               (jtag_callback_data_t)in_fields[i].num_bits);
                }
-               if (fields[i].allocated)
+               if (in_fields[i].allocated)
                {
-                       free(fields[i].in_value);
+                       free(in_fields[i].in_value);
                }
-               if (fields[i].modified)
+               if (in_fields[i].modified)
                {
-                       fields[i].in_value=NULL;
+                       in_fields[i].in_value = NULL;
                }
        }
 }
 
-void jtag_add_dr_scan_check(int num_fields, scan_field_t *fields, tap_state_t state)
+void jtag_add_dr_scan_check(int in_num_fields, scan_field_t *in_fields, tap_state_t state)
 {
-       jtag_add_scan_check(jtag_add_dr_scan, num_fields, fields, state);
+       if (jtag_verify)
+       {
+               jtag_add_scan_check(jtag_add_dr_scan, in_num_fields, in_fields, state);
+       } else
+       {
+               jtag_add_dr_scan(in_num_fields, in_fields, state);
+       }
 }
 
 
+/**
+ * Generate a DR SCAN using the fields passed to the function
+ *
+ * For not bypassed TAPs the function checks in_fields and uses fields specified there.
+ * For bypassed TAPs the function generates a dummy 1bit field.
+ *
+ * The bypass status of TAPs is set by jtag_add_ir_scan().
+ *
+ */
+void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
+{
+       int retval;
 
+       jtag_prelude(state);
 
-int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
-{
-       int j;
-       int nth_tap;
-       int bypass_devices = 0;
-       int field_count = 0;
-       int scan_size;
+       retval=interface_jtag_add_dr_scan(in_num_fields, in_fields, cmd_queue_end_state);
+       if (retval!=ERROR_OK)
+               jtag_error=retval;
+}
 
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-       jtag_tap_t *tap;
 
+/**
+ * see jtag_add_dr_scan()
+ *
+ */
+int MINIDRIVER(interface_jtag_add_dr_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
+{
        /* count devices in bypass */
-       tap = NULL;
-       bypass_devices = 0;
-       for(;;){
-               tap = jtag_NextEnabledTap(tap);
-               if( tap == NULL ){
-                       break;
-               }
-               if( tap->bypass ){
+
+       size_t bypass_devices = 0;
+
+       for (jtag_tap_t * tap = jtag_NextEnabledTap(NULL); tap != NULL; tap = jtag_NextEnabledTap(tap))
+       {
+               if (tap->bypass)
                        bypass_devices++;
-               }
        }
 
-       /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->next = NULL;
-       (*last_cmd)->type = JTAG_SCAN;
+       jtag_command_t * cmd            = cmd_queue_alloc(sizeof(jtag_command_t));
+       scan_command_t * scan           = cmd_queue_alloc(sizeof(scan_command_t));
+       scan_field_t * out_fields       = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(scan_field_t));
+       
+       jtag_queue_command(cmd);
+       
+       cmd->type                               = JTAG_SCAN;
+       cmd->cmd.scan                   = scan;
 
-       /* allocate memory for dr scan command */
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-       (*last_cmd)->cmd.scan->ir_scan = 0;
-       (*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
-       (*last_cmd)->cmd.scan->end_state = state;
+       scan->ir_scan                   = false;
+       scan->num_fields                = in_num_fields + bypass_devices;
+       scan->fields                    = out_fields;
+       scan->end_state                 = state;
 
-       tap = NULL;
-       nth_tap = -1;
-       for(;;){
-               nth_tap++;
-               tap = jtag_NextEnabledTap(tap);
-               if( tap == NULL ){
-                       break;
-               }
-               int found = 0;
-               (*last_cmd)->cmd.scan->fields[field_count].tap = tap;
 
-               for (j = 0; j < num_fields; j++)
-               {
-                       if (tap == fields[j].tap)
-                       {
-                               found = 1;
-                               scan_size = fields[j].num_bits;
-                               (*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size;
-                               (*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-                               (*last_cmd)->cmd.scan->fields[field_count].in_value = fields[j].in_value;
-                               field_count++;
-                       }
-               }
-               if (!found)
+       scan_field_t * field = out_fields;      /* keep track where we insert data */
+
+       /* loop over all enabled TAPs */
+
+       for (jtag_tap_t * tap = jtag_NextEnabledTap(NULL); tap != NULL; tap = jtag_NextEnabledTap(tap))
+       {
+               /* if TAP is not bypassed insert matching input fields */
+
+               if (!tap->bypass)
                {
-#ifdef _DEBUG_JTAG_IO_
-                       /* if a device isn't listed, the BYPASS register should be selected */
-                       if (! tap->bypass)
+                       scan_field_t * start_field = field;     /* keep initial position for assert() */
+
+                       for (int j = 0; j < in_num_fields; j++)
                        {
-                               LOG_ERROR("BUG: no scan data for a device not in BYPASS");
-                               exit(-1);
+                               if (tap != in_fields[j].tap)
+                                       continue;
+
+                               cmd_queue_scan_field_clone(field, in_fields + j);
+
+                               field++;
                        }
-#endif
-                       /* program the scan field to 1 bit length, and ignore it's value */
-                       (*last_cmd)->cmd.scan->fields[field_count].num_bits = 1;
-                       (*last_cmd)->cmd.scan->fields[field_count].out_value = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;
-                       field_count++;
+
+                       assert(field > start_field);    /* must have at least one input field per not bypassed TAP */
                }
+               
+               /* if a TAP is bypassed, generated a dummy bit*/
                else
                {
-#ifdef _DEBUG_JTAG_IO_
-                       /* if a device is listed, the BYPASS register must not be selected */
-                       if (tap->bypass)
-                       {
-                               LOG_ERROR("BUG: scan data for a device in BYPASS");
-                               exit(-1);
-                       }
-#endif
+                       field->tap                      = tap;
+                       field->num_bits         = 1;
+                       field->out_value        = NULL;
+                       field->in_value         = NULL;
+
+                       field++;
                }
        }
+
+       assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
+
        return ERROR_OK;
 }
 
+
+
+/**
+ * Generate a DR SCAN using the array of output values passed to the function
+ *
+ * This function assumes that the parameter target_tap specifies the one TAP
+ * that is not bypassed. All other TAPs must be bypassed and the function will
+ * generate a dummy 1bit field for them.
+ *
+ * For the target_tap a sequence of output-only fields will be generated where
+ * each field has the size num_bits and the field's values are taken from
+ * the array value.
+ *
+ * The bypass status of TAPs is set by jtag_add_ir_scan().
+ *
+ */
 void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap,
-               int num_fields,
+               int in_num_fields,
                const int *num_bits,
                const u32 *value,
                tap_state_t end_state)
 {
-       int nth_tap;
-       int field_count = 0;
-       int scan_size;
-       int bypass_devices = 0;
+       /* count devices in bypass */
 
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-       jtag_tap_t *tap;
+       size_t bypass_devices = 0;
 
-       /* count devices in bypass */
-       tap = NULL;
-       bypass_devices = 0;
-       for(;;){
-               tap = jtag_NextEnabledTap(tap);
-               if( tap == NULL ){
-                       break;
-               }
-               if( tap->bypass ){
+       for (jtag_tap_t * tap = jtag_NextEnabledTap(NULL); tap != NULL; tap = jtag_NextEnabledTap(tap))
+       {
+               if (tap->bypass)
                        bypass_devices++;
-               }
        }
 
-       /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->next = NULL;
-       (*last_cmd)->type = JTAG_SCAN;
 
-       /* allocate memory for dr scan command */
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-       (*last_cmd)->cmd.scan->ir_scan = 0;
-       (*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
-       (*last_cmd)->cmd.scan->end_state = end_state;
+       jtag_command_t * cmd            = cmd_queue_alloc(sizeof(jtag_command_t));
+       scan_command_t * scan           = cmd_queue_alloc(sizeof(scan_command_t));
+       scan_field_t * out_fields       = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(scan_field_t));
 
-       tap = NULL;
-       nth_tap = -1;
-       for(;;){
-               tap = jtag_NextEnabledTap(tap);
-               if( tap == NULL ){
-                       break;
-               }
-               nth_tap++;
-               (*last_cmd)->cmd.scan->fields[field_count].tap = tap;
+       jtag_queue_command(cmd);
+
+       cmd->type                               = JTAG_SCAN;
+       cmd->cmd.scan                   = scan;
+
+       scan->ir_scan                   = false;
+       scan->num_fields                = in_num_fields + bypass_devices;
+       scan->fields                    = out_fields;
+       scan->end_state                 = end_state;
 
-               if (tap == target_tap)
+
+       bool target_tap_match   = false;
+
+       scan_field_t * field = out_fields;      /* keep track where we insert data */
+
+       /* loop over all enabled TAPs */
+
+       for (jtag_tap_t * tap = jtag_NextEnabledTap(NULL); tap != NULL; tap = jtag_NextEnabledTap(tap))
+       {
+               /* if TAP is not bypassed insert matching input fields */
+
+               if (!tap->bypass)
                {
-                       int j;
-#ifdef _DEBUG_JTAG_IO_
-                       /* if a device is listed, the BYPASS register must not be selected */
-                       if (tap->bypass)
-                       {
-                               LOG_ERROR("BUG: scan data for a device in BYPASS");
-                               exit(-1);
-                       }
-#endif
-                       for (j = 0; j < num_fields; j++)
+                       assert(tap == target_tap); /* target_tap must match the one not bypassed TAP */
+
+                       target_tap_match = true;
+
+                       for (int j = 0; j < in_num_fields; j++)
                        {
                                u8 out_value[4];
-                               scan_size = num_bits[j];
+                               size_t scan_size = num_bits[j];
                                buf_set_u32(out_value, 0, scan_size, value[j]);
-                               (*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size;
-                               (*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-                               (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;
-                               field_count++;
+
+                               field->tap                      = tap;
+                               field->num_bits         = scan_size;
+                               field->out_value        = buf_cpy(out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                               field->in_value         = NULL;
+
+                               field++;
                        }
-               } else
+               }
+
+               /* if a TAP is bypassed, generated a dummy bit*/
+               else
                {
-#ifdef _DEBUG_JTAG_IO_
-                       /* if a device isn't listed, the BYPASS register should be selected */
-                       if (! tap->bypass)
-                       {
-                               LOG_ERROR("BUG: no scan data for a device not in BYPASS");
-                               exit(-1);
-                       }
-#endif
-                       /* program the scan field to 1 bit length, and ignore it's value */
-                       (*last_cmd)->cmd.scan->fields[field_count].num_bits = 1;
-                       (*last_cmd)->cmd.scan->fields[field_count].out_value = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;
-                       field_count++;
+
+                       field->tap                              = tap;
+                       field->num_bits                 = 1;
+                       field->out_value                = NULL;
+                       field->in_value                 = NULL;
+
+                       field++;
                }
        }
+
+       assert(target_tap_match);       /* target_tap should be enabled and not bypassed */
 }
 
-void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, tap_state_t state)
+
+/**
+ * Duplicate the scan fields passed into the function into a DR SCAN command
+ *
+ * This function assumes that the caller handles extra fields for bypassed TAPs
+ *
+ */
+void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
 {
        int retval;
 
        jtag_prelude(state);
 
-       retval=interface_jtag_add_plain_dr_scan(num_fields, fields, cmd_queue_end_state);
+       retval=interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, cmd_queue_end_state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
 
-int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
+
+/**
+ * see jtag_add_plain_dr_scan()
+ *
+ */
+int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
 {
-       int i;
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       jtag_command_t * cmd            = cmd_queue_alloc(sizeof(jtag_command_t));
+       scan_command_t * scan           = cmd_queue_alloc(sizeof(scan_command_t));
+       scan_field_t * out_fields       = cmd_queue_alloc(in_num_fields * sizeof(scan_field_t));
 
-       /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->next = NULL;
-       (*last_cmd)->type = JTAG_SCAN;
+       jtag_queue_command(cmd);
 
-       /* allocate memory for scan command */
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-       (*last_cmd)->cmd.scan->ir_scan = 0;
-       (*last_cmd)->cmd.scan->num_fields = num_fields;
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
-       (*last_cmd)->cmd.scan->end_state = state;
+       cmd->type                               = JTAG_SCAN;
+       cmd->cmd.scan                   = scan;
 
-       for (i = 0; i < num_fields; i++)
-       {
-               int num_bits = fields[i].num_bits;
-               int num_bytes = CEIL(fields[i].num_bits, 8);
-               (*last_cmd)->cmd.scan->fields[i].tap = fields[i].tap;
-               (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
-               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
-               (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
-       }
+       scan->ir_scan                   = false;
+       scan->num_fields                = in_num_fields;
+       scan->fields                    = out_fields;
+       scan->end_state                 = state;
+
+       for (int i = 0; i < in_num_fields; i++)
+               cmd_queue_scan_field_clone(out_fields + i, in_fields + i);
 
        return ERROR_OK;
 }
 
+
 void jtag_add_tlr(void)
 {
        jtag_prelude(TAP_RESET);
@@ -994,21 +1050,21 @@ void jtag_add_tlr(void)
 int MINIDRIVER(interface_jtag_add_tlr)(void)
 {
        tap_state_t state = TAP_RESET;
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
 
        /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->next = NULL;
-       (*last_cmd)->type = JTAG_STATEMOVE;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+
+       jtag_queue_command(cmd);
+
+       cmd->type = JTAG_STATEMOVE;
 
-       (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-       (*last_cmd)->cmd.statemove->end_state = state;
+       cmd->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+       cmd->cmd.statemove->end_state = state;
 
        return ERROR_OK;
 }
 
-void jtag_add_pathmove(int num_states, tap_state_t *path)
+void jtag_add_pathmove(int num_states, const tap_state_t *path)
 {
        tap_state_t cur_state = cmd_queue_cur_state;
        int i;
@@ -1046,40 +1102,37 @@ void jtag_add_pathmove(int num_states, tap_state_t *path)
                jtag_error=retval;
 }
 
-int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, tap_state_t *path)
+int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, const tap_state_t *path)
 {
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-       int i;
-
        /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->next = NULL;
-       (*last_cmd)->type = JTAG_PATHMOVE;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
 
-       (*last_cmd)->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t));
-       (*last_cmd)->cmd.pathmove->num_states = num_states;
-       (*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
+       jtag_queue_command(cmd);
 
-       for (i = 0; i < num_states; i++)
-               (*last_cmd)->cmd.pathmove->path[i] = path[i];
+       cmd->type = JTAG_PATHMOVE;
+
+       cmd->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t));
+       cmd->cmd.pathmove->num_states = num_states;
+       cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
+
+       for (int i = 0; i < num_states; i++)
+               cmd->cmd.pathmove->path[i] = path[i];
 
        return ERROR_OK;
 }
 
 int MINIDRIVER(interface_jtag_add_runtest)(int num_cycles, tap_state_t state)
 {
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-
        /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       (*last_cmd)->next = NULL;
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->type = JTAG_RUNTEST;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+
+       jtag_queue_command(cmd);
 
-       (*last_cmd)->cmd.runtest = cmd_queue_alloc(sizeof(runtest_command_t));
-       (*last_cmd)->cmd.runtest->num_cycles = num_cycles;
-       (*last_cmd)->cmd.runtest->end_state = state;
+       cmd->type = JTAG_RUNTEST;
+
+       cmd->cmd.runtest = cmd_queue_alloc(sizeof(runtest_command_t));
+       cmd->cmd.runtest->num_cycles = num_cycles;
+       cmd->cmd.runtest->end_state = state;
 
        return ERROR_OK;
 }
@@ -1099,16 +1152,16 @@ void jtag_add_runtest(int num_cycles, tap_state_t state)
 
 int MINIDRIVER(interface_jtag_add_clocks)( int num_cycles )
 {
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-
        /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       (*last_cmd)->next = NULL;
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->type = JTAG_STABLECLOCKS;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+
+       jtag_queue_command(cmd);
+
+       cmd->type = JTAG_STABLECLOCKS;
+
+       cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(stableclocks_command_t));
+       cmd->cmd.stableclocks->num_cycles = num_cycles;
 
-       (*last_cmd)->cmd.stableclocks = cmd_queue_alloc(sizeof(stableclocks_command_t));
-       (*last_cmd)->cmd.stableclocks->num_cycles = num_cycles;
        return ERROR_OK;
 }
 
@@ -1200,6 +1253,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                jtag_error=retval;
                return;
        }
+       jtag_execute_queue();
 
        if (jtag_srst)
        {
@@ -1227,7 +1281,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                 * and inform possible listeners about this
                 */
                LOG_DEBUG("TRST line asserted");
-               cmd_queue_cur_state = TAP_RESET;
+               tap_set_state(TAP_RESET);
                jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
        }
        else
@@ -1239,17 +1293,16 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 
 int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst)
 {
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-
        /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       (*last_cmd)->next = NULL;
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->type = JTAG_RESET;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+
+       jtag_queue_command(cmd);
+
+       cmd->type = JTAG_RESET;
 
-       (*last_cmd)->cmd.reset = cmd_queue_alloc(sizeof(reset_command_t));
-       (*last_cmd)->cmd.reset->trst = req_trst;
-       (*last_cmd)->cmd.reset->srst = req_srst;
+       cmd->cmd.reset = cmd_queue_alloc(sizeof(reset_command_t));
+       cmd->cmd.reset->trst = req_trst;
+       cmd->cmd.reset->srst = req_srst;
 
        return ERROR_OK;
 }
@@ -1265,16 +1318,15 @@ void jtag_add_end_state(tap_state_t state)
 
 int MINIDRIVER(interface_jtag_add_sleep)(u32 us)
 {
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
-
        /* allocate memory for a new list member */
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-       (*last_cmd)->next = NULL;
-       last_comand_pointer = &((*last_cmd)->next);
-       (*last_cmd)->type = JTAG_SLEEP;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+
+       jtag_queue_command(cmd);
 
-       (*last_cmd)->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
-       (*last_cmd)->cmd.sleep->us = us;
+       cmd->type = JTAG_SLEEP;
+
+       cmd->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
+       cmd->cmd.sleep->us = us;
 
        return ERROR_OK;
 }
@@ -1288,7 +1340,7 @@ void jtag_add_sleep(u32 us)
        return;
 }
 
-int jtag_scan_size(scan_command_t *cmd)
+int jtag_scan_size(const scan_command_t *cmd)
 {
        int bit_count = 0;
        int i;
@@ -1302,13 +1354,13 @@ int jtag_scan_size(scan_command_t *cmd)
        return bit_count;
 }
 
-int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
+int jtag_build_buffer(const scan_command_t *cmd, u8 **buffer)
 {
        int bit_count = 0;
        int i;
 
        bit_count = jtag_scan_size(cmd);
-       *buffer = malloc(CEIL(bit_count, 8));
+       *buffer = calloc(1,CEIL(bit_count, 8));
 
        bit_count = 0;
 
@@ -1346,7 +1398,7 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
        return bit_count;
 }
 
-int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
+int jtag_read_buffer(u8 *buffer, const scan_command_t *cmd)
 {
        int i;
        int bit_count = 0;
@@ -1384,7 +1436,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
        return retval;
 }
 
-static const char *jtag_tap_name(jtag_tap_t *tap)
+static const char *jtag_tap_name(const jtag_tap_t *tap)
 {
        return (tap == NULL) ? "(unknown)" : tap->dotted_name;
 }
@@ -1456,7 +1508,7 @@ void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask)
 
 
 
-enum scan_type jtag_scan_type(scan_command_t *cmd)
+enum scan_type jtag_scan_type(const scan_command_t *cmd)
 {
        int i;
        int type = 0;
@@ -1541,7 +1593,7 @@ int interface_jtag_execute_queue(void)
        jtag_callback_queue_tail = NULL;
 
        jtag_command_queue = NULL;
-       last_comand_pointer = &jtag_command_queue;
+       last_command_pointer = &jtag_command_queue;
 
        return retval;
 }
@@ -2263,9 +2315,10 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, NULL, "interface", handle_interface_command,
                COMMAND_CONFIG, "try to configure interface");
        register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
-               COMMAND_ANY, "set jtag speed (if supported)");
+               COMMAND_ANY, "(DEPRECATED) set jtag speed (if supported)");
        register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
-               COMMAND_ANY, "same as jtag_speed, except it takes maximum khz as arguments. 0 KHz = RTCK.");
+               COMMAND_ANY, "set maximum jtag speed (if supported); "
+               "parameter is maximum khz, or 0 for adaptive clocking (RTCK).");
        register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
                COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");
        register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
@@ -2292,6 +2345,10 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
 
        register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
                COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
+       register_command(cmd_ctx, NULL, "verify_jtag", handle_verify_jtag_command,
+               COMMAND_ANY, "verify value capture <enable|disable>");
+       register_command(cmd_ctx, NULL, "tms_sequence", handle_tms_sequence_command,
+               COMMAND_ANY, "choose short(default) or long tms_sequence <short|long>");
        return ERROR_OK;
 }
 
@@ -2350,6 +2407,20 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
+int jtag_interface_quit(void)
+{
+       if (!jtag || !jtag->quit)
+               return ERROR_OK;
+
+       // close the JTAG interface
+       int result = jtag->quit();
+       if (ERROR_OK != result)
+               LOG_ERROR("failed: %d", result);
+
+       return ERROR_OK;
+}
+
+
 int jtag_init_reset(struct command_context_s *cmd_ctx)
 {
        int retval;
@@ -2594,77 +2665,111 @@ static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cm
 
 static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
+       int new_cfg = 0;
+       int mask = 0;
+
        if (argc < 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (argc >= 1)
-       {
-               if (strcmp(args[0], "none") == 0)
-                       jtag_reset_config = RESET_NONE;
-               else if (strcmp(args[0], "trst_only") == 0)
-                       jtag_reset_config = RESET_HAS_TRST;
-               else if (strcmp(args[0], "srst_only") == 0)
-                       jtag_reset_config = RESET_HAS_SRST;
-               else if (strcmp(args[0], "trst_and_srst") == 0)
-                       jtag_reset_config = RESET_TRST_AND_SRST;
+       /* Original versions cared about the order of these tokens:
+        *   reset_config signals [combination [trst_type [srst_type]]]
+        * They also clobbered the previous configuration even on error.
+        *
+        * Here we don't care about the order, and only change values
+        * which have been explicitly specified.
+        */
+       for (; argc; argc--, args++) {
+               int tmp = 0;
+               int m;
+
+               /* signals */
+               m = RESET_HAS_TRST | RESET_HAS_SRST;
+               if (strcmp(*args, "none") == 0)
+                       tmp = RESET_NONE;
+               else if (strcmp(*args, "trst_only") == 0)
+                       tmp = RESET_HAS_TRST;
+               else if (strcmp(*args, "srst_only") == 0)
+                       tmp = RESET_HAS_SRST;
+               else if (strcmp(*args, "trst_and_srst") == 0)
+                       tmp = RESET_HAS_TRST | RESET_HAS_SRST;
                else
-               {
-                       LOG_ERROR("(1) invalid reset_config argument (%s), defaulting to none", args[0]);
-                       jtag_reset_config = RESET_NONE;
+                       m = 0;
+               if (mask & m) {
+                       LOG_ERROR("extra reset_config %s spec (%s)",
+                                       "signal", *args);
                        return ERROR_INVALID_ARGUMENTS;
                }
-       }
-
-       if (argc >= 2)
-       {
-               if (strcmp(args[1], "separate") == 0)
-               {
-                       /* seperate reset lines - default */
-               } else
-               {
-                       if (strcmp(args[1], "srst_pulls_trst") == 0)
-                               jtag_reset_config |= RESET_SRST_PULLS_TRST;
-                       else if (strcmp(args[1], "trst_pulls_srst") == 0)
-                               jtag_reset_config |= RESET_TRST_PULLS_SRST;
-                       else if (strcmp(args[1], "combined") == 0)
-                               jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
-                       else
-                       {
-                               LOG_ERROR("(2) invalid reset_config argument (%s), defaulting to none", args[1]);
-                               jtag_reset_config = RESET_NONE;
-                               return ERROR_INVALID_ARGUMENTS;
-                       }
+               if (m)
+                       goto next;
+
+               /* combination (options for broken wiring) */
+               m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
+               if (strcmp(*args, "separate") == 0)
+                       /* separate reset lines - default */;
+               else if (strcmp(*args, "srst_pulls_trst") == 0)
+                       tmp |= RESET_SRST_PULLS_TRST;
+               else if (strcmp(*args, "trst_pulls_srst") == 0)
+                       tmp |= RESET_TRST_PULLS_SRST;
+               else if (strcmp(*args, "combined") == 0)
+                       tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
+               else
+                       m = 0;
+               if (mask & m) {
+                       LOG_ERROR("extra reset_config %s spec (%s)",
+                                       "combination", *args);
+                       return ERROR_INVALID_ARGUMENTS;
                }
-       }
+               if (m)
+                       goto next;
 
-       if (argc >= 3)
-       {
-               if (strcmp(args[2], "trst_open_drain") == 0)
-                       jtag_reset_config |= RESET_TRST_OPEN_DRAIN;
-               else if (strcmp(args[2], "trst_push_pull") == 0)
-                       jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN;
+               /* trst_type (NOP without HAS_TRST) */
+               m = RESET_TRST_OPEN_DRAIN;
+               if (strcmp(*args, "trst_open_drain") == 0)
+                       tmp |= RESET_TRST_OPEN_DRAIN;
+               else if (strcmp(*args, "trst_push_pull") == 0)
+                       /* push/pull from adapter - default */;
                else
-               {
-                       LOG_ERROR("(3) invalid reset_config argument (%s) defaulting to none", args[2] );
-                       jtag_reset_config = RESET_NONE;
+                       m = 0;
+               if (mask & m) {
+                       LOG_ERROR("extra reset_config %s spec (%s)",
+                                       "trst_type", *args);
                        return ERROR_INVALID_ARGUMENTS;
                }
-       }
+               if (m)
+                       goto next;
 
-       if (argc >= 4)
-       {
-               if (strcmp(args[3], "srst_push_pull") == 0)
-                       jtag_reset_config |= RESET_SRST_PUSH_PULL;
-               else if (strcmp(args[3], "srst_open_drain") == 0)
-                       jtag_reset_config &= ~RESET_SRST_PUSH_PULL;
+               /* srst_type (NOP without HAS_SRST) */
+               m |= RESET_SRST_PUSH_PULL;
+               if (strcmp(*args, "srst_push_pull") == 0)
+                       tmp |= RESET_SRST_PUSH_PULL;
+               else if (strcmp(*args, "srst_open_drain") == 0)
+                       /* open drain from adapter - default */;
                else
-               {
-                       LOG_ERROR("(4) invalid reset_config argument (%s), defaulting to none", args[3]);
-                       jtag_reset_config = RESET_NONE;
+                       m = 0;
+               if (mask & m) {
+                       LOG_ERROR("extra reset_config %s spec (%s)",
+                                       "srst_type", *args);
                        return ERROR_INVALID_ARGUMENTS;
                }
+               if (m)
+                       goto next;
+
+               /* caller provided nonsense; fail */
+               LOG_ERROR("unknown reset_config flag (%s)", *args);
+               return ERROR_INVALID_ARGUMENTS;
+
+next:
+               /* Remember the bits which were specified (mask)
+                * and their new values (new_cfg).
+                */
+               mask |= m;
+               new_cfg |= tmp;
        }
 
+       /* clear previous values of those bits, save new values */
+       jtag_reset_config &= ~mask;
+       jtag_reset_config |= new_cfg;
+
        return ERROR_OK;
 }
 
@@ -2866,7 +2971,7 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c
        /*          "statename" */
        /* at the end of the arguments. */
        /* assume none. */
-       endstate = TAP_INVALID;
+       endstate = cmd_queue_end_state;
        if( argc >= 4 ){
                /* have at least one pair of numbers. */
                /* is last pair the magic text? */
@@ -2889,9 +2994,11 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c
                }
        }
 
-       fields = malloc(sizeof(scan_field_t) * argc / 2);
+       int num_fields = argc / 2;
+
+       fields = malloc(sizeof(scan_field_t) * num_fields);
 
-       for (i = 0; i < argc / 2; i++)
+       for (i = 0; i < num_fields; i++)
        {
                tap = jtag_TapByString( args[i*2] );
                if (tap==NULL)
@@ -2901,24 +3008,23 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c
                }
                int field_size = tap->ir_length;
                fields[i].tap = tap;
+               fields[i].num_bits = field_size;
                fields[i].out_value = malloc(CEIL(field_size, 8));
                buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0));
                fields[i].in_value = NULL;
        }
 
-       jtag_add_ir_scan(argc / 2, fields, TAP_INVALID);
        /* did we have an endstate? */
-       if (endstate != TAP_INVALID)
-               jtag_add_end_state(endstate);
+       jtag_add_ir_scan(num_fields, fields, endstate);
 
-       jtag_execute_queue();
+       int retval=jtag_execute_queue();
 
-       for (i = 0; i < argc / 2; i++)
+       for (i = 0; i < num_fields; i++)
                free(fields[i].out_value);
 
        free (fields);
 
-       return ERROR_OK;
+       return retval;
 }
 
 static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args)
@@ -2947,7 +3053,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
        }
 
        /* assume no endstate */
-       endstate = TAP_INVALID;
+       endstate = cmd_queue_end_state;
        /* validate arguments as numbers */
        e = JIM_OK;
        for (i = 2; i < argc; i+=2)
@@ -3019,10 +3125,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
                field_count++;
        }
 
-       jtag_add_dr_scan(num_fields, fields, TAP_INVALID);
-       /* did we get an end state? */
-       if (endstate != TAP_INVALID)
-               jtag_add_end_state(endstate);
+       jtag_add_dr_scan(num_fields, fields, endstate);
 
        retval = jtag_execute_queue();
        if (retval != ERROR_OK)
@@ -3088,6 +3191,32 @@ static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, ch
        return ERROR_OK;
 }
 
+static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "enable") == 0)
+               {
+                       jtag_verify = 1;
+               }
+               else if (strcmp(args[0], "disable") == 0)
+               {
+                       jtag_verify = 0;
+               } else
+               {
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+       } else if (argc != 0)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       command_print(cmd_ctx, "verify jtag capture is %s", (jtag_verify) ? "enabled": "disabled");
+
+       return ERROR_OK;
+}
+
+
 int jtag_power_dropout(int *dropout)
 {
        return jtag->power_dropout(dropout);
@@ -3207,19 +3336,12 @@ int tap_move_ndx( tap_state_t astate )
  *
  * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
  */
-static struct
+struct tms_sequences
 {
        u8      bits;
        u8      bit_count;
 
-} tms_seqs[6][6] =             /*  [from_state_ndx][to_state_ndx] */
-{
-       /* value clocked to TMS to move from one of six stable states to another.
-        * N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
-        * N.B. These values are tightly bound to the table in tap_get_tms_path_len().
-        * N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
-        *              These extra ones cause no TAP state problem, because we go into reset and stay in reset.
-        */
+};
 
 /*
  * These macros allow us to specify TMS state transitions by bits rather than hex bytes.
@@ -3239,7 +3361,31 @@ static struct
 
 #define B8(bits,count)         { ((u8)B8__(HEX__(bits))), (count) }
 
-#if 0 && ((BUILD_FT2232_FTD2XX==1) || (BUILD_FT2232_LIBFTDI==1) || (BUILD_JLINK==1))
+static const struct tms_sequences old_tms_seqs[6][6] =         /*  [from_state_ndx][to_state_ndx] */
+{
+       /* value clocked to TMS to move from one of six stable states to another.
+        * N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
+        * N.B. These values are tightly bound to the table in tap_get_tms_path_len().
+        * N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
+        *              These extra ones cause no TAP state problem, because we go into reset and stay in reset.
+        */
+
+
+
+       /* to state: */
+       /*      RESET                   IDLE                    DRSHIFT                 DRPAUSE                 IRSHIFT                 IRPAUSE         */              /* from state: */
+       {       B8(1111111,7),  B8(0000000,7),  B8(0010111,7),  B8(0001010,7),  B8(0011011,7),  B8(0010110,7) },        /* RESET */
+       {       B8(1111111,7),  B8(0000000,7),  B8(0100101,7),  B8(0000101,7),  B8(0101011,7),  B8(0001011,7) },        /* IDLE */
+       {       B8(1111111,7),  B8(0110001,7),  B8(0000000,7),  B8(0000001,7),  B8(0001111,7),  B8(0101111,7) },        /* DRSHIFT */
+       {       B8(1111111,7),  B8(0110000,7),  B8(0100000,7),  B8(0010111,7),  B8(0011110,7),  B8(0101111,7) },        /* DRPAUSE */
+       {       B8(1111111,7),  B8(0110001,7),  B8(0000111,7),  B8(0010111,7),  B8(0000000,7),  B8(0000001,7) },        /* IRSHIFT */
+       {       B8(1111111,7),  B8(0110000,7),  B8(0011100,7),  B8(0010111,7),  B8(0011110,7),  B8(0101111,7) },        /* IRPAUSE */
+};
+
+
+
+static const struct tms_sequences short_tms_seqs[6][6] =               /*  [from_state_ndx][to_state_ndx] */
+{
        /*      this is the table submitted by Jeff Williams on 3/30/2009 with this comment:
 
                OK, I added Peter's version of the state table, and it works OK for
@@ -3266,47 +3412,28 @@ static struct
 
        /* to state: */
        /*      RESET                   IDLE                            DRSHIFT                 DRPAUSE                 IRSHIFT                 IRPAUSE */                      /* from state: */
-       {       B8(1111111,7),  B8(0,1),                        B8(00101,5),    B8(01010,5),            B8(001101,6),   B8(010110,6) },         /* RESET */
-       {       B8(1111111,7),  B8(0,1),                        B8(001,3),              B8(0101,4),             B8(0011,4),     B8(01011,5) },          /* IDLE */
-       {       B8(1111111,7),  B8(011,3),              B8(00111,5),            B8(01,2),               B8(001111,6),   B8(0101111,7) },                /* DRSHIFT */
-       {       B8(1111111,7),  B8(011,3),              B8(01,2),               B8(0,1),                        B8(001111,6),   B8(0101111,7) },                /* DRPAUSE */
+       {       B8(1111111,7),  B8(0000000,7),  B8(0010111,7),          B8(0001010,7),  B8(0011011,7),  B8(0010110,7) },        /* RESET */
+       {       B8(1111111,7),  B8(0000000,7),  B8(001,3),                      B8(0101,4),             B8(0011,4),     B8(01011,5) },          /* IDLE */
+       {       B8(1111111,7),  B8(011,3),              B8(00111,5),            B8(01,2),               B8(001111,6),   B8(0101111,7) },        /* DRSHIFT */
+       {       B8(1111111,7),  B8(011,3),              B8(01,2),               B8(0,1),                B8(001111,6),   B8(0101111,7) },        /* DRPAUSE */
        {       B8(1111111,7),  B8(011,3),              B8(00111,5),            B8(010111,6),   B8(001111,6),   B8(01,2) },                     /* IRSHIFT */
        {       B8(1111111,7),  B8(011,3),              B8(00111,5),            B8(010111,6),   B8(01,2),               B8(0,1) }                       /* IRPAUSE */
 
-#else  /* this is the old table, converted from hex and with the bit_count set to 7 for each combo, like before */
-
-       /* to state: */
-       /*      RESET                   IDLE                            DRSHIFT                 DRPAUSE                 IRSHIFT                 IRPAUSE */                      /* from state: */
-       {       B8(1111111,7),  B8(0000000,7),  B8(0010111,7),  B8(0001010,7),  B8(0011011,7),  B8(0010110,7) },                /* RESET */
-       {       B8(1111111,7),  B8(0000000,7),  B8(0100101,7),  B8(0000101,7),  B8(0101011,7),  B8(0001011,7) },                /* IDLE */
-       {       B8(1111111,7),  B8(0110001,7),  B8(0000000,7),  B8(0000001,7),  B8(0001111,7),  B8(0101111,7) },                /* DRSHIFT */
-       {       B8(1111111,7),  B8(0110000,7),  B8(0100000,7),  B8(0010111,7),  B8(0011110,7),  B8(0101111,7) },                /* DRPAUSE */
-       {       B8(1111111,7),  B8(0110001,7),  B8(0000111,7),  B8(0010111,7),  B8(0000000,7),  B8(0000001,7) },                /* IRSHIFT */
-       {       B8(1111111,7),  B8(0110000,7),  B8(0011100,7),  B8(0010111,7),  B8(0100000,7),  B8(0101111,7) }                 /* IRPAUSE */
-
-#endif
-
-#if 0 /* keeping old hex stuff for awhile, for reference */
-       /* RESET                        IDLE                    DRSHIFT                 DRPAUSE                 IRSHIFT                 IRPAUSE */
-       {  0x7f,                        0x00,                   0x17,                   0x0a,                   0x1b,                   0x16 }, /* RESET */
-       {  0x7f,                        0x00,                   0x25,                   0x05,                   0x2b,                   0x0b }, /* IDLE */
-       {  0x7f,                        0x31,                   0x00,                   0x01,                   0x0f,                   0x2f }, /* DRSHIFT  */
-       {  0x7f,                        0x30,                   0x20,                   0x17,                   0x1e,                   0x2f }, /* DRPAUSE  */
-       {  0x7f,                        0x31,                   0x07,                   0x17,                   0x00,                   0x01 }, /* IRSHIFT  */
-       {  0x7f,                        0x30,                   0x1c,                   0x17,                   0x20,                   0x2f }  /* IRPAUSE  */
-#endif
 };
 
+typedef const struct tms_sequences tms_table[6][6];
+
+static tms_table *tms_seqs=&short_tms_seqs;
 
 int tap_get_tms_path( tap_state_t from, tap_state_t to )
 {
-       return tms_seqs[tap_move_ndx(from)][tap_move_ndx(to)].bits;
+       return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bits;
 }
 
 
 int tap_get_tms_path_len( tap_state_t from, tap_state_t to )
 {
-       return tms_seqs[tap_move_ndx(from)][tap_move_ndx(to)].bit_count;
+       return (*tms_seqs)[tap_move_ndx(from)][tap_move_ndx(to)].bit_count;
 }
 
 
@@ -3559,4 +3686,123 @@ tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
 }
 #endif // _DEBUG_JTAG_IO_
 
+#ifndef HAVE_JTAG_MINIDRIVER_H
+void jtag_alloc_in_value32(scan_field_t *field)
+{
+       field->in_value=(u8 *)cmd_queue_alloc(4);
+}
+#endif
+
+static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "short") == 0)
+               {
+                       tms_seqs=&short_tms_seqs;
+               }
+               else if (strcmp(args[0], "long") == 0)
+               {
+                       tms_seqs=&old_tms_seqs;
+               } else
+               {
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+       } else if (argc != 0)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       command_print(cmd_ctx, "tms sequence is  %s", (tms_seqs==&short_tms_seqs) ? "short": "long");
+
+       return ERROR_OK;
+}
+
 /*-----</Cable Helper API>--------------------------------------*/
+
+
+/**
+ * Function jtag_add_statemove
+ * moves from the current state to the goal \a state. This needs
+ * to be handled according to the xsvf spec, see the XSTATE command
+ * description.
+ */
+int jtag_add_statemove(tap_state_t goal_state)
+{
+       int retval = ERROR_OK;
+
+       tap_state_t moves[8];
+       tap_state_t cur_state = cmd_queue_cur_state;
+       int i;
+       int tms_bits;
+       int     tms_count;
+
+       LOG_DEBUG( "cur_state=%s goal_state=%s",
+               tap_state_name(cur_state),
+               tap_state_name(goal_state) );
+
+
+       /*      From the XSVF spec, pertaining to XSTATE:
+
+               For special states known as stable states (Test-Logic-Reset,
+               Run-Test/Idle, Pause-DR, Pause- IR), an XSVF interpreter follows
+               predefined TAP state paths when the starting state is a stable state and
+               when the XSTATE specifies a new stable state (see the STATE command in
+               the [Ref 5] for the TAP state paths between stable states). For
+               non-stable states, XSTATE should specify a state that is only one TAP
+               state transition distance from the current TAP state to avoid undefined
+               TAP state paths. A sequence of multiple XSTATE commands can be issued to
+               transition the TAP through a specific state path.
+       */
+
+       if (goal_state==cur_state )
+               ;       /* nothing to do */
+
+       else if( goal_state==TAP_RESET )
+       {
+               jtag_add_tlr();
+       }
+
+       else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) )
+       {
+               /*      note: unless tms_bits holds a path that agrees with [Ref 5] in above
+                       spec, then this code is not fully conformant to the xsvf spec.  This
+                       puts a burden on tap_get_tms_path() function from the xsvf spec.
+                       If in doubt, you should confirm that that burden is being met.
+               */
+
+               tms_bits  = tap_get_tms_path(cur_state, goal_state);
+               tms_count = tap_get_tms_path_len(cur_state, goal_state);
+
+               assert( (unsigned) tms_count < DIM(moves) );
+
+               for (i=0;   i<tms_count;   i++, tms_bits>>=1)
+               {
+                       bool bit = tms_bits & 1;
+
+                       cur_state = tap_state_transition(cur_state, bit);
+                       moves[i] = cur_state;
+               }
+
+               jtag_add_pathmove(tms_count, moves);
+       }
+
+       /*      else state must be immediately reachable in one clock cycle, and does not
+               need to be a stable state.
+       */
+       else if( tap_state_transition(cur_state, true)  == goal_state
+               ||   tap_state_transition(cur_state, false) == goal_state )
+       {
+               /* move a single state */
+               moves[0] = goal_state;
+               jtag_add_pathmove( 1, moves );
+       }
+
+       else
+       {
+               retval = ERROR_FAIL;
+       }
+
+       return retval;
+}
+