Cleanup jtag_tap_by_abs_position:
[fw/openocd] / src / jtag / jtag.c
index d55888ca8dc2f7561b7028bc264d7b52baad80d5..05cfd94801dcf5b4406389d61c80194313124308 100644 (file)
 #include "config.h"
 #endif
 
-#define INCLUDE_JTAG_MINIDRIVER_H
-#define INCLUDE_JTAG_INTERFACE_H
 #include "jtag.h"
+#include "minidriver.h"
+#include "interface.h"
 
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
 
 
-int jtag_flush_queue_count; /* count # of flushes for profiling / debugging purposes */
+/// The number of JTAG queue flushes (for profiling and debugging purposes).
+static int jtag_flush_queue_count;
 
 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);
@@ -47,16 +48,6 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
 */
 int jtag_error=ERROR_OK;
 
-typedef struct cmd_queue_page_s
-{
-       void *address;
-       size_t used;
-       struct cmd_queue_page_s *next;
-} cmd_queue_page_t;
-
-#define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
-static cmd_queue_page_t *cmd_queue_pages = NULL;
-
 char* jtag_event_strings[] =
 {
        "JTAG controller reset (RESET or TRST)"
@@ -72,27 +63,15 @@ 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;
-static jtag_command_t **next_command_pointer = &jtag_command_queue;
-static jtag_tap_t *jtag_all_taps = NULL;
+/**
+ * List all TAPs that have been created.
+ */
+static jtag_tap_t *__jtag_all_taps = NULL;
+/**
+ * The number of TAPs in the __jtag_all_taps list, used to track the
+ * assigned chain position to new TAPs
+ */
+static int jtag_num_taps = 0;
 
 enum reset_types jtag_reset_config = RESET_NONE;
 tap_state_t cmd_queue_end_state = TAP_RESET;
@@ -105,25 +84,22 @@ int jtag_verify = 1;
 static int jtag_nsrst_delay = 0; /* default to no nSRST delay */
 static int jtag_ntrst_delay = 0; /* default to no nTRST delay */
 
-/* maximum number of JTAG devices expected in the chain
- */
-#define JTAG_MAX_CHAIN_SIZE 20
-
 /* callbacks to inform high-level handlers about JTAG state changes */
 jtag_event_callback_t *jtag_event_callbacks;
 
 /* speed in kHz*/
 static int speed_khz = 0;
 /* flag if the kHz speed was defined */
-static int hasKHz = 0;
+static bool hasKHz = false;
 
 /* jtag interfaces (parport, FTDI-USB, TI-USB, ...)
  */
 
 #if BUILD_ECOSBOARD == 1
        extern jtag_interface_t zy1000_interface;
-#endif
-
+#elif defined(BUILD_MINIDRIVER_DUMMY)
+       extern jtag_interface_t minidummy_interface;
+#else // standard drivers
 #if BUILD_PARPORT == 1
        extern jtag_interface_t parport_interface;
 #endif
@@ -179,11 +155,21 @@ static int hasKHz = 0;
 #if BUILD_ARMJTAGEW == 1
        extern jtag_interface_t armjtagew_interface;
 #endif
+#endif // standard drivers
 
+/**
+ * The list of built-in JTAG interfaces, containing entries for those
+ * drivers that were enabled by the @c configure script.
+ *
+ * The list should be defined to contain either one minidriver interface
+ * or some number of standard driver interfaces, never both.
+ */
 jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_ECOSBOARD == 1
        &zy1000_interface,
-#endif
+#elif defined(BUILD_MINIDRIVER_DUMMY)
+       &minidummy_interface,
+#else // standard drivers
 #if BUILD_PARPORT == 1
        &parport_interface,
 #endif
@@ -226,24 +212,19 @@ jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_ARMJTAGEW == 1
        &armjtagew_interface,
 #endif
+#endif // standard drivers
        NULL,
 };
 
-static jtag_interface_t *jtag = NULL;
+struct jtag_interface_s *jtag = NULL;
 
 /* configuration */
 static jtag_interface_t *jtag_interface = NULL;
 int jtag_speed = 0;
 
-/* forward declarations */
-//void jtag_add_pathmove(int num_states, tap_state_t *path);
-//void jtag_add_runtest(int num_cycles, tap_state_t endstate);
-//void jtag_add_end_state(tap_state_t endstate);
-//void jtag_add_sleep(u32 us);
-//int jtag_execute_queue(void);
-static tap_state_t tap_state_by_name(const char *name);
-
 /* jtag commands */
+static int handle_interface_list_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc);
 static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -254,7 +235,6 @@ static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, ch
 
 static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
-static int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 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);
@@ -265,102 +245,88 @@ static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, ch
 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)
+jtag_tap_t *jtag_all_taps(void)
 {
-       return jtag_all_taps;
+       return __jtag_all_taps;
 };
 
-int jtag_NumTotalTaps(void)
+int jtag_tap_count(void)
 {
-       jtag_tap_t *t;
-       int n;
+       return jtag_num_taps;
+}
 
-       n = 0;
-       t = jtag_AllTaps();
-       while(t){
-               n++;
+unsigned jtag_tap_count_enabled(void)
+{
+       jtag_tap_t *t = jtag_all_taps();
+       unsigned n = 0;
+       while(t)
+       {
+               if (t->enabled)
+                       n++;
                t = t->next_tap;
        }
        return n;
 }
 
-int jtag_NumEnabledTaps(void)
+/// Append a new TAP to the chain of all taps.
+void jtag_tap_add(struct jtag_tap_s *t)
 {
-       jtag_tap_t *t;
-       int n;
+       t->abs_chain_position = jtag_num_taps++;
 
-       n = 0;
-       t = jtag_AllTaps();
-       while(t){
-               if( t->enabled ){
-                       n++;
-               }
-               t = t->next_tap;
-       }
-       return n;
+       jtag_tap_t **tap = &__jtag_all_taps;
+       while(*tap != NULL)
+               tap = &(*tap)->next_tap;
+       *tap = t;
 }
 
-jtag_tap_t *jtag_TapByString( const char *s )
+jtag_tap_t *jtag_tap_by_string(const char *s)
 {
-       jtag_tap_t *t;
+       /* try by name first */
+       jtag_tap_t *t = jtag_all_taps();
+       while (t)
+       {
+               if (0 == strcmp(t->dotted_name, s))
+                       return t;
+               t = t->next_tap;
+       }
+
+       /* no tap found by name, so try to parse the name as a number */
        char *cp;
+       unsigned n = strtoul(s, &cp, 0);
+       if ((s == cp) || (*cp != 0))
+               return NULL;
 
-       t = jtag_AllTaps();
-       /* try name first */
-       while(t){
-               if( 0 == strcmp( t->dotted_name, s ) ){
-                       break;
-               } else {
-                       t = t->next_tap;
-               }
-       }
-       /* backup plan is by number */
-       if( t == NULL ){
-               /* ok - is "s" a number? */
-               int n;
-               n = strtol( s, &cp, 0 );
-               if( (s != cp) && (*cp == 0) ){
-                       /* Then it is... */
-                       t = jtag_TapByAbsPosition(n);
-               }
-       }
-       return t;
+       return jtag_tap_by_abs_position(n);
 }
 
-jtag_tap_t * jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o )
+jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
 {
-       jtag_tap_t *t;
-       const char *cp;
-
-       cp = Jim_GetString( o, NULL );
-       if(cp == NULL){
+       const char *cp = Jim_GetString(o, NULL);
+       jtag_tap_t *t = cp ? jtag_tap_by_string(cp) : NULL;
+       if (NULL == cp)
                cp = "(unknown)";
-               t = NULL;
-       }  else {
-               t = jtag_TapByString( cp );
-       }
-       if( t == NULL ){
-               Jim_SetResult_sprintf(interp,"Tap: %s is unknown", cp );
-       }
+       if (NULL == t)
+               Jim_SetResult_sprintf(interp, "Tap '%s' could not be found", cp);
        return t;
 }
 
 /* returns a pointer to the n-th device in the scan chain */
-jtag_tap_t * jtag_TapByAbsPosition( int n )
+jtag_tap_t *jtag_tap_by_abs_position(int n)
 {
-       int orig_n;
-       jtag_tap_t *t;
-
-       orig_n = n;
-       t = jtag_AllTaps();
+       jtag_tap_t *t = jtag_all_taps();
 
-       while( t && (n > 0)) {
-               n--;
+       while (t && n-- > 0)
                t = t->next_tap;
-       }
+
        return t;
 }
 
+const char *jtag_tap_name(const jtag_tap_t *tap)
+{
+       return (tap == NULL) ? "(unknown)" : tap->dotted_name;
+}
+
+
 int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv)
 {
        jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
@@ -423,150 +389,32 @@ int jtag_call_event_callbacks(enum jtag_event event)
        return ERROR_OK;
 }
 
-void jtag_queue_command(jtag_command_t * cmd)
+static void jtag_checks(void)
 {
-       // this command goes on the end, so ensure the queue terminates
-       cmd->next = NULL;
-
-       jtag_command_t **last_cmd = next_command_pointer;
-       assert(NULL != last_cmd);
-       assert(NULL == *last_cmd);
-       *last_cmd = cmd;
-
-       // store location where the next command pointer will be stored
-       next_command_pointer = &cmd->next;
+       assert(jtag_trst == 0);
 }
 
