Extend handle_jtag_n{s,t}rst_delay_command routines:
[fw/openocd] / src / jtag / jtag.c
index c8babdce96bdd2d7adb29c95540a2e8d563526ee..91430b6e7f0c53e5ecd73a39e74c856d9b0a001f 100644 (file)
 #include "config.h"
 #endif
 
-#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,9 +63,15 @@ const Jim_Nvp nvp_jtag_tap_event[] = {
 int jtag_trst = 0;
 int jtag_srst = 0;
 
-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;
@@ -87,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
@@ -161,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
@@ -208,6 +212,7 @@ jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_ARMJTAGEW == 1
        &armjtagew_interface,
 #endif
+#endif // standard drivers
        NULL,
 };
 
@@ -228,7 +233,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);
@@ -239,32 +243,23 @@ 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;
-
-       n = 0;
-       t = jtag_AllTaps();
-       while(t){
-               n++;
-               t = t->next_tap;
-       }
-       return n;
+       return jtag_num_taps;
 }
 
-int jtag_NumEnabledTaps(void)
+unsigned jtag_tap_count_enabled(void)
 {
        jtag_tap_t *t;
-       int n;
+       unsigned n;
 
        n = 0;
-       t = jtag_AllTaps();
+       t = jtag_all_taps();
        while(t){
                if( t->enabled ){
                        n++;
@@ -274,12 +269,23 @@ int jtag_NumEnabledTaps(void)
        return n;
 }
 
-jtag_tap_t *jtag_TapByString( const char *s )
+/// Append a new TAP to the chain of all taps.
+static void jtag_tap_add(struct jtag_tap_s *t)
+{
+       t->abs_chain_position = jtag_num_taps++;
+
+       jtag_tap_t **tap = &__jtag_all_taps;
+       while(*tap != NULL)
+               tap = &(*tap)->next_tap;
+       *tap = t;
+}
+
+jtag_tap_t *jtag_tap_by_string( const char *s )
 {
        jtag_tap_t *t;
        char *cp;
 
-       t = jtag_AllTaps();
+       t = jtag_all_taps();
        /* try name first */
        while(t){
                if( 0 == strcmp( t->dotted_name, s ) ){
@@ -295,13 +301,13 @@ jtag_tap_t *jtag_TapByString( const char *s )
                n = strtol( s, &cp, 0 );
                if( (s != cp) && (*cp == 0) ){
                        /* Then it is... */
-                       t = jtag_TapByAbsPosition(n);
+                       t = jtag_tap_by_abs_position(n);
                }
        }
        return t;
 }
 
-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;
@@ -311,7 +317,7 @@ jtag_tap_t * jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o )
                cp = "(unknown)";
                t = NULL;
        }  else {
-               t = jtag_TapByString( cp );
+               t = jtag_tap_by_string( cp );
        }
        if( t == NULL ){
                Jim_SetResult_sprintf(interp,"Tap: %s is unknown", cp );
@@ -320,13 +326,13 @@ jtag_tap_t * jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o )
 }
 
 /* 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();
+       t = jtag_all_taps();
 
        while( t && (n > 0)) {
                n--;
@@ -335,6 +341,12 @@ jtag_tap_t * jtag_TapByAbsPosition( int n )
        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;
@@ -397,125 +409,18 @@ int jtag_call_event_callbacks(enum jtag_event event)
        return ERROR_OK;
 }
 
-void jtag_queue_command(jtag_command_t * cmd)
-{
-       // 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;
-}
-
-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)
-{
-       cmd_queue_free();
-
-       jtag_command_queue = NULL;
-       next_command_pointer = &jtag_command_queue;
-}
-
-static void jtag_prelude1(void)
+static void jtag_checks(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);
+       assert(jtag_trst == 0);
 }
 
 static void jtag_prelude(tap_state_t state)
 {
-       jtag_prelude1();
+       jtag_checks();
 
-       if (state != TAP_INVALID)
-               jtag_add_end_state(state);
+       assert(state!=TAP_INVALID);
 
-       cmd_queue_cur_state = cmd_queue_end_state;
+       cmd_queue_cur_state = state;
 }
 
 void jtag_alloc_in_value32(scan_field_t *field)
@@ -528,7 +433,7 @@ void jtag_add_ir_scan_noverify(int in_num_fields, const scan_field_t *in_fields,
        int retval;
        jtag_prelude(state);
 
-       retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, cmd_queue_end_state);
+       retval=interface_jtag_add_ir_scan(in_num_fields, in_fields, state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 
@@ -577,7 +482,7 @@ void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields, ta
 
        jtag_prelude(state);
 
-       retval=interface_jtag_add_plain_ir_scan(in_num_fields, in_fields, cmd_queue_end_state);
+       retval=interface_jtag_add_plain_ir_scan(in_num_fields, in_fields, state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -665,7 +570,7 @@ void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields, tap_stat
 
        jtag_prelude(state);
 
-       retval=interface_jtag_add_dr_scan(in_num_fields, in_fields, cmd_queue_end_state);
+       retval=interface_jtag_add_dr_scan(in_num_fields, in_fields, state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -684,7 +589,7 @@ void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields, ta
 
        jtag_prelude(state);
 
-       retval=interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, cmd_queue_end_state);
+       retval=interface_jtag_add_plain_dr_scan(in_num_fields, in_fields, state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -693,14 +598,13 @@ void jtag_add_dr_out(jtag_tap_t* tap,
                int num_fields, const int* num_bits, const u32* value,
                tap_state_t end_state)
 {
-       if (end_state != TAP_INVALID)
-               cmd_queue_end_state = end_state;
+       assert(end_state != TAP_INVALID);
 
-       cmd_queue_cur_state = cmd_queue_end_state;
+       cmd_queue_cur_state = end_state;
 
        interface_jtag_add_dr_out(tap,
                        num_fields, num_bits, value,
-                       cmd_queue_end_state);
+                       end_state);
 }
 
 void jtag_add_tlr(void)
@@ -711,6 +615,8 @@ void jtag_add_tlr(void)
        retval=interface_jtag_add_tlr();
        if (retval!=ERROR_OK)
                jtag_error=retval;
+       
+       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
 }
 
 void jtag_add_pathmove(int num_states, const tap_state_t *path)
@@ -743,7 +649,7 @@ void jtag_add_pathmove(int num_states, const tap_state_t *path)
                cur_state = path[i];
        }
 
-       jtag_prelude1();
+       jtag_checks();
 
        retval = interface_jtag_add_pathmove(num_states, path);
        cmd_queue_cur_state = path[num_states - 1];
@@ -758,7 +664,7 @@ void jtag_add_runtest(int num_cycles, tap_state_t state)
        jtag_prelude(state);
 
        /* executed by sw or hw fifo */
