jtag: add '-ignore-version' option
[fw/openocd] / src / jtag / core.c
index 1c2e2655cadcb12e5266c82e98913a8fa0a2d5c4..e311bfbcc8d5ce0ecfaee9d0dfa73c90bbead5fb 100644 (file)
@@ -32,7 +32,6 @@
 #endif
 
 #include "jtag.h"
-#include "minidriver.h"
 #include "interface.h"
 
 #ifdef HAVE_STRINGS_H
@@ -244,17 +243,6 @@ struct jtag_tap *jtag_tap_by_string(const char *s)
        return t;
 }
 
-struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
-{
-       const char *cp = Jim_GetString(o, NULL);
-       struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL;
-       if (NULL == cp)
-               cp = "(unknown)";
-       if (NULL == t)
-               Jim_SetResult_sprintf(interp, "Tap '%s' could not be found", cp);
-       return t;
-}
-
 struct jtag_tap* jtag_tap_next_enabled(struct jtag_tap* p)
 {
        p = p ? p->next_tap : jtag_all_taps();
@@ -409,18 +397,6 @@ void jtag_add_plain_ir_scan(int in_num_fields, const struct scan_field *in_field
        jtag_set_error(retval);
 }
 
-void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
-{
-       interface_jtag_add_callback(f, data0);
-}
-
-void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
-               jtag_callback_data_t data1, jtag_callback_data_t data2,
-               jtag_callback_data_t data3)
-{
-       interface_jtag_add_callback4(f, data0, data1, data2, data3);
-}
-
 static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
                uint8_t *in_check_mask, int num_bits);
 
@@ -502,20 +478,6 @@ void jtag_add_plain_dr_scan(int in_num_fields, const struct scan_field *in_field
        jtag_set_error(retval);
 }
 
-void jtag_add_dr_out(struct jtag_tap* tap,
-               int num_fields, const int* num_bits, const uint32_t* value,
-               tap_state_t end_state)
-{
-       assert(end_state != TAP_RESET);
-       assert(end_state != TAP_INVALID);
-
-       cmd_queue_cur_state = end_state;
-
-       interface_jtag_add_dr_out(tap,
-                       num_fields, num_bits, value,
-                       end_state);
-}
-
 void jtag_add_tlr(void)
 {
        jtag_prelude(TAP_RESET);
@@ -586,7 +548,7 @@ int jtag_add_statemove(tap_state_t goal_state)
                unsigned tms_bits  = tap_get_tms_path(cur_state, goal_state);
                unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state);
                tap_state_t moves[8];