-void* cmd_queue_alloc(size_t size)
-{
-       cmd_queue_page_t **p_page = &cmd_queue_pages;
-       int offset;
-       u8 *t;
-
-       /*
-        * WARNING:
-        *    We align/round the *SIZE* per below
-        *    so that all pointers returned by
-        *    this function are reasonably well
-        *    aligned.
-        *
-        * If we did not, then an "odd-length" request would cause the
-        * *next* allocation to be at an *odd* address, and because
-        * this function has the same type of api as malloc() - we
-        * must also return pointers that have the same type of
-        * alignment.
-        *
-        * What I do not/have is a reasonable portable means
-        * to align by...
-        *
-        * The solution here, is based on these suggestions.
-        * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
-        *
-        */
-       union worse_case_align {
-               int i;
-               long l;
-               float f;
-               void *v;
-       };
-#define ALIGN_SIZE  (sizeof(union worse_case_align))
-
-       /* The alignment process. */
-       size = (size + ALIGN_SIZE -1) & (~(ALIGN_SIZE-1));
-       /* Done... */
-
-       if (*p_page)
-       {
-               while ((*p_page)->next)
-                       p_page = &((*p_page)->next);
-               if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
-                       p_page = &((*p_page)->next);
-       }
-
-       if (!*p_page)
-       {
-               *p_page = malloc(sizeof(cmd_queue_page_t));
-               (*p_page)->used = 0;
-               (*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
-               (*p_page)->next = NULL;
-       }
-
-       offset = (*p_page)->used;
-       (*p_page)->used += size;
-
-       t=(u8 *)((*p_page)->address);
-       return t + offset;
-}
-
-void cmd_queue_free(void)
-{
-       cmd_queue_page_t *page = cmd_queue_pages;
-
-       while (page)
-       {
-               cmd_queue_page_t *last = page;
-               free(page->address);
-               page = page->next;
-               free(last);
-       }
-
-       cmd_queue_pages = NULL;
-}
-
-void jtag_command_queue_reset(void)
+static void jtag_prelude(tap_state_t state)
 {
-       cmd_queue_free();
+       jtag_checks();
 
-       jtag_command_queue = NULL;
-       next_command_pointer = &jtag_command_queue;
-}
+       assert(state!=TAP_INVALID);
 
-/**
- * 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;
+       cmd_queue_cur_state = state;
 }
 
-
-static void jtag_prelude1(void)
-{
-       if (jtag_trst == 1)
-       {
-               LOG_WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-               jtag_error=ERROR_JTAG_TRST_ASSERTED;
-               return;
-       }
-
-       if (cmd_queue_end_state == TAP_RESET)
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-}
-
-static void jtag_prelude(tap_state_t state)
+void jtag_alloc_in_value32(scan_field_t *field)
 {
-       jtag_prelude1();
-
-       if (state != TAP_INVALID)
-               jtag_add_end_state(state);
-
-       cmd_queue_cur_state = cmd_queue_end_state;
+       interface_jtag_alloc_in_value32(field);
 }
 
-void jtag_add_ir_scan_noverify(int in_num_fields, const scan_field_t *in_fields, tap_state_t state)
+void jtag_add_ir_scan_noverify(int in_count, const scan_field_t *in_fields,
+               tap_state_t state)
 {
-       int retval;
        jtag_prelude(state);
 
-       retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, cmd_queue_end_state);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
-
+       int retval = interface_jtag_add_ir_scan(in_count, in_fields, state);
+       jtag_set_error(retval);
 }
 
 
@@ -600,126 +448,33 @@ void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t st
        }
 }
 
-/**
- * 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)
-{
-       size_t num_taps = jtag_NumEnabledTaps();
-
-       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));
-
-       jtag_queue_command(cmd);
-
-       cmd->type                               = JTAG_SCAN;
-       cmd->cmd.scan                   = scan;
-
-       scan->ir_scan                   = true;
-       scan->num_fields                = num_taps;     /* one field per device */
-       scan->fields                    = out_fields;
-       scan->end_state                 = state;
-
-
-       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 != in_fields[j].tap)
-                               continue;
-
-                       /* 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 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(field->out_value, tap->cur_instr, tap->ir_length);
-
-               field++;
-       }
-
-       assert(field == out_fields + num_taps); /* paranoia: jtag_NumEnabledTaps() and jtag_NextEnabledTap() not in sync */
-
-       return ERROR_OK;
-}
-
 /**
  * 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)
+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(in_num_fields, in_fields, cmd_queue_end_state);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
+       int retval = interface_jtag_add_plain_ir_scan(
+                       in_num_fields, in_fields, state);
+       jtag_set_error(retval);
 }
 
-
-/**
- * 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)
+void jtag_add_callback(jtag_callback1_t f, u8 *in)
 {
-
-       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);
-
-       cmd->type                               = JTAG_SCAN;
-       cmd->cmd.scan                   = scan;
-
-       scan->ir_scan                   = true;
-       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;
+       interface_jtag_add_callback(f, in);
 }
 
-
+void jtag_add_callback4(jtag_callback_t f, u8 *in,
+               jtag_callback_data_t data1, jtag_callback_data_t data2,
+               jtag_callback_data_t data3)
+{
+       interface_jtag_add_callback4(f, in, data1, data2, data3);
+}
 
 int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits);
 
@@ -728,27 +483,6 @@ 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);
 }
 
-#ifdef HAVE_JTAG_MINIDRIVER_H
-void interface_jtag_add_scan_check_alloc(scan_field_t *field)
-{
-       /* We're executing this synchronously, so try to use local storage. */
-       if (field->num_bits > 32)
-       {
-               unsigned num_bytes = TAP_SCAN_BYTES(field->num_bits);
-               field->in_value = (u8 *)malloc(num_bytes);
-               field->allocated = 1;
-       }
-       else
-               field->in_value = field->intmp;
-}
-#else
-void interface_jtag_add_scan_check_alloc(scan_field_t *field)
-{
-       unsigned num_bytes = TAP_SCAN_BYTES(field->num_bits);
-       field->in_value = (u8 *)cmd_queue_alloc(num_bytes);
-}
-#endif
-
 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)
 {
@@ -799,394 +533,121 @@ void jtag_add_dr_scan_check(int in_num_fields, scan_field_t *in_fields, tap_stat
 
 
 /**
- * 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().
- *
+ * Generate a DR SCAN using the fields passed to the function.
+ * For connected TAPs, the function checks in_fields and uses fields
+ * specified there.  For bypassed TAPs, the function generates a dummy
+ * 1-bit 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)
+void jtag_add_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_dr_scan(in_num_fields, in_fields, cmd_queue_end_state);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
-}
-
-
-/**
- * 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 */
-
-       size_t bypass_devices = 0;
-
-       for (jtag_tap_t * tap = jtag_NextEnabledTap(NULL); tap != NULL; tap = jtag_NextEnabledTap(tap))
-       {
-               if (tap->bypass)
-                       bypass_devices++;
-       }
-
-       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;
-
-       scan->ir_scan                   = false;
-       scan->num_fields                = in_num_fields + bypass_devices;
-       scan->fields                    = out_fields;
-       scan->end_state                 = state;
-
-
-       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)
-               {
-                       scan_field_t * start_field = field;     /* keep initial position for assert() */
-
-                       for (int j = 0; j < in_num_fields; j++)
-                       {
-                               if (tap != in_fields[j].tap)
-                                       continue;
-
-                               cmd_queue_scan_field_clone(field, in_fields + j);
-
-                               field++;
-                       }
-
-                       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
-               {
-                       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 in_num_fields,
-               const int *num_bits,
-               const u32 *value,
-               tap_state_t end_state)
-{
-       /* count devices in 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++;
-       }
-
-
-       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;
-
-       scan->ir_scan                   = false;
-       scan->num_fields                = in_num_fields + bypass_devices;
-       scan->fields                    = out_fields;
-       scan->end_state                 = end_state;
-
-
-       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)
-               {
-                       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];
-                               size_t scan_size = num_bits[j];
-                               buf_set_u32(out_value, 0, scan_size, value[j]);
-
-                               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++;
-                       }
-               }
-
-               /* if a TAP is bypassed, generated a dummy bit*/
-               else
-               {
-
-                       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 */
+       int retval;
+       retval = interface_jtag_add_dr_scan(in_num_fields, in_fields, state);
+       jtag_set_error(retval);
 }
 
-
 /**
- * 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
- *
+ * Duplicate the scan fields passed into the function into a DR SCAN
+ * command.  Unlike jtag_add_dr_scan(), 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)
+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(in_num_fields, in_fields, cmd_queue_end_state);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
+       int retval;
+       retval = interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state);
+       jtag_set_error(retval);
 }
 
-
-/**
- * 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)
+void jtag_add_dr_out(jtag_tap_t* tap,
+               int num_fields, const int* num_bits, const u32* value,
+               tap_state_t 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 * sizeof(scan_field_t));
-
-       jtag_queue_command(cmd);
+       assert(end_state != TAP_INVALID);
 
-       cmd->type                               = JTAG_SCAN;
-       cmd->cmd.scan                   = scan;
+       cmd_queue_cur_state = end_state;
 
-       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;
+       interface_jtag_add_dr_out(tap,
+                       num_fields, num_bits, value,
+                       end_state);
 }
 
-
 void jtag_add_tlr(void)
 {
        jtag_prelude(TAP_RESET);
-
-       int retval;
-       retval=interface_jtag_add_tlr();
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
-}
-
-int MINIDRIVER(interface_jtag_add_tlr)(void)
-{
-       tap_state_t state = TAP_RESET;
-
-       /* allocate memory for a new list member */
-       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-
-       jtag_queue_command(cmd);
-
-       cmd->type = JTAG_STATEMOVE;
-
-       cmd->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-       cmd->cmd.statemove->end_state = state;
-
-       return ERROR_OK;
+       jtag_set_error(interface_jtag_add_tlr());
+       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
 }
 
 void jtag_add_pathmove(int num_states, const tap_state_t *path)
 {
        tap_state_t cur_state = cmd_queue_cur_state;
-       int i;
-       int retval;
 
        /* the last state has to be a stable state */
        if (!tap_is_state_stable(path[num_states - 1]))
        {
                LOG_ERROR("BUG: TAP path doesn't finish in a stable state");
-               exit(-1);
+               jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE);
+               return;
        }
 
-       for (i=0; i<num_states; i++)
+       for (int i = 0; i < num_states; i++)
        {
                if (path[i] == TAP_RESET)
                {
                        LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences");
-                       exit(-1);
+                       jtag_set_error(ERROR_JTAG_STATE_INVALID);
+                       return;
                }
 
                if ( tap_state_transition(cur_state, true)  != path[i]
                  && tap_state_transition(cur_state, false) != path[i])
                {
-                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[i]));
-                       exit(-1);
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
+                                       tap_state_name(cur_state), tap_state_name(path[i]));
+                       jtag_set_error(ERROR_JTAG_TRANSITION_INVALID);
+                       return;
                }
                cur_state = path[i];
        }
 
