]> git.sur5r.net Git - openocd/blobdiff - src/jtag/jtag.c
Fix fallout from r1818
[openocd] / src / jtag / jtag.c
index 242eb56bf6b3fd0d6a12ab78eef3688b0253c406..f1c6676ea5e99a1ddf53b38663ee4da1028116c1 100644 (file)
 #include "config.h"
 #endif
 
-#include "replacements.h"
-
 #include "jtag.h"
 
-#include "command.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
 
-static void jtag_execute_queue_noclear(void);
+
+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);
 
 /* 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
@@ -74,8 +70,26 @@ const Jim_Nvp nvp_jtag_tap_event[] = {
 int jtag_trst = 0;
 int jtag_srst = 0;
 
+#ifndef HAVE_JTAG_MINIDRIVER_H
+struct jtag_callback_entry
+{
+       struct jtag_callback_entry *next;
+
+       jtag_callback_t callback;
+       u8 *in;
+       jtag_callback_data_t data1;
+       jtag_callback_data_t data2;
+       jtag_callback_data_t data3;
+};
+
+
+static struct jtag_callback_entry *jtag_callback_queue_head = NULL;
+static struct jtag_callback_entry *jtag_callback_queue_tail = NULL;
+#endif
+
+
 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;
@@ -83,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 */
@@ -242,8 +257,10 @@ static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cm
 static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 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);
 
 jtag_tap_t *jtag_AllTaps(void)
 {
@@ -419,9 +436,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;
@@ -521,41 +553,63 @@ static void jtag_prelude(tap_state_t state)
        cmd_queue_cur_state = cmd_queue_end_state;
 }
 
-void jtag_add_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state)
+void jtag_add_ir_scan_noverify(int num_fields, scan_field_t *fields, tap_state_t state)
 {
        int retval;
-
        jtag_prelude(state);
 
        retval=interface_jtag_add_ir_scan(num_fields, 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)
+{
+       if (jtag_verify&&jtag_verify_capture_ir)
+       {
+               /* 8 x 32 bit id's is enough for all invoations */
+               int j;
+               for (j = 0; j < num_fields; j++)
+               {
+                       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.
+                        */
+                       fields[j].check_value=fields[j].tap->expected;
+                       fields[j].check_mask=fields[j].tap->expected_mask;
+               }
+               jtag_add_scan_check(jtag_add_ir_scan_noverify, num_fields, fields, state);
+       } else
+       {
+               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)
 {
-       jtag_command_t **last_cmd;
        jtag_tap_t *tap;
        int j;
        int x;
        int nth_tap;
        int scan_size = 0;
 
-       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_SCAN;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       
+       jtag_queue_command(cmd);
+       
+       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;
+       cmd->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       cmd->cmd.scan->ir_scan = true;
        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;
+       cmd->cmd.scan->num_fields = x;  /* one field per device */
+       cmd->cmd.scan->fields = cmd_queue_alloc(x  * sizeof(scan_field_t));
+       cmd->cmd.scan->end_state = state;
 
        nth_tap = -1;
        tap = NULL;
@@ -568,11 +622,13 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields,
                        break;
                }
                nth_tap++;
+
+               assert(nth_tap < x );
+
                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;
-               (*last_cmd)->cmd.scan->fields[nth_tap].in_handler = NULL;       /* disable verification by default */
+               cmd->cmd.scan->fields[nth_tap].tap = tap;
+               cmd->cmd.scan->fields[nth_tap].num_bits = scan_size;
+               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++)
@@ -580,21 +636,8 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields,
                        if (tap == fields[j].tap)
                        {
                                found = 1;
-                               (*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 (jtag_verify_capture_ir)
-                               {
-                                       if (fields[j].in_handler==NULL)
-                                       {
-                                               jtag_set_check_value((*last_cmd)->cmd.scan->fields+nth_tap, tap->expected, tap->expected_mask, NULL);
-                                       } else
-                                       {
-                                               (*last_cmd)->cmd.scan->fields[nth_tap].in_handler = fields[j].in_handler;
-                                               (*last_cmd)->cmd.scan->fields[nth_tap].in_handler_priv = fields[j].in_handler_priv;
-                                               (*last_cmd)->cmd.scan->fields[nth_tap].in_check_value = tap->expected;
-                                               (*last_cmd)->cmd.scan->fields[nth_tap].in_check_mask = tap->expected_mask;
-                                       }
-                               }
+                               cmd->cmd.scan->fields[nth_tap].in_value = fields[j].in_value;
+                               cmd->cmd.scan->fields[nth_tap].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
 
                                tap->bypass = 0;
                                break;
@@ -604,13 +647,14 @@ int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields,
                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);
+                       cmd->cmd.scan->fields[nth_tap].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
                        tap->bypass = 1;
                }
 
                /* update device information */
-               buf_cpy((*last_cmd)->cmd.scan->fields[nth_tap].out_value, tap->cur_instr, scan_size);
+               buf_cpy(cmd->cmd.scan->fields[nth_tap].out_value, tap->cur_instr, scan_size);
        }
