Factoring of jtag_examine_chain for maintainability:
[fw/openocd] / src / jtag / jtag.c
index c8babdce96bdd2d7adb29c95540a2e8d563526ee..ca4eb6849319a1feb9263df2ea723ff5a43a72ff 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,17 +84,13 @@ 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, ...)
  */
@@ -239,32 +232,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)
+int jtag_tap_count_enabled(void)
 {
        jtag_tap_t *t;
        int n;
 
        n = 0;
-       t = jtag_AllTaps();
+       t = jtag_all_taps();
        while(t){
                if( t->enabled ){
                        n++;
@@ -274,12 +258,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 +290,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 +306,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 +315,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 +330,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 +398,18 @@ 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;
-}
-
-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)
-{
-       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 +422,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 +471,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 +559,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 +578,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 +587,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 +604,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 +638,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 +653,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 +673,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 +763,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 +784,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 +810,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 +877,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 +905,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 +919,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,9 +939,16 @@ void jtag_sleep(u32 us)
        alive_sleep(us/1000);
 }
 
+/// 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)
+
 /* Try to examine chain layout according to IEEE 1149.1 Â§12
  */
-int jtag_examine_chain(void)
+static int jtag_examine_chain(void)
 {
        jtag_tap_t *tap;
        scan_field_t field;
@@ -1193,7 +990,7 @@ int jtag_examine_chain(void)
        }
 
        /* point at the 1st tap */
-       tap = jtag_NextEnabledTap(NULL);
+       tap = jtag_tap_next_enabled(NULL);
        if( tap == NULL ){
                LOG_ERROR("JTAG: No taps enabled?");
                return ERROR_JTAG_INIT_FAILED;
@@ -1245,11 +1042,8 @@ int jtag_examine_chain(void)
                                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)",
@@ -1258,58 +1052,58 @@ int jtag_examine_chain(void)
 
                        bit_count += 32;
                }
-               if (tap)
-               {
-                       tap->idcode = idcode;
+               device_count++;
+               if (!tap)
+                       continue;
 
-                       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;
-                                       }
+               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;
                                }
+                       }
 
-                               /* 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)",
+                       /* 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,
-                                                         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] ) );
-                                       }
-
-                                       return ERROR_JTAG_INIT_FAILED;
-                               } else {
-                                       LOG_INFO("JTAG Tap/device matched");
+                                                         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] ) );
                                }
+
+                               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);
+                       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++;
+               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());
+                                 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;
        }
@@ -1317,7 +1111,7 @@ int jtag_examine_chain(void)
        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 +1122,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 +1146,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 +1275,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 +1444,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 +1535,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 +1569,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 +1589,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;
                        }
@@ -1871,8 +1659,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 +1677,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 +1772,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 +1898,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 +1933,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, "---|--------------------|---------|------------|------------|------|------|------|---------");
 
@@ -2288,7 +2085,7 @@ static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, ch
        }
        else
        {
-               jtag_nsrst_delay = strtoul(args[0], NULL, 0);
+               jtag_set_nsrst_delay(strtoul(args[0], NULL, 0));
        }
 
        return ERROR_OK;
@@ -2303,12 +2100,13 @@ static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, ch
        }
        else
        {
-               jtag_ntrst_delay = strtoul(args[0], NULL, 0);
+               jtag_set_ntrst_delay(strtoul(args[0], NULL, 0));
        }
 
        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;
@@ -2342,17 +2140,17 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd,
        int retval=ERROR_OK;
        LOG_DEBUG("handle jtag khz");
 
+       int cur_speed = 0;
        if(argc == 1)
        {
-               speed_khz = strtoul(args[0], NULL, 0);
+               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)
+                       if ((retval=jtag->khz(jtag_get_speed_khz(), &speed_div1))!=ERROR_OK)
                        {
-                               speed_khz = 0;
+                               jtag_set_speed_khz(0);
                                return retval;
                        }
 
@@ -2361,7 +2159,7 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd,
                        retval=jtag->speed(cur_speed);
                } else
                {
-                       hasKHz = 1;
+                       hasKHz = true;
                }
        } else if (argc==0)
        {
@@ -2369,43 +2167,38 @@ static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd,
        {
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
+       cur_speed = jtag_get_speed_khz();
 
        if (jtag!=NULL)
        {
-               if ((retval=jtag->speed_div(jtag_speed, &speed_khz))!=ERROR_OK)
+               if ((retval=jtag->speed_div(jtag_speed, &cur_speed))!=ERROR_OK)
                        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
+
+       tap_state_t state = tap_state_by_name(args[0]);
+       if (state < 0)
        {
-               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, "Invalid state name: %s\n", args[0] );
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
-       command_print(cmd_ctx, "current endstate: %s", tap_state_name(cmd_queue_end_state));
+       jtag_set_end_state(state);
+       jtag_execute_queue();
+
+       command_print(cmd_ctx, "current endstate: %s",
+                       tap_state_name(cmd_queue_end_state));
 
        return ERROR_OK;
 }
@@ -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,13 @@ int jtag_add_statemove(tap_state_t goal_state)
        return retval;
 }
 
+void jtag_set_nsrst_delay(unsigned delay)
+{
+       jtag_nsrst_delay = delay;
+}
+void jtag_set_ntrst_delay(unsigned delay)
+{
+       jtag_ntrst_delay = delay;
+}
+
+