-       jtag_prelude1();
+       jtag_checks();
 
-       retval = interface_jtag_add_pathmove(num_states, path);
+       jtag_set_error(interface_jtag_add_pathmove(num_states, path));
        cmd_queue_cur_state = path[num_states - 1];
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
-}
-
-int MINIDRIVER(interface_jtag_add_pathmove)(int num_states, const tap_state_t *path)
-{
-       /* allocate memory for a new list member */
-       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-
-       jtag_queue_command(cmd);
-
-       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)
-{
-       /* allocate memory for a new list member */
-       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-
-       jtag_queue_command(cmd);
-
-       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;
 }
 
 void jtag_add_runtest(int num_cycles, tap_state_t state)
 {
-       int retval;
-
        jtag_prelude(state);
-
-       /* executed by sw or hw fifo */
-       retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
+       jtag_set_error(interface_jtag_add_runtest(num_cycles, state));
 }
 
 
-int MINIDRIVER(interface_jtag_add_clocks)( int num_cycles )
+void jtag_add_clocks(int num_cycles)
 {
-       /* allocate memory for a new list member */
-       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;
-
-       return ERROR_OK;
-}
-
-void jtag_add_clocks( int num_cycles )
-{
-       int retval;
-
-       if( !tap_is_state_stable(cmd_queue_cur_state) )
+       if (!tap_is_state_stable(cmd_queue_cur_state))
        {
-                LOG_ERROR( "jtag_add_clocks() was called with TAP in non-stable state \"%s\"",
-                                tap_state_name(cmd_queue_cur_state) );
-                jtag_error = ERROR_JTAG_NOT_STABLE_STATE;
+                LOG_ERROR("jtag_add_clocks() called with TAP in unstable state \"%s\"",
+                                tap_state_name(cmd_queue_cur_state));
+                jtag_set_error(ERROR_JTAG_NOT_STABLE_STATE);
                 return;
        }
 
-       if( num_cycles > 0 )
+       if (num_cycles > 0)
        {
-               jtag_prelude1();
-
-               retval = interface_jtag_add_clocks(num_cycles);
-               if (retval != ERROR_OK)
-                       jtag_error=retval;
+               jtag_checks();
+               jtag_set_error(interface_jtag_add_clocks(num_cycles));
        }
 }
 
 void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 {
        int trst_with_tlr = 0;
-       int retval;
 
        /* FIX!!! there are *many* different cases here. A better
         * approach is needed for legal combinations of transitions...
@@ -1210,7 +671,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (!req_tlr_or_trst))
        {
                LOG_ERROR("BUG: requested reset would assert trst");
-               jtag_error=ERROR_FAIL;
+               jtag_set_error(ERROR_FAIL);
                return;
        }
 
@@ -1223,7 +684,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
        {
                LOG_ERROR("BUG: requested SRST assertion, but the current configuration doesn't support this");
-               jtag_error=ERROR_FAIL;
+               jtag_set_error(ERROR_FAIL);
                return;
        }
 
@@ -1243,10 +704,10 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 
        jtag_srst = req_srst;
 
-       retval = interface_jtag_add_reset(jtag_trst, jtag_srst);
-       if (retval!=ERROR_OK)
+       int retval = interface_jtag_add_reset(jtag_trst, jtag_srst);
+       if (retval != ERROR_OK)
        {
-               jtag_error=retval;
+               jtag_set_error(retval);
                return;
        }
        jtag_execute_queue();
@@ -1265,9 +726,8 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (trst_with_tlr)
        {
                LOG_DEBUG("JTAG reset with RESET instead of TRST");
-               jtag_add_end_state(TAP_RESET);
+               jtag_set_end_state(TAP_RESET);
                jtag_add_tlr();
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
                return;
        }
 
@@ -1278,163 +738,37 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                 */
                LOG_DEBUG("TRST line asserted");
                tap_set_state(TAP_RESET);
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-       }
-       else
-       {
-               if (jtag_ntrst_delay)
-                       jtag_add_sleep(jtag_ntrst_delay * 1000);
-       }
-}
-
-int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst)
-{
-       /* allocate memory for a new list member */
-       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-
-       jtag_queue_command(cmd);
-
-       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;
-}
-
-void jtag_add_end_state(tap_state_t state)
-{
-       cmd_queue_end_state = state;
-       if ((cmd_queue_end_state == TAP_DRSHIFT)||(cmd_queue_end_state == TAP_IRSHIFT))
-       {
-               LOG_ERROR("BUG: TAP_DRSHIFT/IRSHIFT can't be end state. Calling code should use a larger scan field");
-       }
-}
-
-int MINIDRIVER(interface_jtag_add_sleep)(u32 us)
-{
-       /* allocate memory for a new list member */
-       jtag_command_t * cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-
-       jtag_queue_command(cmd);
-
-       cmd->type = JTAG_SLEEP;
-
-       cmd->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
-       cmd->cmd.sleep->us = us;
-
-       return ERROR_OK;
-}
-
-void jtag_add_sleep(u32 us)
-{
-       keep_alive(); /* we might be running on a very slow JTAG clk */
-       int retval=interface_jtag_add_sleep(us);
-       if (retval!=ERROR_OK)
-               jtag_error=retval;
-       return;
-}
-
-int jtag_scan_size(const scan_command_t *cmd)
-{
-       int bit_count = 0;
-       int i;
-
-       /* count bits in scan command */
-       for (i = 0; i < cmd->num_fields; i++)
-       {
-               bit_count += cmd->fields[i].num_bits;
-       }
-
-       return bit_count;
-}
-
-int jtag_build_buffer(const scan_command_t *cmd, u8 **buffer)
-{
-       int bit_count = 0;
-       int i;
-
-       bit_count = jtag_scan_size(cmd);
-       *buffer = calloc(1,CEIL(bit_count, 8));
-
-       bit_count = 0;
-
-#ifdef _DEBUG_JTAG_IO_
-       LOG_DEBUG("%s num_fields: %i", cmd->ir_scan ? "IRSCAN" : "DRSCAN", cmd->num_fields);
-#endif
-
-       for (i = 0; i < cmd->num_fields; i++)
-       {
-               if (cmd->fields[i].out_value)
-               {
-#ifdef _DEBUG_JTAG_IO_
-                       char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : cmd->fields[i].num_bits, 16);
-#endif
-                       buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
-#ifdef _DEBUG_JTAG_IO_
-                       LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i, cmd->fields[i].num_bits, char_buf);
-                       free(char_buf);
-#endif
-               }
-               else
-               {
-#ifdef _DEBUG_JTAG_IO_
-                       LOG_DEBUG("fields[%i].out_value[%i]: NULL", i, cmd->fields[i].num_bits);
-#endif
-               }
-
-               bit_count += cmd->fields[i].num_bits;
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+       }
+       else
+       {
+               if (jtag_ntrst_delay)
+                       jtag_add_sleep(jtag_ntrst_delay * 1000);
        }
-
-#ifdef _DEBUG_JTAG_IO_
-       //LOG_DEBUG("bit_count totalling: %i",  bit_count );
-#endif
-
-       return bit_count;
 }
 
-int jtag_read_buffer(u8 *buffer, const scan_command_t *cmd)
+tap_state_t jtag_set_end_state(tap_state_t state)
 {
-       int i;
-       int bit_count = 0;
-       int retval;
-
-       /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
-       retval = ERROR_OK;
-
-       for (i = 0; i < cmd->num_fields; i++)
+       if ((state == TAP_DRSHIFT)||(state == TAP_IRSHIFT))
        {
-               /* if neither in_value nor in_handler
-                * are specified we don't have to examine this field
-                */
-               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);
-
-#ifdef _DEBUG_JTAG_IO_
-                       char *char_buf = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
-                       LOG_DEBUG("fields[%i].in_value[%i]: 0x%s", i, num_bits, char_buf);
-                       free(char_buf);
-#endif
-
-                       if (cmd->fields[i].in_value)
-                       {
-                               buf_cpy(captured, cmd->fields[i].in_value, num_bits);
-                       }
-
-                       free(captured);
-               }
-               bit_count += cmd->fields[i].num_bits;
+               LOG_ERROR("BUG: TAP_DRSHIFT/IRSHIFT can't be end state. Calling code should use a larger scan field");
        }
 