+       assert(nth_tap == (x-1));
 
        return ERROR_OK;
 }
@@ -628,36 +672,31 @@ void jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, tap_state_t st
 
 int MINIDRIVER(interface_jtag_add_plain_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
 {
-       int i;
-       jtag_command_t **last_cmd;
+       /* allocate memory for a new list member */
 
-       last_cmd = jtag_get_last_command_p();
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_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;
+       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;
+       cmd->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       cmd->cmd.scan->ir_scan = true;
+       cmd->cmd.scan->num_fields = num_fields;
+       cmd->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
+       cmd->cmd.scan->end_state = state;
 
-       for( i = 0 ; i < num_fields ; i++ ){
+       for (int 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;
-               (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
-               (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
-               (*last_cmd)->cmd.scan->fields[i].in_handler = NULL;
-               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = NULL;
+               cmd->cmd.scan->fields[i].tap = fields[i].tap;
+               cmd->cmd.scan->fields[i].num_bits = num_bits;
+               cmd->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
+               cmd->cmd.scan->fields[i].in_value = fields[i].in_value;
        }
+
        return ERROR_OK;
 }
 
@@ -672,10 +711,70 @@ void jtag_add_dr_scan(int num_fields, scan_field_t *fields, tap_state_t state)
                jtag_error=retval;
 }
 
-void jtag_add_dr_scan_now(int num_fields, scan_field_t *fields, tap_state_t state)
+
+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)
 {
-       jtag_add_dr_scan(num_fields, fields, state);
-       jtag_execute_queue_noclear();
+       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)
+{
+       for (int i=0; i<num_fields; i++)
+       {
+               fields[i].allocated=0;
+               fields[i].modified=0;
+               if ((fields[i].check_value!=NULL)&&(fields[i].in_value==NULL))
+               {
+                       fields[i].modified=1;
+                       /* we need storage space... */
+#ifdef HAVE_JTAG_MINIDRIVER_H
+                       if (fields[i].num_bits<=32)
+                       {
+                               /* This is enough space and we're executing this synchronously */
+                               fields[i].in_value=fields[i].intmp;
+                       } else
+                       {
+                               fields[i].in_value=(u8 *)malloc(CEIL(fields[i].num_bits, 8));
+                               fields[i].allocated=1;
+                       }
+#else
+                       fields[i].in_value=(u8 *)cmd_queue_alloc(CEIL(fields[i].num_bits, 8));
+#endif
+               }
+       }
+
+       jtag_add_scan(num_fields, fields, state);
+
+       for (int i=0; i<num_fields; i++)
+       {
+               if ((fields[i].check_value!=NULL)&&(fields[i].in_value!=NULL))
+               {
+                       /* this is synchronous for a minidriver */
+                       jtag_add_callback4(jtag_check_value_mask_callback, fields[i].in_value, (jtag_callback_data_t)fields[i].check_value, (jtag_callback_data_t)fields[i].check_mask, (jtag_callback_data_t)fields[i].num_bits);
+               }
+               if (fields[i].allocated)
+               {
+                       free(fields[i].in_value);
+               }
+               if (fields[i].modified)
+               {
+                       fields[i].in_value=NULL;
+               }
+       }
+}
+
+void jtag_add_dr_scan_check(int num_fields, scan_field_t *fields, tap_state_t state)
+{
+       if (jtag_verify)
+       {
+               jtag_add_scan_check(jtag_add_dr_scan, num_fields, fields, state);
+       } else
+       {
+               jtag_add_dr_scan(num_fields, fields, state);
+       }
 }
 
 int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
@@ -686,7 +785,6 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
        int field_count = 0;
        int scan_size;
 
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
        jtag_tap_t *tap;
 
        /* count devices in bypass */
@@ -703,17 +801,19 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
        }
 
        /* 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));
+       
+       jtag_queue_command(cmd);
+       
+       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 = state;
+       cmd->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       cmd->cmd.scan->ir_scan = false;
+       cmd->cmd.scan->num_fields = num_fields + bypass_devices;
+       cmd->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
+       cmd->cmd.scan->end_state = state;
 
        tap = NULL;
        nth_tap = -1;
@@ -724,7 +824,7 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
                        break;
                }
                int found = 0;
-               (*last_cmd)->cmd.scan->fields[field_count].tap = tap;
+               cmd->cmd.scan->fields[field_count].tap = tap;
 
                for (j = 0; j < num_fields; j++)
                {
@@ -732,13 +832,10 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
                        {
                                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;
-                               (*last_cmd)->cmd.scan->fields[field_count].in_check_value = fields[j].in_check_value;
-                               (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = fields[j].in_check_mask;
-                               (*last_cmd)->cmd.scan->fields[field_count].in_handler = fields[j].in_handler;
-                               (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = fields[j].in_handler_priv;
+                               cmd->cmd.scan->fields[field_count].num_bits = scan_size;
+                               cmd->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                               cmd->cmd.scan->fields[field_count].in_value = fields[j].in_value;
+                               field_count++;
                        }
                }
                if (!found)
@@ -752,13 +849,10 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
                        }
 #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;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;
+                       cmd->cmd.scan->fields[field_count].num_bits = 1;
+                       cmd->cmd.scan->fields[field_count].out_value = NULL;
+                       cmd->cmd.scan->fields[field_count].in_value = NULL;
+                       field_count++;
                }
                else
                {
@@ -772,6 +866,9 @@ int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields,
 #endif
                }
        }
+
+       /* field_count represents the true number of fields setup*/
+       cmd->cmd.scan->num_fields = field_count;
        return ERROR_OK;
 }
 