-               assert(tms_count < DIM(moves));
+               assert(tms_count < ARRAY_SIZE(moves));
 
                for (unsigned i = 0; i < tms_count; i++, tms_bits >>= 1)
                {
@@ -773,8 +735,7 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
                uint8_t *in_check_mask, int num_bits)
 {
        int retval = ERROR_OK;
-
-       int compare_failed = 0;
+       int compare_failed;
 
        if (in_check_mask)
                compare_failed = buf_cmp_mask(captured, in_check_value, in_check_mask, num_bits);
@@ -997,16 +958,25 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
 
 static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
 {
+       uint32_t idcode = tap->idcode;
+
        /* ignore expected BYPASS codes; warn otherwise */
-       if (0 == tap->expected_ids_cnt && !tap->idcode)
+       if (0 == tap->expected_ids_cnt && !idcode)
                return true;
 
+       /* optionally ignore the JTAG version field */
+       uint32_t mask = tap->ignore_version ? ~(0xff << 24) : ~0;
+
+       idcode &= mask;
+
        /* Loop over the expected identification codes and test for a match */
        unsigned ii, limit = tap->expected_ids_cnt;
 
        for (ii = 0; ii < limit; ii++)
        {
-               if (tap->idcode == tap->expected_ids[ii])
+               uint32_t expected = tap->expected_ids[ii] & mask;
+
+               if (idcode == expected)
                        return true;
 
                /* treat "-expected-id 0" as a "don't-warn" wildcard */
@@ -1064,7 +1034,7 @@ static int jtag_examine_chain(void)
                if ((idcode & 1) == 0)
                {
                        /* Zero for LSB indicates a device in bypass */
-                       LOG_WARNING("TAP %s does not have IDCODE",
+                       LOG_INFO("TAP %s does not have IDCODE",
                                        tap->dotted_name);
                        idcode = 0;
                        tap->hasidcode = false;
@@ -1193,7 +1163,7 @@ static int jtag_validate_ircapture(void)
        /* increase length to add 2 bit sentinel after scan */
        total_ir_length += 2;
 
-       ir_test = malloc(CEIL(total_ir_length, 8));
+       ir_test = malloc(DIV_ROUND_UP(total_ir_length, 8));
        if (ir_test == NULL)
                return ERROR_FAIL;
 
@@ -1224,7 +1194,14 @@ static int jtag_validate_ircapture(void)
                /* If we're autoprobing, guess IR lengths.  They must be at
                 * least two bits.  Guessing will fail if (a) any TAP does
                 * not conform to the JTAG spec; or (b) when the upper bits
-                * captured from some conforming TAP are nonzero.
+                * captured from some conforming TAP are nonzero.  Or if
+                * (c) an IR length is longer than 32 bits -- which is only
+                * an implementation limit, which could someday be raised.
+                *
+                * REVISIT optimization:  if there's a *single* TAP we can
+                * lift restrictions (a) and (b) by scanning a recognizable
+                * pattern before the all-ones BYPASS.  Check for where the
+                * pattern starts in the result, instead of an 0...01 value.
                 *
                 * REVISIT alternative approach: escape to some tcl code
                 * which could provide more knowledge, based on IDCODE; and
@@ -1233,7 +1210,8 @@ static int jtag_validate_ircapture(void)
                if (tap->ir_length == 0) {
                        tap->ir_length = 2;
                        while ((val = buf_get_u32(ir_test, chain_pos,
-                                               tap->ir_length + 1)) == 1) {
+                                               tap->ir_length + 1)) == 1
+                                       && tap->ir_length <= 32) {
                                tap->ir_length++;
                        }
                        LOG_WARNING("AUTO %s - use \"... -irlen %d\"",
@@ -1293,7 +1271,7 @@ void jtag_tap_init(struct jtag_tap *tap)
 
        /* if we're autoprobing, cope with potentially huge ir_length */
        ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX;
-       ir_len_bytes = CEIL(ir_len_bits, 8);
+       ir_len_bytes = DIV_ROUND_UP(ir_len_bits, 8);
 
        tap->expected = calloc(1, ir_len_bytes);
        tap->expected_mask = calloc(1, ir_len_bytes);
@@ -1334,7 +1312,7 @@ void jtag_tap_free(struct jtag_tap *tap)
        free(tap);
 }
 
-int jtag_interface_init(struct command_context_s *cmd_ctx)
+int jtag_interface_init(struct command_context *cmd_ctx)
 {
        if (jtag)
                return ERROR_OK;
@@ -1375,7 +1353,7 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
        return ERROR_OK;
 }
 
-int jtag_init_inner(struct command_context_s *cmd_ctx)
+int jtag_init_inner(struct command_context *cmd_ctx)
 {
        struct jtag_tap *tap;
        int retval;
@@ -1461,7 +1439,7 @@ int jtag_interface_quit(void)
 }
 
 
-int jtag_init_reset(struct command_context_s *cmd_ctx)
+int jtag_init_reset(struct command_context *cmd_ctx)
 {
        int retval;
 
@@ -1515,7 +1493,7 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
        return jtag_init_inner(cmd_ctx);
 }
 
-int jtag_init(struct command_context_s *cmd_ctx)
+int jtag_init(struct command_context *cmd_ctx)
 {
        int retval;
 
@@ -1527,7 +1505,7 @@ int jtag_init(struct command_context_s *cmd_ctx)
        if ((retval = jtag_execute_queue()) != ERROR_OK)
                return retval;
 
-       if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
+       if (Jim_Eval_Named(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
                return ERROR_FAIL;
 
        return ERROR_OK;