-       return retval;
+       if (state!=TAP_INVALID)
+               cmd_queue_end_state = state;
+       return cmd_queue_end_state;
 }
 
-static const char *jtag_tap_name(const jtag_tap_t *tap)
+tap_state_t jtag_get_end_state(void)
 {
-       return (tap == NULL) ? "(unknown)" : tap->dotted_name;
+       return cmd_queue_end_state;
+}
+
+void jtag_add_sleep(u32 us)
+{
+       /// @todo Here, keep_alive() appears to be a layering violation!!!
+       keep_alive();
+       jtag_set_error(interface_jtag_add_sleep(us));
 }
 
 int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits)
@@ -1504,119 +838,37 @@ void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask)
 
 
 
-enum scan_type jtag_scan_type(const scan_command_t *cmd)
-{
-       int i;
-       int type = 0;
-
-       for (i = 0; i < cmd->num_fields; i++)
-       {
-               if (cmd->fields[i].in_value)
-                       type |= SCAN_IN;
-               if (cmd->fields[i].out_value)
-                       type |= SCAN_OUT;
-       }
-
-       return type;
-}
-
-
-#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 default_interface_jtag_execute_queue(void)
 {
-       int retval;
-
-       if (jtag==NULL)
+       if (NULL == jtag)
        {
-               LOG_ERROR("No JTAG interface configured yet. Issue 'init' command in startup scripts before communicating with targets.");
+               LOG_ERROR("No JTAG interface configured yet.  "
+                       "Issue 'init' command in startup scripts "
+                       "before communicating with targets.");
                return ERROR_FAIL;
        }
 
-       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;
-               }
-       }
-
-       jtag_callback_queue_head = NULL;
-       jtag_callback_queue_tail = NULL;
-
-       jtag_command_queue_reset();
-
-       return retval;
+       return jtag->execute_queue();
 }
-#endif
 
 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++;
+       jtag_set_error(interface_jtag_execute_queue());
+}
 
-       int retval=interface_jtag_execute_queue();
-       /* we keep the first error */
-       if ((jtag_error==ERROR_OK)&&(retval!=ERROR_OK))
-       {
-               jtag_error=retval;
-       }
+int jtag_get_flush_queue_count(void)
+{
+       return jtag_flush_queue_count;
 }
 
 int jtag_execute_queue(void)
 {
-       int retval;
        jtag_execute_queue_noclear();
-       retval=jtag_error;
-       jtag_error=ERROR_OK;
-       return retval;
+       return jtag_error_clear();
 }
 
-int jtag_reset_callback(enum jtag_event event, void *priv)
+static int jtag_reset_callback(enum jtag_event event, void *priv)
 {
        jtag_tap_t *tap = priv;
 
@@ -1636,175 +888,206 @@ void jtag_sleep(u32 us)
        alive_sleep(us/1000);
 }
 
-/* Try to examine chain layout according to IEEE 1149.1 Â§12
- */
-int jtag_examine_chain(void)
+/// maximum number of JTAG devices expected in the chain
+#define JTAG_MAX_CHAIN_SIZE 20
+
+#define EXTRACT_MFG(X)  (((X) & 0xffe) >> 1)
+#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
+#define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
+
+static int jtag_examine_chain_execute(u8 *idcode_buffer, unsigned num_idcode)
+{
+       scan_field_t field = {
+                       .tap = NULL,
+                       .num_bits = num_idcode * 32,
+                       .out_value = idcode_buffer,
+                       .in_value = idcode_buffer,
+               };
+
+       // initialize to the end of chain ID value
+       for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+
+       jtag_add_plain_dr_scan(1, &field, TAP_RESET);
+       return jtag_execute_queue();
+}
+
+static bool jtag_examine_chain_check(u8 *idcodes, unsigned count)
 {
-       jtag_tap_t *tap;
-       scan_field_t field;
-       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
-       int i;
-       int bit_count;
-       int device_count = 0;
        u8 zero_check = 0x0;
        u8 one_check = 0xff;
 
-       field.tap = NULL;
-       field.num_bits = sizeof(idcode_buffer) * 8;
-       field.out_value = idcode_buffer;
-
-       field.in_value = idcode_buffer;
+       for (unsigned i = 0; i < count * 4; i++)
+       {
+               zero_check |= idcodes[i];
+               one_check &= idcodes[i];
+       }
 
+       /* if there wasn't a single non-zero bit or if all bits were one,
+        * the scan is not valid */
+       if (zero_check == 0x00 || one_check == 0xff)
+       {
+               LOG_ERROR("JTAG communication failure: check connection, "
+                       "JTAG interface, target power etc.");
+               return false;
+       }
+       return true;
+}
 
+static void jtag_examine_chain_display(enum log_levels level, const char *msg,
+               const char *name, u32 idcode)
+{
+       log_printf_lf(level, __FILE__, __LINE__, __FUNCTION__,
+                       "JTAG tap: %s %16.16s: 0x%08x "
+                       "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+               name, msg, idcode,
+               EXTRACT_MFG(idcode), EXTRACT_PART(idcode), EXTRACT_VER(idcode) );
+}
 
+static bool jtag_idcode_is_final(u32 idcode)
+{
+               return idcode == 0x000000FF || idcode == 0xFFFFFFFF;
+}
 
-       for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+/**
+ * This helper checks that remaining bits in the examined chain data are
+ * all as expected, but a single JTAG device requires only 64 bits to be
+ * read back correctly.  This can help identify and diagnose problems
+ * with the JTAG chain earlier, gives more helpful/explicit error messages.
+ */
+static void jtag_examine_chain_end(u8 *idcodes, unsigned count, unsigned max)
+{
+       bool triggered = false;
+       for ( ; count < max - 31; count += 32)
        {
-               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+               u32 idcode = buf_get_u32(idcodes, count, 32);
+               // do not trigger the warning if the data looks good
+               if (!triggered && jtag_idcode_is_final(idcode))
+                       continue;
+               LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
+                               count, idcode);
+               triggered = true;
        }
+}
 
-       jtag_add_plain_dr_scan(1, &field, TAP_RESET);
-       jtag_execute_queue();
+static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
+{
+       if (0 == tap->expected_ids_cnt)
+       {
+               /// @todo Enable LOG_INFO to ask for reports about unknown TAP IDs.
+#if 0
+               LOG_INFO("Uknown JTAG TAP ID: 0x%08x", tap->idcode)
+               LOG_INFO("Please report the chip name and reported ID code to the openocd project");
+#endif
+               return true;
+       }
 
-       for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
+       /* Loop over the expected identification codes and test for a match */
+       u8 ii;
+       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
        {
-               zero_check |= idcode_buffer[i];
-               one_check &= idcode_buffer[i];
+               if (tap->idcode == tap->expected_ids[ii])
+                       break;
        }
 
-       /* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */
-       if ((zero_check == 0x00) || (one_check == 0xff))
+       /* If none of the expected ids matched, log an error */
+       if (ii != tap->expected_ids_cnt)
        {
-               LOG_ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
-               return ERROR_JTAG_INIT_FAILED;
+               LOG_INFO("JTAG Tap/device matched");
+               return true;
+       }
+       jtag_examine_chain_display(LOG_LVL_ERROR, "got",
+                       tap->dotted_name, tap->idcode);
+       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       {
+               char msg[32];
+               snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
+                               ii + 1, tap->expected_ids_cnt);
+               jtag_examine_chain_display(LOG_LVL_ERROR, msg,
+                               tap->dotted_name, tap->expected_ids[ii]);
        }