@@ -786,7 +883,6 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap,
        int scan_size;
        int bypass_devices = 0;
 
-       jtag_command_t **last_cmd = jtag_get_last_command_p();
        jtag_tap_t *tap;
 
        /* count devices in bypass */
@@ -803,17 +899,18 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap,
        }
 
        /* 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));
+
+       jtag_queue_command(cmd);
+
+       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;
+       cmd->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       cmd->cmd.scan->ir_scan = false;
+       cmd->cmd.scan->num_fields = num_fields + bypass_devices;
+       cmd->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
+       cmd->cmd.scan->end_state = end_state;
 
        tap = NULL;
        nth_tap = -1;
@@ -823,7 +920,7 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap,
                        break;
                }
                nth_tap++;
-               (*last_cmd)->cmd.scan->fields[field_count].tap = tap;
+               cmd->cmd.scan->fields[field_count].tap = tap;
 
                if (tap == target_tap)
                {
@@ -841,13 +938,10 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap,
                                u8 out_value[4];
                                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;
-                               (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;
-                               (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;
-                               (*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;
-                               (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;
+                               cmd->cmd.scan->fields[field_count].num_bits = scan_size;
+                               cmd->cmd.scan->fields[field_count].out_value = buf_cpy(out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                               cmd->cmd.scan->fields[field_count].in_value = NULL;
+                               field_count++;
                        }
                } else
                {
@@ -860,13 +954,10 @@ void MINIDRIVER(interface_jtag_add_dr_out)(jtag_tap_t *target_tap,
                        }
 #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;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;
-                       (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;
+                       cmd->cmd.scan->fields[field_count].num_bits = 1;
+                       cmd->cmd.scan->fields[field_count].out_value = NULL;
+                       cmd->cmd.scan->fields[field_count].in_value = NULL;
+                       field_count++;
                }
        }
 }
@@ -884,34 +975,28 @@ void jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, tap_state_t st
 
 int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
 {
-       int i;
-       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_SCAN;
+       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+
+       jtag_queue_command(cmd);
+
+       cmd->type = JTAG_SCAN;
 
        /* 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->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       cmd->cmd.scan->ir_scan = false;
+       cmd->cmd.scan->num_fields = num_fields;
+       cmd->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
+       cmd->cmd.scan->end_state = state;
 
-       for (i = 0; i < num_fields; i++)
+       for (int 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;
-               (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
-               (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
-               (*last_cmd)->cmd.scan->fields[i].in_handler = fields[i].in_handler;
-               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[i].in_handler_priv;
+               cmd->cmd.scan->fields[i].tap = fields[i].tap;
+               cmd->cmd.scan->fields[i].num_bits = num_bits;
+               cmd->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
+               cmd->cmd.scan->fields[i].in_value = fields[i].in_value;
        }
 
        return ERROR_OK;
@@ -930,16 +1015,16 @@ 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);
 
-       (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-       (*last_cmd)->cmd.statemove->end_state = state;
+       cmd->type = JTAG_STATEMOVE;
+
+       cmd->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+       cmd->cmd.statemove->end_state = state;
 
        return ERROR_OK;
 }
@@ -984,38 +1069,35 @@ void jtag_add_pathmove(int num_states, tap_state_t *path)
 
 int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, 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));
+
+       jtag_queue_command(cmd);
+
+       cmd->type = JTAG_PATHMOVE;
 
-       (*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);
+       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 (i = 0; i < num_states; i++)
-               (*last_cmd)->cmd.pathmove->path[i] = path[i];
+       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;
 }
@@ -1035,16 +1117,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;
 }
 
@@ -1175,17 +1257,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);
 
-       (*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->type = JTAG_RESET;
+
+       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;
 }
@@ -1201,16 +1282,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);
+
+       cmd->type = JTAG_SLEEP;
 
-       (*last_cmd)->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
-       (*last_cmd)->cmd.sleep->us = us;
+       cmd->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
+       cmd->cmd.sleep->us = us;
 
        return ERROR_OK;
 }
@@ -1244,7 +1324,7 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
        int i;
 
        bit_count = jtag_scan_size(cmd);
-       *buffer = malloc(CEIL(bit_count, 8));
+       *buffer = calloc(1,CEIL(bit_count, 8));
 
        bit_count = 0;
 
@@ -1296,7 +1376,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
                /* if neither in_value nor in_handler
                 * are specified we don't have to examine this field
                 */