-       retval=interface_jtag_add_runtest(num_cycles, cmd_queue_end_state);
+       retval=interface_jtag_add_runtest(num_cycles, state);
        if (retval!=ERROR_OK)
                jtag_error=retval;
 }
@@ -778,7 +684,7 @@ void jtag_add_clocks( int num_cycles )
 
        if( num_cycles > 0 )
        {
-               jtag_prelude1();
+               jtag_checks();
 
                retval = interface_jtag_add_clocks(num_cycles);
                if (retval != ERROR_OK)
@@ -868,9 +774,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;
        }
 
@@ -890,13 +795,21 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        }
 }
 
-void jtag_add_end_state(tap_state_t state)
+tap_state_t jtag_set_end_state(tap_state_t state)
 {
-       cmd_queue_end_state = state;
-       if ((cmd_queue_end_state == TAP_DRSHIFT)||(cmd_queue_end_state == TAP_IRSHIFT))
+       if ((state == TAP_DRSHIFT)||(state == TAP_IRSHIFT))
        {
                LOG_ERROR("BUG: TAP_DRSHIFT/IRSHIFT can't be end state. Calling code should use a larger scan field");
        }
+
+       if (state!=TAP_INVALID)
+               cmd_queue_end_state = state;
+       return cmd_queue_end_state;
+}
+
+tap_state_t jtag_get_end_state(void)
+{
+       return cmd_queue_end_state;
 }
 
 void jtag_add_sleep(u32 us)
@@ -908,107 +821,6 @@ void jtag_add_sleep(u32 us)
        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;
-       }
-
-#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)
-{
-       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 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;
-       }
-
-       return retval;
-}
-
-static const char *jtag_tap_name(const jtag_tap_t *tap)
-{
-       return (tap == NULL) ? "(unknown)" : tap->dotted_name;
-}
-
 int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits)
 {
        int retval = ERROR_OK;
@@ -1076,22 +888,6 @@ 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;
-}
-
 int default_interface_jtag_execute_queue(void)
 {
        if (NULL == jtag)
@@ -1120,6 +916,11 @@ void jtag_execute_queue_noclear(void)
        }
 }
 
+int jtag_get_flush_queue_count(void)
+{
+       return jtag_flush_queue_count;
+}
+
 int jtag_execute_queue(void)
 {
        int retval;
@@ -1129,7 +930,7 @@ int jtag_execute_queue(void)
        return retval;
 }
 
-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;
 
@@ -1149,175 +950,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;
@@ -1328,7 +1160,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;
                }
@@ -1352,7 +1184,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;
                }
@@ -1481,10 +1313,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;
@@ -1616,58 +1482,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 )
@@ -1747,7 +1573,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;
                        }
@@ -1781,7 +1607,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;
                        }
@@ -1801,7 +1627,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;
                        }
@@ -1838,8 +1664,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,
@@ -1871,8 +1695,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)
@@ -1889,7 +1713,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;
@@ -1984,6 +1808,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");
@@ -2101,9 +1934,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  );
@@ -2136,7 +1969,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, "---|--------------------|---------|------------|------------|------|------|------|---------");
 
@@ -2279,40 +2112,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");
@@ -2323,14 +2150,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);
 
@@ -2339,77 +2159,50 @@ 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)
-{
-       tap_state_t state;
-
-       if (argc < 1)
-       {
-               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;
@@ -2454,7 +2247,7 @@ static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd,
                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;
@@ -2530,7 +2323,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] );
@@ -2638,7 +2431,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;
        }
@@ -2697,7 +2490,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;
 }
@@ -2728,27 +2521,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;
 }
@@ -2885,7 +2684,7 @@ 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
+       /*      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
@@ -2904,3 +2703,19 @@ int jtag_add_statemove(tap_state_t goal_state)
        return retval;
 }
 
+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;
+}