+       return false;
+}
+
+/* Try to examine chain layout according to IEEE 1149.1 Â§12
+ */
+static int jtag_examine_chain(void)
+{
+       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+       unsigned device_count = 0;
+
+       jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+
+       if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
+               return ERROR_JTAG_INIT_FAILED;
 
        /* point at the 1st tap */
-       tap = jtag_NextEnabledTap(NULL);
-       if( tap == NULL ){
+       jtag_tap_t *tap = jtag_tap_next_enabled(NULL);
+       if (tap == NULL)
+       {
                LOG_ERROR("JTAG: No taps enabled?");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
+       for (unsigned bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
        {
                u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
                if ((idcode & 1) == 0)
                {
                        /* LSB must not be 0, this indicates a device in bypass */
                        LOG_WARNING("Tap/Device does not have IDCODE");
-                       idcode=0;
+                       idcode = 0;
 
                        bit_count += 1;
                }
                else
                {
-                       u32 manufacturer;
-                       u32 part;
-                       u32 version;
-
-                       /* some devices, such as AVR will output all 1's instead of TDI
-                       input value at end of chain. */
-                       if ((idcode == 0x000000FF)||(idcode == 0xFFFFFFFF))
+                       /*
+                        * End of chain (invalid manufacturer ID) some devices, such
+                        * as AVR will output all 1's instead of TDI input value at
+                        * end of chain.
+                        */
+                       if (jtag_idcode_is_final(idcode))
                        {
-                               int unexpected=0;
-                               /* End of chain (invalid manufacturer ID)
-                                *
-                                * The JTAG examine is the very first thing that happens
-                                *
-                                * A single JTAG device requires only 64 bits to be read back correctly.
-                                *
-                                * The code below adds a check that the rest of the data scanned (640 bits)
-                                * are all as expected. This helps diagnose/catch problems with the JTAG chain
-                                *
-                                * earlier and gives more helpful/explicit error messages.
-                                */
-                               for (bit_count += 32; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;bit_count += 32)
-                               {
-                                       idcode = buf_get_u32(idcode_buffer, bit_count, 32);
-                                       if (unexpected||((idcode != 0x000000FF)&&(idcode != 0xFFFFFFFF)))
-                                       {
-                                               LOG_WARNING("Unexpected idcode after end of chain! %d 0x%08x", bit_count, idcode);
-                                               unexpected = 1;
-                                       }
-                               }
-
+                               jtag_examine_chain_end(idcode_buffer,
+                                               bit_count + 32, JTAG_MAX_CHAIN_SIZE * 32);
                                break;
                        }
 
-#define EXTRACT_MFG(X)  (((X) & 0xffe) >> 1)
-                       manufacturer = EXTRACT_MFG(idcode);
-#define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
-                       part = EXTRACT_PART(idcode);
-#define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
-                       version = EXTRACT_VER(idcode);
-
-                       LOG_INFO("JTAG tap: %s tap/device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)",
-                                        ((tap != NULL) ? (tap->dotted_name) : "(not-named)"),
-                               idcode, manufacturer, part, version);
+                       jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
+                                       tap ? tap->dotted_name : "(not-named)",
+                                       idcode);
 
                        bit_count += 32;
                }
-               if (tap)
-               {
-                       tap->idcode = idcode;
-
-                       if (tap->expected_ids_cnt > 0) {
-                               /* Loop over the expected identification codes and test for a match */
-                               u8 ii;
-                               for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
-                                       if( tap->idcode == tap->expected_ids[ii] ){
-                                               break;
-                                       }
-                               }
+               device_count++;
+               if (!tap)
+                       continue;
 
-                               /* If none of the expected ids matched, log an error */
-                               if (ii == tap->expected_ids_cnt) {
-                                       LOG_ERROR("JTAG tap: %s             got: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
-                                                         tap->dotted_name,
-                                                         idcode,
-                                                         EXTRACT_MFG( tap->idcode ),
-                                                         EXTRACT_PART( tap->idcode ),
-                                                         EXTRACT_VER( tap->idcode ) );
-                                       for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
-                                               LOG_ERROR("JTAG tap: %s expected %hhu of %hhu: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
-                                                                 tap->dotted_name,
-                                                                 ii + 1,
-                                                                 tap->expected_ids_cnt,
-                                                                 tap->expected_ids[ii],
-                                                                 EXTRACT_MFG( tap->expected_ids[ii] ),
-                                                                 EXTRACT_PART( tap->expected_ids[ii] ),
-                                                                 EXTRACT_VER( tap->expected_ids[ii] ) );
-                                       }
+               tap->idcode = idcode;
 
-                                       return ERROR_JTAG_INIT_FAILED;
-                               } else {
-                                       LOG_INFO("JTAG Tap/device matched");
-                               }
-                       } else {
-#if 0
-                               LOG_INFO("JTAG TAP ID: 0x%08x - Unknown - please report (A) chipname and (B) idcode to the openocd project",
-                                                tap->idcode);
-#endif
-                       }
-                       tap = jtag_NextEnabledTap(tap);
-               }
-               device_count++;
+               // ensure the TAP ID does matches what was expected
+               if (!jtag_examine_chain_match_tap(tap))
+                       return ERROR_JTAG_INIT_FAILED;
+
+               tap = jtag_tap_next_enabled(tap);
        }
 
        /* see if number of discovered devices matches configuration */
-       if (device_count != jtag_NumEnabledTaps())
+       if (device_count != jtag_tap_count_enabled())
        {
-               LOG_ERROR("number of discovered devices in JTAG chain (%i) doesn't match (enabled) configuration (%i), total taps: %d",
-                                 device_count, jtag_NumEnabledTaps(), jtag_NumTotalTaps());
-               LOG_ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
+               LOG_ERROR("number of discovered devices in JTAG chain (%i) "
+                               "does not match (enabled) configuration (%i), total taps: %d",
+                               device_count, jtag_tap_count_enabled(), jtag_tap_count());
+               LOG_ERROR("check the config file and ensure proper JTAG communication"
+                               " (connections, speed, ...)");
                return ERROR_JTAG_INIT_FAILED;
        }
 
        return ERROR_OK;
 }
 
-int jtag_validate_chain(void)
+static int jtag_validate_chain(void)
 {
        jtag_tap_t *tap;
        int total_ir_length = 0;
@@ -1815,7 +1098,7 @@ int jtag_validate_chain(void)
        tap = NULL;
        total_ir_length = 0;
        for(;;){
-               tap = jtag_NextEnabledTap(tap);
+               tap = jtag_tap_next_enabled(tap);
                if( tap == NULL ){
                        break;
                }
@@ -1839,7 +1122,7 @@ int jtag_validate_chain(void)
        chain_pos = 0;
        int val;
        for(;;){
-               tap = jtag_NextEnabledTap(tap);
+               tap = jtag_tap_next_enabled(tap);
                if( tap == NULL ){
                        break;
                }
@@ -1968,10 +1251,44 @@ static int jtag_tap_configure_cmd( Jim_GetOptInfo *goi, jtag_tap_t * tap)
        return JIM_OK;
 }
 
+
+static void jtag_tap_init(jtag_tap_t *tap)
+{
+       assert(0 != tap->ir_length);
+
+       tap->expected = malloc(tap->ir_length);
+       tap->expected_mask = malloc(tap->ir_length);
+       tap->cur_instr = malloc(tap->ir_length);
+
+       buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value);
+       buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask);
+       buf_set_ones(tap->cur_instr, tap->ir_length);
+
+       // place TAP in bypass mode
+       tap->bypass = 1;
+       // register the reset callback for the TAP
+       jtag_register_event_callback(&jtag_reset_callback, tap);
+
+       LOG_DEBUG("Created Tap: %s @ abs position %d, "
+                       "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
+                               tap->abs_chain_position, tap->ir_length,
+                               tap->ir_capture_value, tap->ir_capture_mask);
+       jtag_tap_add(tap);
+}
+
+static void jtag_tap_free(jtag_tap_t *tap)
+{
+       /// @todo is anything missing? no memory leaks please 
+       free((void *)tap->expected_ids);
+       free((void *)tap->chip);
+       free((void *)tap->tapname);
+       free((void *)tap->dotted_name);
+       free(tap);
+}
+
 static int jim_newtap_cmd( Jim_GetOptInfo *goi )
 {
        jtag_tap_t *pTap;
-       jtag_tap_t **ppTap;
        jim_wide w;
        int x;
        int e;
@@ -2103,58 +1420,18 @@ static int jim_newtap_cmd( Jim_GetOptInfo *goi )
                } /* switch(n->value) */
        } /* while( goi->argc ) */
 
-       /* Did we get all the options? */
-       if( reqbits ){
-               // no
-               Jim_SetResult_sprintf( goi->interp,
-                                                          "newtap: %s missing required parameters",
-                                                          pTap->dotted_name);
-               /* TODO: Tell user what is missing :-( */
-               /* no memory leaks pelase */
-               free(((void *)(pTap->expected_ids)));
-               free(((void *)(pTap->chip)));
-               free(((void *)(pTap->tapname)));
-               free(((void *)(pTap->dotted_name)));
-               free(((void *)(pTap)));
-               return JIM_ERR;
-       }
-
-       pTap->expected      = malloc( pTap->ir_length );
-       pTap->expected_mask = malloc( pTap->ir_length );
-       pTap->cur_instr     = malloc( pTap->ir_length );
-
-       buf_set_u32( pTap->expected,
-                                0,
-                                pTap->ir_length,
-                                pTap->ir_capture_value );
-       buf_set_u32( pTap->expected_mask,
-                                0,
-                                pTap->ir_length,
-                                pTap->ir_capture_mask );
-       buf_set_ones( pTap->cur_instr,
-                                 pTap->ir_length );
-
-       pTap->bypass = 1;
-
-       jtag_register_event_callback(jtag_reset_callback, pTap );
-
-       ppTap = &(jtag_all_taps);
-       while( (*ppTap) != NULL ){
-               ppTap = &((*ppTap)->next_tap);
-       }
-       *ppTap = pTap;
+       /* Did all the required option bits get cleared? */
+       if (0 == reqbits)
        {
-               static int n_taps = 0;
-               pTap->abs_chain_position = n_taps++;
+               jtag_tap_init(pTap);
+               return ERROR_OK;
        }
-       LOG_DEBUG( "Created Tap: %s @ abs position %d, irlen %d, capture: 0x%x mask: 0x%x",
-                               (*ppTap)->dotted_name,
-                               (*ppTap)->abs_chain_position,
-                               (*ppTap)->ir_length,
-                               (*ppTap)->ir_capture_value,
-                               (*ppTap)->ir_capture_mask );
 
-       return ERROR_OK;
+       Jim_SetResult_sprintf(goi->interp,
+                       "newtap: %s missing required parameters",
+                       pTap->dotted_name);
+       jtag_tap_free(pTap);
+       return JIM_ERR;
 }
 
 static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
@@ -2234,7 +1511,7 @@ static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv
 
                {
                        jtag_tap_t *t;
-                       t = jtag_TapByJimObj( goi.interp, goi.argv[0] );
+                       t = jtag_tap_by_jim_obj( goi.interp, goi.argv[0] );
                        if( t == NULL ){
                                return JIM_ERR;
                        }
@@ -2268,7 +1545,7 @@ static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv
                        jtag_tap_t *t;
 
                        Jim_GetOpt_Obj(&goi, &o);
-                       t = jtag_TapByJimObj( goi.interp, o );
+                       t = jtag_tap_by_jim_obj( goi.interp, o );
                        if( t == NULL ){
                                return JIM_ERR;
                        }
@@ -2288,7 +1565,7 @@ static int jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv
                        jtag_tap_t *t;
 
                        Jim_GetOpt_Obj(&goi, &o);
-                       t = jtag_TapByJimObj( goi.interp, o );
+                       t = jtag_tap_by_jim_obj( goi.interp, o );
                        if( t == NULL ){
                                return JIM_ERR;
                        }
@@ -2307,6 +1584,9 @@ 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,
+               "interface_list", &handle_interface_list_command,
+               COMMAND_ANY, "list all built-in interfaces");
        register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
                COMMAND_ANY, "(DEPRECATED) set jtag speed (if supported)");
        register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