-               if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
+               if (cmd->fields[i].in_value)
                {
                        int num_bits = cmd->fields[i].num_bits;
                        u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
@@ -1310,28 +1390,6 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
                        if (cmd->fields[i].in_value)
                        {
                                buf_cpy(captured, cmd->fields[i].in_value, num_bits);
-
-                               if (cmd->fields[i].in_handler)
-                               {
-                                       if (cmd->fields[i].in_handler(cmd->fields[i].in_value, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
-                                       {
-                                               LOG_WARNING("in_handler: with \"in_value\", mismatch in %s", cmd->ir_scan ? "SIR" : "SDR" );
-                                               retval = ERROR_JTAG_QUEUE_FAILED;
-                                       }
-                               }
-                       }
-
-                       /* no in_value specified, but a handler takes care of the scanned data */
-                       if (cmd->fields[i].in_handler && (!cmd->fields[i].in_value))
-                       {
-                               if (cmd->fields[i].in_handler(captured, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
-                               {
-                                       /* We're going to call the error:handler later, but if the in_handler
-                                        * reported an error we report this failure upstream
-                                        */
-                                       LOG_WARNING("in_handler: w/o \"in_value\", mismatch in %s",  cmd->ir_scan ? "SIR" : "SDR" );
-                                       retval = ERROR_JTAG_QUEUE_FAILED;
-                               }
                        }
 
                        free(captured);
@@ -1347,34 +1405,35 @@ static const char *jtag_tap_name(jtag_tap_t *tap)
        return (tap == NULL) ? "(unknown)" : tap->dotted_name;
 }
 
-int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)
+int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits)
 {
        int retval = ERROR_OK;
-       int num_bits = field->num_bits;
 
        int compare_failed = 0;
 
-       if (field->in_check_mask)
-               compare_failed = buf_cmp_mask(captured, field->in_check_value, field->in_check_mask, num_bits);
+       if (in_check_mask)
+               compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits);
        else
-               compare_failed = buf_cmp(captured, field->in_check_value, num_bits);
+               compare_failed = buf_cmp(captured, in_check_value, num_bits);
 
        if (compare_failed){
                /* An error handler could have caught the failing check
                 * only report a problem when there wasn't a handler, or if the handler
                 * acknowledged the error
                 */
+               /*
                LOG_WARNING("TAP %s:",
                                        jtag_tap_name(field->tap));
+                                       */
                if (compare_failed)
                {
                        char *captured_char = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
-                       char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
+                       char *in_check_value_char = buf_to_str(in_check_value, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
 
-                       if (field->in_check_mask)
+                       if (in_check_mask)
                        {
                                char *in_check_mask_char;
-                               in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
+                               in_check_mask_char = buf_to_str(in_check_mask, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
                                LOG_WARNING("value captured during scan didn't pass the requested check:");
                                LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s",
                                                        captured_char, in_check_value_char, in_check_mask_char);
@@ -1395,21 +1454,24 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)
        return retval;
 }
 
-/*
-  set up checking of this field using the in_handler. The values passed in must be valid until
-  after jtag_execute() has completed.
- */
-void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handler_t *in_error_handler)
+void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask)
 {
-       if (value)
-               field->in_handler = jtag_check_value;
-       else
-               field->in_handler = NULL;       /* No check, e.g. embeddedice uses value==NULL to indicate no check */
-       field->in_handler_priv = NULL;
-       field->in_check_value = value;
-       field->in_check_mask = mask;
+       assert(field->in_value != NULL);
+
+       if (value==NULL)
+       {
+               /* no checking to do */
+               return;
+       }
+
+       jtag_execute_queue_noclear();
+
+       int retval=jtag_check_value_inner(field->in_value, value, mask, field->num_bits);
+       jtag_set_error(retval);
 }
 
+
+
 enum scan_type jtag_scan_type(scan_command_t *cmd)
 {
        int i;
@@ -1417,7 +1479,7 @@ enum scan_type jtag_scan_type(scan_command_t *cmd)
 
        for (i = 0; i < cmd->num_fields; i++)
        {
-               if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
+               if (cmd->fields[i].in_value)
                        type |= SCAN_IN;
                if (cmd->fields[i].out_value)
                        type |= SCAN_OUT;
@@ -1426,7 +1488,47 @@ enum scan_type jtag_scan_type(scan_command_t *cmd)
        return type;
 }
 
-int MINIDRIVER(interface_jtag_execute_queue)(void)
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+/* add callback to end of queue */
+void jtag_add_callback4(jtag_callback_t callback, u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+{
+       struct jtag_callback_entry *entry=cmd_queue_alloc(sizeof(struct jtag_callback_entry));
+
+       entry->next=NULL;
+       entry->callback=callback;
+       entry->in=in;
+       entry->data1=data1;
+       entry->data2=data2;
+       entry->data3=data3;
+
+       if (jtag_callback_queue_head==NULL)
+       {
+               jtag_callback_queue_head=entry;
+               jtag_callback_queue_tail=entry;
+       } else
+       {
+               jtag_callback_queue_tail->next=entry;
+               jtag_callback_queue_tail=entry;
+       }
+}
+
+
+static int jtag_convert_to_callback4(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+{
+       ((jtag_callback1_t)data1)(in);
+       return ERROR_OK;
+}
+
+void jtag_add_callback(jtag_callback1_t callback, u8 *in)
+{
+       jtag_add_callback4(jtag_convert_to_callback4, in, (jtag_callback_data_t)callback, 0, 0);
+}
+#endif
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+
+int interface_jtag_execute_queue(void)
 {
        int retval;
 
@@ -1438,16 +1540,36 @@ int MINIDRIVER(interface_jtag_execute_queue)(void)
 
        retval = jtag->execute_queue();
 
+       if (retval == ERROR_OK)
+       {
+               struct jtag_callback_entry *entry;
+               for (entry=jtag_callback_queue_head; entry!=NULL; entry=entry->next)
+               {
+                       retval=entry->callback(entry->in, entry->data1, entry->data2, entry->data3);
+                       if (retval!=ERROR_OK)
+                               break;
+               }
+       }
+
        cmd_queue_free();
 
+       jtag_callback_queue_head = NULL;
+       jtag_callback_queue_tail = NULL;
+
        jtag_command_queue = NULL;
-       last_comand_pointer = &jtag_command_queue;
+       last_command_pointer = &jtag_command_queue;
 
        return retval;
 }
+#endif
 
-static void jtag_execute_queue_noclear(void)
+void jtag_execute_queue_noclear(void)
 {
+       /* each flush can take as much as 1-2ms on high bandwidth low latency interfaces.
+        * E.g. a JTAG over TCP/IP or USB....
+        */
+       jtag_flush_queue_count++;
+
        int retval=interface_jtag_execute_queue();
        /* we keep the first error */
        if ((jtag_error==ERROR_OK)&&(retval!=ERROR_OK))
@@ -1505,7 +1627,7 @@ int jtag_examine_chain(void)
        field.in_value = idcode_buffer;
 
 
-       field.in_handler = NULL;
+
 
        for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
        {
@@ -1679,7 +1801,7 @@ int jtag_validate_chain(void)
        field.num_bits = total_ir_length;
        field.out_value = ir_test;
        field.in_value = ir_test;
-       field.in_handler = NULL;
+
 
        jtag_add_plain_ir_scan(1, &field, TAP_RESET);
        jtag_execute_queue();
@@ -2182,9 +2304,12 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
                COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
        register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
+       register_jim(cmd_ctx, "flush_count", Jim_Command_flush_count, "returns number of times the JTAG queue has been flushed");
 
        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>");
        return ERROR_OK;
 }
 
@@ -2759,7 +2884,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? */
@@ -2782,9 +2907,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)
@@ -2794,27 +2921,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;
-               fields[i].in_check_mask = NULL;
-               fields[i].in_handler = NULL;
-               fields[i].in_handler_priv = 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)
@@ -2843,7 +2966,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)
@@ -2912,16 +3035,10 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
                fields[field_count].out_value = malloc(CEIL(bits, 8));
                str_to_buf(str, len, fields[field_count].out_value, bits, 0);
                fields[field_count].in_value = fields[field_count].out_value;
-               fields[field_count].in_check_mask = NULL;
-               fields[field_count].in_check_value = NULL;
-               fields[field_count].in_handler = NULL;
-               fields[field_count++].in_handler_priv = NULL;
+               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)
@@ -2953,6 +3070,15 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
        return JIM_OK;
 }
 
+
+static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args)
+{
+       Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_flush_queue_count));
+
+       return JIM_OK;
+}
+
+
 static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        if (argc == 1)
@@ -2978,6 +3104,31 @@ 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);
@@ -3156,23 +3307,23 @@ 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(0000000,7),  B8(00101,5),            B8(01010,5),    B8(001101,6),   B8(010110,6) },         /* 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(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 */
+       /*      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 */
 
 #endif
 
@@ -3449,4 +3600,12 @@ 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
+
+
 /*-----</Cable Helper API>--------------------------------------*/