@@ -2325,8 +1605,6 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
                COMMAND_EXEC, "print current scan chain configuration");
 
-       register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,
-               COMMAND_EXEC, "finish JTAG operations in <tap_state>");
        register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
                COMMAND_EXEC, "toggle reset lines <trst> <srst>");
        register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
@@ -2358,8 +1636,8 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        }
        if(hasKHz)
        {
-               jtag_interface->khz(speed_khz, &jtag_speed);
-               hasKHz = 0;
+               jtag_interface->khz(jtag_get_speed_khz(), &jtag_speed);
+               hasKHz = false;
        }
 
        if (jtag_interface->init() != ERROR_OK)
@@ -2376,7 +1654,7 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
 
        LOG_DEBUG("Init JTAG chain");
 
-       tap = jtag_NextEnabledTap(NULL);
+       tap = jtag_tap_next_enabled(NULL);
        if( tap == NULL ){
                LOG_ERROR("There are no enabled taps?");
                return ERROR_JTAG_INIT_FAILED;
@@ -2471,6 +1749,15 @@ int jtag_init(struct command_context_s *cmd_ctx)
        return jtag_init_reset(cmd_ctx);
 }
 
+void jtag_set_speed_khz(unsigned khz)
+{
+       speed_khz = khz;
+}
+unsigned jtag_get_speed_khz(void)
+{
+       return speed_khz;
+}
+
 static int default_khz(int khz, int *jtag_speed)
 {
        LOG_ERROR("Translation from khz to jtag_speed not implemented");
@@ -2495,11 +1782,9 @@ static int default_srst_asserted(int *srst_asserted)
        return ERROR_OK;
 }
 
-static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_interface_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
-       int i;
-       int retval;
-
        /* check whether the interface is already configured */
        if (jtag_interface)
        {
@@ -2508,54 +1793,54 @@ static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd
        }
 
        /* interface name is a mandatory argument */
-       if (argc < 1 || args[0][0] == '\0')
-       {
+       if (argc != 1 || args[0][0] == '\0')
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
-       for (i=0; jtag_interfaces[i]; i++)
+       for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
        {
-               if (strcmp(args[0], jtag_interfaces[i]->name) == 0)
-               {
-                       if ((retval = jtag_interfaces[i]->register_commands(cmd_ctx)) != ERROR_OK)
-                       {
+               if (strcmp(args[0], jtag_interfaces[i]->name) != 0)
+                       continue;
+
+               int retval = jtag_interfaces[i]->register_commands(cmd_ctx);
+               if (ERROR_OK != retval)
                                return retval;
-                       }
 
-                       jtag_interface = jtag_interfaces[i];
+               jtag_interface = jtag_interfaces[i];
 
-                       if (jtag_interface->khz == NULL)
-                       {
-                               jtag_interface->khz = default_khz;
-                       }
-                       if (jtag_interface->speed_div == NULL)
-                       {
-                               jtag_interface->speed_div = default_speed_div;
-                       }
-                       if (jtag_interface->power_dropout == NULL)
-                       {
-                               jtag_interface->power_dropout = default_power_dropout;
-                       }
-                       if (jtag_interface->srst_asserted == NULL)
-                       {
-                               jtag_interface->srst_asserted = default_srst_asserted;
-                       }
+               if (jtag_interface->khz == NULL)
+                       jtag_interface->khz = default_khz;
+               if (jtag_interface->speed_div == NULL)
+                       jtag_interface->speed_div = default_speed_div;
+               if (jtag_interface->power_dropout == NULL)
+                       jtag_interface->power_dropout = default_power_dropout;
+               if (jtag_interface->srst_asserted == NULL)
+                       jtag_interface->srst_asserted = default_srst_asserted;
 
-                       return ERROR_OK;
-               }
+               return ERROR_OK;
        }
 
        /* no valid interface was found (i.e. the configuration option,
         * didn't match one of the compiled-in interfaces
         */
-       LOG_ERROR("No valid jtag interface found (%s)", args[0]);
-       LOG_ERROR("compiled-in jtag interfaces:");
-       for (i = 0; jtag_interfaces[i]; i++)
+       LOG_ERROR("The specified JTAG interface was not found (%s)", args[0]);
+       handle_interface_list_command(cmd_ctx, cmd, args, argc);
+       return ERROR_JTAG_INVALID_INTERFACE;
+}
+
+static int handle_interface_list_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
+{
+       if (strcmp(cmd, "interface_list") == 0 && argc > 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       command_print(cmd_ctx, "The following JTAG interfaces are available:");
+       for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
        {
-               LOG_ERROR("%i: %s", i, jtag_interfaces[i]->name);
+               const char *name = jtag_interfaces[i]->name;
+               command_print(cmd_ctx, "%u: %s", i + 1, name);
        }
 
-       return ERROR_JTAG_INVALID_INTERFACE;
+       return ERROR_OK;
 }
 
 static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
@@ -2588,9 +1873,9 @@ static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *c
 
        newargs[0] = Jim_NewStringObj( interp, "jtag", -1   );
        newargs[1] = Jim_NewStringObj( interp, "newtap", -1 );
-       sprintf( buf, "chip%d", jtag_NumTotalTaps() );
+       sprintf( buf, "chip%d", jtag_tap_count() );
        newargs[2] = Jim_NewStringObj( interp, buf, -1 );
-       sprintf( buf, "tap%d", jtag_NumTotalTaps() );
+       sprintf( buf, "tap%d", jtag_tap_count() );
        newargs[3] = Jim_NewStringObj( interp, buf, -1  );
        newargs[4] = Jim_NewStringObj( interp, "-irlen", -1  );
        newargs[5] = Jim_NewStringObj( interp, args[0], -1  );
@@ -2623,7 +1908,7 @@ static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cm
 {
        jtag_tap_t *tap;
 
-       tap = jtag_all_taps;
+       tap = jtag_all_taps();
        command_print(cmd_ctx, "     TapName            | Enabled |   IdCode      Expected    IrLen IrCap  IrMask Instr     ");
        command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------");
 
@@ -2766,40 +2051,34 @@ next:
        return ERROR_OK;
 }
 
-static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
-       if (argc < 1)
-       {
-               LOG_ERROR("jtag_nsrst_delay <ms> command takes one required argument");
-               exit(-1);
-       }
-       else
-       {
-               jtag_nsrst_delay = strtoul(args[0], NULL, 0);
-       }
-
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (argc == 1)
+               jtag_set_nsrst_delay(strtoul(args[0], NULL, 0));
+       command_print(cmd_ctx, "jtag_nsrst_delay: %u", jtag_get_nsrst_delay());
        return ERROR_OK;
 }
 
-static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
-       if (argc < 1)
-       {
-               LOG_ERROR("jtag_ntrst_delay <ms> command takes one required argument");
-               exit(-1);
-       }
-       else
-       {
-               jtag_ntrst_delay = strtoul(args[0], NULL, 0);
-       }
-
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (argc == 1)
+               jtag_set_ntrst_delay(strtoul(args[0], NULL, 0));
+       command_print(cmd_ctx, "jtag_ntrst_delay: %u", jtag_get_ntrst_delay());
        return ERROR_OK;
 }
 
 static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       int retval=ERROR_OK;
+       int retval = ERROR_OK;
 
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
        if (argc == 1)
        {
                LOG_DEBUG("handle jtag speed");
@@ -2810,14 +2089,7 @@ static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cm
                /* this command can be called during CONFIG,
                 * in which case jtag isn't initialized */
                if (jtag)
-               {
-                       retval=jtag->speed(cur_speed);
-               }
-       } else if (argc == 0)
-       {
-       } else
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
+                       retval = jtag->speed(cur_speed);
        }
        command_print(cmd_ctx, "jtag_speed: %d", jtag_speed);
 
@@ -2826,104 +2098,71 @@ static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cm
 
 static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       int retval=ERROR_OK;
-       LOG_DEBUG("handle jtag khz");
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if(argc == 1)
+       int retval = ERROR_OK;
+       int cur_speed = 0;
+       if (argc == 1)
        {
-               speed_khz = strtoul(args[0], NULL, 0);
+               LOG_DEBUG("handle jtag khz");
+
+               jtag_set_speed_khz(strtoul(args[0], NULL, 0));
                if (jtag != NULL)
                {
-                       int cur_speed = 0;
                        LOG_DEBUG("have interface set up");
                        int speed_div1;
-                       if ((retval=jtag->khz(speed_khz, &speed_div1))!=ERROR_OK)
+                       retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
+                       if (ERROR_OK != retval)
                        {
-                               speed_khz = 0;
+                               jtag_set_speed_khz(0);
                                return retval;
                        }
-
                        cur_speed = jtag_speed = speed_div1;
 
-                       retval=jtag->speed(cur_speed);
-               } else
-               {
-                       hasKHz = 1;
+                       retval = jtag->speed(cur_speed);
                }
-       } else if (argc==0)
-       {
-       } else
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
+               else
+                       hasKHz = true;
        }
 
-       if (jtag!=NULL)
+       cur_speed = jtag_get_speed_khz();
+       if (jtag != NULL)
        {
-               if ((retval=jtag->speed_div(jtag_speed, &speed_khz))!=ERROR_OK)
+               retval = jtag->speed_div(jtag_speed, &cur_speed);
+               if (ERROR_OK != retval)
                        return retval;
        }
 
-       if (speed_khz==0)
-       {
+       if (cur_speed)
+               command_print(cmd_ctx, "%d kHz", cur_speed);
+       else
                command_print(cmd_ctx, "RCLK - adaptive");
-       } else
-       {
-               command_print(cmd_ctx, "%d kHz", speed_khz);
-       }
        return retval;
 
 }
 
-static int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_jtag_reset_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
-       tap_state_t state;
-
-       if (argc < 1)
-       {
+       if (argc != 2)
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       else
-       {
-               state = tap_state_by_name( args[0] );
-               if( state < 0 ){
-                       command_print( cmd_ctx, "Invalid state name: %s\n", args[0] );
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-               jtag_add_end_state(state);
-               jtag_execute_queue();
-       }
-       command_print(cmd_ctx, "current endstate: %s", tap_state_name(cmd_queue_end_state));
-
-       return ERROR_OK;
-}
 
-static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
        int trst = -1;
-       int srst = -1;
-
-       if (argc < 2)
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
        if (args[0][0] == '1')
                trst = 1;
        else if (args[0][0] == '0')
                trst = 0;
        else
-       {
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
+       int srst = -1;
        if (args[1][0] == '1')
                srst = 1;
        else if (args[1][0] == '0')
                srst = 0;
        else
-       {
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
        if (jtag_interface_init(cmd_ctx) != ERROR_OK)
                return ERROR_JTAG_INIT_FAILED;
@@ -2934,18 +2173,16 @@ static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cm
        return ERROR_OK;
 }
 
-static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_runtest_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
 {
-       if (argc < 1)
-       {
+       if (argc != 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
-       jtag_add_runtest(strtol(args[0], NULL, 0), TAP_INVALID);
+       jtag_add_runtest(strtol(args[0], NULL, 0), jtag_get_end_state());
        jtag_execute_queue();
 
        return ERROR_OK;
-
 }
 
 /*
@@ -3017,7 +2254,7 @@ static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, c
 
        for (i = 0; i < num_fields; i++)
        {
-               tap = jtag_TapByString( args[i*2] );
+               tap = jtag_tap_by_string( args[i*2] );
                if (tap==NULL)
                {
                        command_print( cmd_ctx, "Tap: %s unknown", args[i*2] );
@@ -3125,7 +2362,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
                }
        } /* validate args */
 
-       tap = jtag_TapByJimObj( interp, args[1] );
+       tap = jtag_tap_by_jim_obj( interp, args[1] );
        if( tap == NULL ){
                return JIM_ERR;
        }
@@ -3184,7 +2421,7 @@ static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args
 
 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));
+       Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
 
        return JIM_OK;
 }
@@ -3215,27 +2452,33 @@ static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, ch
        return ERROR_OK;
 }
 
+void jtag_set_verify(bool enable)
+{
+       jtag_verify = enable;
+}
+
+bool jtag_will_verify()
+{
+       return jtag_verify;
+}
+
 static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
        if (argc == 1)
        {
                if (strcmp(args[0], "enable") == 0)
-               {
-                       jtag_verify = 1;
-               }
+                       jtag_set_verify(true);
                else if (strcmp(args[0], "disable") == 0)
-               {
-                       jtag_verify = 0;
-               } else
-               {
+                       jtag_set_verify(false);
+               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");
+       const char *status = jtag_will_verify() ? "enabled": "disabled";
+       command_print(cmd_ctx, "verify jtag capture is %s", status);
 
        return ERROR_OK;
 }
@@ -3282,525 +2525,80 @@ void jtag_tap_handle_event( jtag_tap_t * tap, enum jtag_tap_event e)
        }
 }
 
-/*-----<Cable Helper API>---------------------------------------*/
-
-/*  these Cable Helper API functions are all documented in the jtag.h header file,
-       using a Doxygen format.  And since Doxygen's configuration file "Doxyfile",
-       is setup to prefer its docs in the header file, no documentation is here, for
-       if it were, it would have to be doubly maintained.
-*/
-
-/**
- * @see tap_set_state() and tap_get_state() accessors.
- * Actual name is not important since accessors hide it.
- */
-static tap_state_t state_follower = TAP_RESET;
-
-void tap_set_state_impl( tap_state_t new_state )
-{
-       /* this is the state we think the TAPs are in now, was cur_state */
-       state_follower = new_state;
-}
-
-tap_state_t tap_get_state()
-{
-       return state_follower;
-}
-
-/**
- * @see tap_set_end_state() and tap_get_end_state() accessors.
- * Actual name is not important because accessors hide it.
- */
-static tap_state_t end_state_follower = TAP_RESET;
-
-void tap_set_end_state( tap_state_t new_end_state )
-{
-       /* this is the state we think the TAPs will be in at completion of the
-          current TAP operation, was end_state
-       */
-       end_state_follower = new_end_state;
-}
-
-tap_state_t tap_get_end_state()
-{
-       return end_state_follower;
-}
-
-
-int tap_move_ndx( tap_state_t astate )
-{
-       /* given a stable state, return the index into the tms_seqs[] array within tap_get_tms_path() */
-
-       int ndx;
-
-       switch( astate )
-       {
-       case TAP_RESET:         ndx = 0;                        break;
-       case TAP_DRSHIFT:       ndx = 2;                        break;
-       case TAP_DRPAUSE:       ndx = 3;                        break;
-       case TAP_IDLE:          ndx = 1;                        break;
-       case TAP_IRSHIFT:       ndx = 4;                        break;
-       case TAP_IRPAUSE:       ndx = 5;                        break;
-       default:
-               LOG_ERROR( "fatal: unstable state \"%s\" used in tap_move_ndx()", tap_state_name(astate) );
-               exit(1);
-       }
-
-       return ndx;
-}
-
-
-/* tap_move[i][j]: tap movement command to go from state i to state j
- * 0: Test-Logic-Reset
- * 1: Run-Test/Idle
- * 2: Shift-DR
- * 3: Pause-DR
- * 4: Shift-IR
- * 5: Pause-IR
- *
- * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
- */
-struct tms_sequences
-{
-       u8      bits;
-       u8      bit_count;
-
-};
-
-/*
- * These macros allow us to specify TMS state transitions by bits rather than hex bytes.
- * Read the bits from LSBit first to MSBit last (right-to-left).
- */
-#define HEX__(n) 0x##n##LU
-
-#define B8__(x) \
-        (((x) & 0x0000000FLU)?(1<<0):0) \
-       +(((x) & 0x000000F0LU)?(1<<1):0) \
-       +(((x) & 0x00000F00LU)?(1<<2):0) \
-       +(((x) & 0x0000F000LU)?(1<<3):0) \
-       +(((x) & 0x000F0000LU)?(1<<4):0) \
-       +(((x) & 0x00F00000LU)?(1<<5):0) \
-       +(((x) & 0x0F000000LU)?(1<<6):0) \
-       +(((x) & 0xF0000000LU)?(1<<7):0)
-
-#define B8(bits,count)         { ((u8)B8__(HEX__(bits))), (count) }
-
-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
-               me on MC1322x. I've recreated the jlink portion of patch with this
-               new state table. His changes to my state table are pretty minor in
-               terms of total transitions, but Peter feels that his version fixes
-               some long-standing problems.
-               Jeff
-
-               I added the bit count into the table, reduced RESET column to 7 bits from 8.
-               Dick
-
-               state specific comments:
-               ------------------------
-               *->RESET                   tried the 5 bit reset and it gave me problems, 7 bits seems to
-                                          work better on ARM9 with ft2232 driver.  (Dick)
-
-               RESET->DRSHIFT add 1 extra clock cycles in the RESET state before advancing.
-                                               needed on ARM9 with ft2232 driver.  (Dick)
-
-               RESET->IRSHIFT add 1 extra clock cycles in the RESET state before advancing.
-                                               needed on ARM9 with ft2232 driver.  (Dick)
-       */
-
-       /* 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(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 */
-
-};
-
-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;
-}
-
-
-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;
-}
-
-
-bool tap_is_state_stable(tap_state_t astate)
-{
-       bool is_stable;
-
-       /*      A switch() is used because it is symbol dependent
-               (not value dependent like an array), and can also check bounds.
-       */
-       switch( astate )
-       {
-       case TAP_RESET:
-       case TAP_IDLE:
-       case TAP_DRSHIFT:
-       case TAP_DRPAUSE:
-       case TAP_IRSHIFT:
-       case TAP_IRPAUSE:
-               is_stable = true;
-               break;
-       default:
-               is_stable = false;
-       }
-
-       return is_stable;
-}
-
-tap_state_t tap_state_transition(tap_state_t cur_state, bool tms)
-{
-       tap_state_t new_state;
-
-       /*      A switch is used because it is symbol dependent and not value dependent
-               like an array.  Also it can check for out of range conditions.
-       */
-
-       if (tms)
-       {
-               switch (cur_state)
-               {
-               case TAP_RESET:
-                       new_state = cur_state;
-                       break;
-               case TAP_IDLE:
-               case TAP_DRUPDATE:
-               case TAP_IRUPDATE:
-                       new_state = TAP_DRSELECT;
-                       break;
-               case TAP_DRSELECT:
-                       new_state = TAP_IRSELECT;
-                       break;
-               case TAP_DRCAPTURE:
-               case TAP_DRSHIFT:
-                       new_state = TAP_DREXIT1;
-                       break;
-               case TAP_DREXIT1:
-               case TAP_DREXIT2:
-                       new_state = TAP_DRUPDATE;
-                       break;
-               case TAP_DRPAUSE:
-                       new_state = TAP_DREXIT2;
-                       break;
-               case TAP_IRSELECT:
-                       new_state = TAP_RESET;
-                       break;
-               case TAP_IRCAPTURE:
-               case TAP_IRSHIFT:
-                       new_state = TAP_IREXIT1;
-                       break;
-               case TAP_IREXIT1:
-               case TAP_IREXIT2:
-                       new_state = TAP_IRUPDATE;
-                       break;
-               case TAP_IRPAUSE:
-                       new_state = TAP_IREXIT2;
-                       break;
-               default:
-                       LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
-                       exit(1);
-                       break;
-               }
-       }
-       else
-       {
-               switch (cur_state)
-               {
-               case TAP_RESET:
-               case TAP_IDLE:
-               case TAP_DRUPDATE:
-               case TAP_IRUPDATE:
-                       new_state = TAP_IDLE;
-                       break;
-               case TAP_DRSELECT:
-                       new_state = TAP_DRCAPTURE;
-                       break;
-               case TAP_DRCAPTURE:
-               case TAP_DRSHIFT:
-               case TAP_DREXIT2:
-                       new_state = TAP_DRSHIFT;
-                       break;
-               case TAP_DREXIT1:
-               case TAP_DRPAUSE:
-                       new_state = TAP_DRPAUSE;
-                       break;
-               case TAP_IRSELECT:
-                       new_state = TAP_IRCAPTURE;
-                       break;
-               case TAP_IRCAPTURE:
-               case TAP_IRSHIFT:
-               case TAP_IREXIT2:
-                       new_state = TAP_IRSHIFT;
-                       break;
-               case TAP_IREXIT1:
-               case TAP_IRPAUSE:
-                       new_state = TAP_IRPAUSE;
-                       break;
-               default:
-                       LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
-                       exit(1);
-                       break;
-               }
-       }
-
-       return new_state;
-}
-
-const char* tap_state_name(tap_state_t state)
-{
-       const char* ret;
-
-       switch( state )
-       {
-       case TAP_RESET:         ret = "RESET";                  break;
-       case TAP_IDLE:          ret = "RUN/IDLE";               break;
-       case TAP_DRSELECT:      ret = "DRSELECT";               break;
-       case TAP_DRCAPTURE: ret = "DRCAPTURE";          break;
-       case TAP_DRSHIFT:       ret = "DRSHIFT";                        break;
-       case TAP_DREXIT1:       ret = "DREXIT1";                        break;
-       case TAP_DRPAUSE:       ret = "DRPAUSE";                        break;
-       case TAP_DREXIT2:       ret = "DREXIT2";                        break;
-       case TAP_DRUPDATE:      ret = "DRUPDATE";               break;
-       case TAP_IRSELECT:      ret = "IRSELECT";               break;
-       case TAP_IRCAPTURE: ret = "IRCAPTURE";          break;
-       case TAP_IRSHIFT:       ret = "IRSHIFT";                        break;
-       case TAP_IREXIT1:       ret = "IREXIT1";                        break;
-       case TAP_IRPAUSE:       ret = "IRPAUSE";                        break;
-       case TAP_IREXIT2:       ret = "IREXIT2";                        break;
-       case TAP_IRUPDATE:      ret = "IRUPDATE";               break;
-       default:                                ret = "???";
-       }
-
-       return ret;
-}
-
-static tap_state_t tap_state_by_name( const char *name )
-{
-       tap_state_t x;
-
-       for( x = 0 ; x < TAP_NUM_STATES ; x++ ){
-               /* be nice to the human */
-               if( 0 == strcasecmp( name, tap_state_name(x) ) ){
-                       return x;
-               }
-       }
-       /* not found */
-       return TAP_INVALID;
-}
-
-#ifdef _DEBUG_JTAG_IO_
-
-#define JTAG_DEBUG_STATE_APPEND(buf, len, bit) \
-               do { buf[len] = bit ? '1' : '0'; } while(0)
-#define JTAG_DEBUG_STATE_PRINT(a, b, astr, bstr) \
-               DEBUG_JTAG_IO("TAP/SM: %9s -> %5s\tTMS: %s\tTDI: %s", \
-                       tap_state_name(a), tap_state_name(b), astr, bstr)
-
-tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf,
-               unsigned tap_bits, tap_state_t next_state)
-{
-       const u8 *tms_buffer;
-       const u8 *tdi_buffer;
-       unsigned tap_bytes;
-       unsigned cur_byte;
-       unsigned cur_bit;
-
-       unsigned tap_out_bits;
-       char tms_str[33];
-       char tdi_str[33];
-
-       tap_state_t last_state;
-
-       // set startstate (and possibly last, if tap_bits == 0)
-       last_state = next_state;
-       DEBUG_JTAG_IO("TAP/SM: START state: %s", tap_state_name(next_state));
-
-       tms_buffer = (const u8 *)tms_buf;
-       tdi_buffer = (const u8 *)tdi_buf;
-
-       tap_bytes = TAP_SCAN_BYTES(tap_bits);
-       DEBUG_JTAG_IO("TAP/SM: TMS bits: %u (bytes: %u)", tap_bits, tap_bytes);
-
-       tap_out_bits = 0;
-       for(cur_byte = 0; cur_byte < tap_bytes; cur_byte++)
-       {
-               for(cur_bit = 0; cur_bit < 8; cur_bit++)
-               {
-                       // make sure we do not run off the end of the buffers
-                       unsigned tap_bit = cur_byte * 8 + cur_bit;
-                       if (tap_bit == tap_bits)
-                               break;
-
-                       // check and save TMS bit
-                       tap_bit = !!(tms_buffer[cur_byte] & (1 << cur_bit));
-                       JTAG_DEBUG_STATE_APPEND(tms_str, tap_out_bits, tap_bit);
-
-                       // use TMS bit to find the next TAP state
-                       next_state = tap_state_transition(last_state, tap_bit);
-
-                       // check and store TDI bit
-                       tap_bit = !!(tdi_buffer[cur_byte] & (1 << cur_bit));
-                       JTAG_DEBUG_STATE_APPEND(tdi_str, tap_out_bits, tap_bit);
-
-                       // increment TAP bits
-                       tap_out_bits++;
-
-                       // Only show TDO bits on state transitions, or
-                       // after some number of bits in the same state.
-                       if ((next_state == last_state) && (tap_out_bits < 32))
-                               continue;
-
-                       // terminate strings and display state transition
-                       tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
-                       JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
-
-                       // reset state
-                       last_state = next_state;
-                       tap_out_bits = 0;
-               }
-       }
-
-       if (tap_out_bits)
-       {
-               // terminate strings and display state transition
-               tms_str[tap_out_bits] = tdi_str[tap_out_bits] = 0;
-               JTAG_DEBUG_STATE_PRINT(last_state, next_state, tms_str, tdi_str);
-       }
-
-       DEBUG_JTAG_IO("TAP/SM: FINAL state: %s", tap_state_name(next_state));
-
-       return next_state;
-}
-#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)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
        if (argc == 1)
        {
+               bool use_new_table;
                if (strcmp(args[0], "short") == 0)
-               {
-                       tms_seqs=&short_tms_seqs;
-               }
+                       use_new_table = true;
                else if (strcmp(args[0], "long") == 0)
-               {
-                       tms_seqs=&old_tms_seqs;
-               } else
-               {
+                       use_new_table = false;
+               else
                        return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-       } else if (argc != 0)
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
+
+               tap_use_new_tms_table(use_new_table);
        }
 
-       command_print(cmd_ctx, "tms sequence is  %s", (tms_seqs==&short_tms_seqs) ? "short": "long");
+       command_print(cmd_ctx, "tms sequence is  %s",
+                       tap_uses_new_tms_table() ? "short": "long");
 
        return ERROR_OK;
 }
 
-/*-----</Cable Helper API>--------------------------------------*/
-
-
 /**
- * Function jtag_add_statemove
- * moves from the current state to the goal \a state. This needs
+ * 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.
+ *
+ * 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.
+ *
+ * @note Unless @a 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.
+ *
+ * Otherwise, state must be immediately reachable in one clock cycle,
+ * and does not need to be a stable state.
  */
 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.
-               */
+               unsigned tms_bits  = tap_get_tms_path(cur_state, goal_state);
+               unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state);
+               tap_state_t moves[8];
+               assert(tms_count < DIM(moves));
 
-               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)
+               for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1)
                {
                        bool bit = tms_bits & 1;
 
@@ -3810,23 +2608,31 @@ int jtag_add_statemove(tap_state_t goal_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 );
+               jtag_add_pathmove(1, &goal_state);
        }
 
        else
-       {
-               retval = ERROR_FAIL;
-       }
+               return ERROR_FAIL;
 
-       return retval;
+       return ERROR_OK;
 }
 
+void jtag_set_nsrst_delay(unsigned delay)
+{
+       jtag_nsrst_delay = delay;
+}
+unsigned jtag_get_nsrst_delay(void)
+{
+       return jtag_nsrst_delay;
+}
+void jtag_set_ntrst_delay(unsigned delay)
+{
+       jtag_ntrst_delay = delay;
+}
+unsigned jtag_get_ntrst_delay(void)
+{
+       return jtag_ntrst_delay;
+}