scan_field_t -> struct scan_field
[fw/openocd] / src / jtag / core.c
index 854236f3d15346d31b5d3bba24e89c4803ff34ea..48af0406fe74aa954306014f48d7aeb17fafb211 100644 (file)
@@ -43,8 +43,8 @@
 /// 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);
+static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const struct scan_field *in_fields, tap_state_t state),
+               int in_num_fields, struct scan_field *in_fields, tap_state_t state);
 
 /**
  * The jtag_error variable is set when an error occurs while executing
@@ -68,15 +68,17 @@ static const char *jtag_event_strings[] =
 
 /*
  * JTAG adapters must initialize with TRST and SRST de-asserted
- * (they're negative logic, so that means *high*)
+ * (they're negative logic, so that means *high*).  But some
+ * hardware doesn't necessarily work that way ... so set things
+ * up so that jtag_init() always forces that state.
  */
-static int jtag_trst = 0;
-static int jtag_srst = 0;
+static int jtag_trst = -1;
+static int jtag_srst = -1;
 
 /**
  * List all TAPs that have been created.
  */
-static jtag_tap_t *__jtag_all_taps = NULL;
+static struct jtag_tap *__jtag_all_taps = NULL;
 /**
  * The number of TAPs in the __jtag_all_taps list, used to track the
  * assigned chain position to new TAPs
@@ -135,8 +137,34 @@ int jtag_error_clear(void)
        return temp;
 }
 
+/************/
 
-jtag_tap_t *jtag_all_taps(void)
+static bool jtag_poll = 1;
+
+bool is_jtag_poll_safe(void)
+{
+       /* Polling can be disabled explicitly with set_enabled(false).
+        * It is also implicitly disabled while TRST is active and
+        * while SRST is gating the JTAG clock.
+        */
+       if (!jtag_poll || jtag_trst != 0)
+               return false;
+       return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING);
+}
+
+bool jtag_poll_get_enabled(void)
+{
+       return jtag_poll;
+}
+
+void jtag_poll_set_enabled(bool value)
+{
+       jtag_poll = value;
+}
+
+/************/
+
+struct jtag_tap *jtag_all_taps(void)
 {
        return __jtag_all_taps;
 };
@@ -148,7 +176,7 @@ unsigned jtag_tap_count(void)
 
 unsigned jtag_tap_count_enabled(void)
 {
-       jtag_tap_t *t = jtag_all_taps();
+       struct jtag_tap *t = jtag_all_taps();
        unsigned n = 0;
        while (t)
        {
@@ -160,20 +188,20 @@ unsigned jtag_tap_count_enabled(void)
 }
 
 /// Append a new TAP to the chain of all taps.
-void jtag_tap_add(struct jtag_tap_s *t)
+void jtag_tap_add(struct jtag_tap *t)
 {
        t->abs_chain_position = jtag_num_taps++;
 
-       jtag_tap_t **tap = &__jtag_all_taps;
+       struct jtag_tap **tap = &__jtag_all_taps;
        while (*tap != NULL)
                tap = &(*tap)->next_tap;
        *tap = t;
 }
 
 /* returns a pointer to the n-th device in the scan chain */
-static inline jtag_tap_t *jtag_tap_by_position(unsigned n)
+static inline struct jtag_tap *jtag_tap_by_position(unsigned n)
 {
-       jtag_tap_t *t = jtag_all_taps();
+       struct jtag_tap *t = jtag_all_taps();
 
        while (t && n-- > 0)
                t = t->next_tap;
@@ -181,10 +209,10 @@ static inline jtag_tap_t *jtag_tap_by_position(unsigned n)
        return t;
 }
 
-jtag_tap_t *jtag_tap_by_string(const char *s)
+struct jtag_tap *jtag_tap_by_string(const char *s)
 {
        /* try by name first */
-       jtag_tap_t *t = jtag_all_taps();
+       struct jtag_tap *t = jtag_all_taps();
 
        while (t)
        {
@@ -210,10 +238,10 @@ jtag_tap_t *jtag_tap_by_string(const char *s)
        return t;
 }
 
-jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
+struct jtag_tap *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
 {
        const char *cp = Jim_GetString(o, NULL);
-       jtag_tap_t *t = cp ? jtag_tap_by_string(cp) : NULL;
+       struct jtag_tap *t = cp ? jtag_tap_by_string(cp) : NULL;
        if (NULL == cp)
                cp = "(unknown)";
        if (NULL == t)
@@ -221,7 +249,7 @@ jtag_tap_t *jtag_tap_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
        return t;
 }
 
-jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p)
+struct jtag_tap* jtag_tap_next_enabled(struct jtag_tap* p)
 {
        p = p ? p->next_tap : jtag_all_taps();
        while (p)
@@ -233,7 +261,7 @@ jtag_tap_t* jtag_tap_next_enabled(jtag_tap_t* p)
        return NULL;
 }
 
-const char *jtag_tap_name(const jtag_tap_t *tap)
+const char *jtag_tap_name(const struct jtag_tap *tap)
 {
        return (tap == NULL) ? "(unknown)" : tap->dotted_name;
 }
@@ -325,12 +353,12 @@ static void jtag_prelude(tap_state_t state)
        cmd_queue_cur_state = state;
 }
 
-void jtag_alloc_in_value32(scan_field_t *field)
+void jtag_alloc_in_value32(struct scan_field *field)
 {
        interface_jtag_alloc_in_value32(field);
 }
 
-void jtag_add_ir_scan_noverify(int in_count, const scan_field_t *in_fields,
+void jtag_add_ir_scan_noverify(int in_count, const struct scan_field *in_fields,
                tap_state_t state)
 {
        jtag_prelude(state);
@@ -340,7 +368,7 @@ void jtag_add_ir_scan_noverify(int in_count, const scan_field_t *in_fields,
 }
 
 
-void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t state)
+void jtag_add_ir_scan(int in_num_fields, struct scan_field *in_fields, tap_state_t state)
 {
        assert(state != TAP_RESET);
 
@@ -363,7 +391,7 @@ void jtag_add_ir_scan(int in_num_fields, scan_field_t *in_fields, tap_state_t st
        }
 }
 
-void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields,
+void jtag_add_plain_ir_scan(int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -395,12 +423,12 @@ static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callb
        return jtag_check_value_inner((uint8_t *)data0, (uint8_t *)data1, (uint8_t *)data2, (int)data3);
 }
 
-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)
+static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const struct scan_field *in_fields, tap_state_t state),
+               int in_num_fields, struct scan_field *in_fields, tap_state_t state)
 {
        for (int i = 0; i < in_num_fields; i++)
        {
-               struct scan_field_s *field = &in_fields[i];
+               struct scan_field *field = &in_fields[i];
                field->allocated = 0;
                field->modified = 0;
                if (field->check_value || field->in_value)
@@ -432,7 +460,7 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
        }
 }
 
-void jtag_add_dr_scan_check(int in_num_fields, scan_field_t *in_fields, tap_state_t state)
+void jtag_add_dr_scan_check(int in_num_fields, struct scan_field *in_fields, tap_state_t state)
 {
        if (jtag_verify)
        {
@@ -444,7 +472,7 @@ void jtag_add_dr_scan_check(int in_num_fields, scan_field_t *in_fields, tap_stat
 }
 
 
-void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields,
+void jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -456,7 +484,7 @@ void jtag_add_dr_scan(int in_num_fields, const scan_field_t *in_fields,
        jtag_set_error(retval);
 }
 
-void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields,
+void jtag_add_plain_dr_scan(int in_num_fields, const struct scan_field *in_fields,
                tap_state_t state)
 {
        assert(state != TAP_RESET);
@@ -468,7 +496,7 @@ void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields,
        jtag_set_error(retval);
 }
 
-void jtag_add_dr_out(jtag_tap_t* tap,
+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)
 {
@@ -539,12 +567,14 @@ int jtag_add_statemove(tap_state_t goal_state)
                tap_state_name(goal_state));
 
 
-       if (goal_state == cur_state)
-               ;       /* nothing to do */
-       else if (goal_state == TAP_RESET)
-       {
+       /* If goal is RESET, be paranoid and force that that transition
+        * (e.g. five TCK cycles, TMS high).  Else trust "cur_state".
+        */
+       if (goal_state == TAP_RESET)
                jtag_add_tlr();
-       }
+       else if (goal_state == cur_state)
+               /* nothing to do */ ;
+
        else if (tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state))
        {
                unsigned tms_bits  = tap_get_tms_path(cur_state, goal_state);
@@ -776,7 +806,7 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
        return retval;
 }
 
-void jtag_check_value_mask(scan_field_t *field, uint8_t *value, uint8_t *mask)
+void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask)
 {
        assert(field->in_value != NULL);
 
@@ -826,7 +856,7 @@ int jtag_execute_queue(void)
 
 static int jtag_reset_callback(enum jtag_event event, void *priv)
 {
-       jtag_tap_t *tap = priv;
+       struct jtag_tap *tap = priv;
 
        if (event == JTAG_TRST_ASSERTED)
        {
@@ -860,9 +890,12 @@ void jtag_sleep(uint32_t us)
  */
 #define END_OF_CHAIN_FLAG      0x000000ff
 
+/* a larger IR length than we ever expect to autoprobe */
+#define JTAG_IRLEN_MAX         60
+
 static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
 {
-       scan_field_t field = {
+       struct scan_field field = {
                        .tap = NULL,
                        .num_bits = num_idcode * 32,
                        .out_value = idcode_buffer,
@@ -890,7 +923,15 @@ static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count)
        }
 
        /* if there wasn't a single non-zero bit or if all bits were one,
-        * the scan is not valid */
+        * the scan is not valid.  We wrote a mix of both values; either
+        *
+        *  - There's a hardware issue (almost certainly):
+        *     + all-zeroes can mean a target stuck in JTAG reset
+        *     + all-ones tends to mean no target
+        *  - The scan chain is WAY longer than we can handle, *AND* either
+        *     + there are several hundreds of TAPs in bypass, or
+        *     + at least a few dozen TAPs all have an all-ones IDCODE
+        */
        if (zero_check == 0x00 || one_check == 0xff)
        {
                LOG_ERROR("JTAG scan chain interrogation failed: all %s",
@@ -937,8 +978,9 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
        for (; count < max - 31; count += 32)
        {
                uint32_t idcode = buf_get_u32(idcodes, count, 32);
-               // do not trigger the warning if the data looks good
-               if (!triggered && jtag_idcode_is_final(idcode))
+
+               /* do not trigger the warning if the data looks good */
+               if (jtag_idcode_is_final(idcode))
                        continue;
                LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
                                        count, (unsigned int)idcode);
@@ -947,15 +989,16 @@ static bool jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned ma
        return triggered;
 }
 
-static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
+static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
 {
        /* ignore expected BYPASS codes; warn otherwise */
        if (0 == tap->expected_ids_cnt && !tap->idcode)
                return true;
 
        /* Loop over the expected identification codes and test for a match */
-       uint8_t ii;
-       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       unsigned ii, limit = tap->expected_ids_cnt;
+
+       for (ii = 0; ii < limit; ii++)
        {
                if (tap->idcode == tap->expected_ids[ii])
                        return true;
@@ -968,11 +1011,11 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
        /* If none of the expected ids matched, warn */
        jtag_examine_chain_display(LOG_LVL_WARNING, "UNEXPECTED",
                        tap->dotted_name, tap->idcode);
-       for (ii = 0; ii < tap->expected_ids_cnt; ii++)
+       for (ii = 0; ii < limit; ii++)
        {
                char msg[32];
-               snprintf(msg, sizeof(msg), "expected %hhu of %hhu",
-                               ii + 1, tap->expected_ids_cnt);
+
+               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit);
                jtag_examine_chain_display(LOG_LVL_ERROR, msg,
                                tap->dotted_name, tap->expected_ids[ii]);
        }
@@ -986,21 +1029,25 @@ static int jtag_examine_chain(void)
 {
        uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
        unsigned bit_count;
+       int retval;
+       int tapcount = 0;
+       bool autoprobe = false;
 
        /* DR scan to collect BYPASS or IDCODE register contents.
         * Then make sure the scan data has both ones and zeroes.
         */
-       jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+       LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS");
+       retval = jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+       if (retval != ERROR_OK)
+               return retval;
        if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
                return ERROR_JTAG_INIT_FAILED;
 
        /* point at the 1st tap */
-       jtag_tap_t *tap = jtag_tap_next_enabled(NULL);
-       if (tap == NULL)
-       {
-               LOG_ERROR("JTAG: No taps enabled?");
-               return ERROR_JTAG_INIT_FAILED;
-       }
+       struct jtag_tap *tap = jtag_tap_next_enabled(NULL);
+
+       if (!tap)
+               autoprobe = true;
 
        for (bit_count = 0;
                        tap && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;
@@ -1010,7 +1057,7 @@ static int jtag_examine_chain(void)
 
                if ((idcode & 1) == 0)
                {
-                       /* LSB must not be 0, this indicates a device in bypass */
+                       /* Zero for LSB indicates a device in bypass */
                        LOG_WARNING("TAP %s does not have IDCODE",
                                        tap->dotted_name);
                        idcode = 0;
@@ -1022,7 +1069,8 @@ static int jtag_examine_chain(void)
                {
                        /* Friendly devices support IDCODE */
                        tap->hasidcode = true;
-                       jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found",
+                       jtag_examine_chain_display(LOG_LVL_INFO,
+                                       "tap/device found",
                                        tap->dotted_name, idcode);
 
                        bit_count += 32;
@@ -1031,7 +1079,7 @@ static int jtag_examine_chain(void)
 
                /* ensure the TAP ID matches what was expected */
                if (!jtag_examine_chain_match_tap(tap))
-                       return ERROR_JTAG_INIT_FAILED;
+                       retval = ERROR_JTAG_INIT_SOFT_FAIL;
        }
 
        /* Fail if too many TAPs were enabled for us to verify them all. */
@@ -1041,17 +1089,73 @@ static int jtag_examine_chain(void)
                return ERROR_JTAG_INIT_FAILED;
        }
 
+       /* if autoprobing, the tap list is still empty ... populate it! */
+       while (autoprobe && bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31) {
+               uint32_t idcode;
+               char buf[12];
+
+               /* Is there another TAP? */
+               idcode = buf_get_u32(idcode_buffer, bit_count, 32);
+               if (jtag_idcode_is_final(idcode))
+                       break;
+
+               /* Default everything in this TAP except IR length.
+                *
+                * REVISIT create a jtag_alloc(chip, tap) routine, and
+                * share it with jim_newtap_cmd().
+                */
+               tap = calloc(1, sizeof *tap);
+               if (!tap)
+                       return ERROR_FAIL;
+
+               sprintf(buf, "auto%d", tapcount++);
+               tap->chip = strdup(buf);
+               tap->tapname = strdup("tap");
+
+               sprintf(buf, "%s.%s", tap->chip, tap->tapname);
+               tap->dotted_name = strdup(buf);
+
+               /* tap->ir_length == 0 ... signifying irlen autoprobe */
+               tap->ir_capture_mask = 0x03;
+               tap->ir_capture_value = 0x01;
+
+               tap->enabled = true;
+
+               if ((idcode & 1) == 0) {
+                       bit_count += 1;
+                       tap->hasidcode = false;
+               } else {
+                       bit_count += 32;
+                       tap->hasidcode = true;
+                       tap->idcode = idcode;
+
+                       tap->expected_ids_cnt = 1;
+                       tap->expected_ids = malloc(sizeof(uint32_t));
+                       tap->expected_ids[0] = idcode;
+               }
+
+               LOG_WARNING("AUTO %s - use \"jtag newtap "
+                               "%s %s -expected-id 0x%8.8" PRIx32 " ...\"",
+                               tap->dotted_name, tap->chip, tap->tapname,
+                               tap->idcode);
+
+               jtag_tap_init(tap);
+       }
+
        /* After those IDCODE or BYPASS register values should be
         * only the data we fed into the scan chain.
         */
        if (jtag_examine_chain_end(idcode_buffer, bit_count,
                        8 * sizeof(idcode_buffer))) {
                LOG_ERROR("double-check your JTAG setup (interface, "
-                               "speed, TAPs, ...)");
+                               "speed, missing TAPs, ...)");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       return ERROR_OK;
+       /* Return success or, for backwards compatibility if only
+        * some IDCODE values mismatched, a soft/continuable fault.
+        */
+       return retval;
 }
 
 /*
@@ -1064,18 +1168,21 @@ static int jtag_examine_chain(void)
  */
 static int jtag_validate_ircapture(void)
 {
-       jtag_tap_t *tap;
+       struct jtag_tap *tap;
        int total_ir_length = 0;
        uint8_t *ir_test = NULL;
-       scan_field_t field;
+       struct scan_field field;
        int val;
        int chain_pos = 0;
        int retval;
 
+       /* when autoprobing, accomodate huge IR lengths */
        for (tap = NULL, total_ir_length = 0;
                        (tap = jtag_tap_next_enabled(tap)) != NULL;
-                       total_ir_length += tap->ir_length)
-               continue;
+                       total_ir_length += tap->ir_length) {
+               if (tap->ir_length == 0)
+                       total_ir_length += JTAG_IRLEN_MAX;
+       }
 
        /* increase length to add 2 bit sentinel after scan */
        total_ir_length += 2;
@@ -1108,16 +1215,40 @@ static int jtag_validate_ircapture(void)
                        break;
                }
 
+               /* 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.
+                *
+                * REVISIT alternative approach: escape to some tcl code
+                * which could provide more knowledge, based on IDCODE; and
+                * only guess when that has no success.
+                */
+               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++;
+                       }
+                       LOG_WARNING("AUTO %s - use \"... -irlen %d\"",
+                                       jtag_tap_name(tap), tap->ir_length);
+               }
+
                /* Validate the two LSBs, which must be 01 per JTAG spec.
-                * REVISIT we might be able to verify some MSBs too, using
-                * ircapture/irmask attributes.
+                *
+                * Or ... more bits could be provided by TAP declaration.
+                * Plus, some taps (notably in i.MX series chips) violate
+                * this part of the JTAG spec, so their capture mask/value
+                * attributes might disable this test.
                 */
                val = buf_get_u32(ir_test, chain_pos, tap->ir_length);
-               if ((val & 0x3) != 1) {
-                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x..1",
+               if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
+                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x",
                                        jtag_tap_name(tap),
                                        (tap->ir_length + 7) / tap->ir_length,
-                                       val);
+                                       val,
+                                       (tap->ir_length + 7) / tap->ir_length,
+                                       (unsigned) tap->ir_capture_value);
 
                        retval = ERROR_JTAG_INIT_FAILED;
                        goto done;
@@ -1149,22 +1280,30 @@ done:
 }
 
 
-void jtag_tap_init(jtag_tap_t *tap)
+void jtag_tap_init(struct jtag_tap *tap)
 {
-       assert(0 != tap->ir_length);
+       unsigned ir_len_bits;
+       unsigned ir_len_bytes;
 
-       /// @todo fix, this allocates one byte per bit for all three fields!
-       tap->expected = malloc(tap->ir_length);
-       tap->expected_mask = malloc(tap->ir_length);
-       tap->cur_instr = malloc(tap->ir_length);
+       /* 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);
 
-       /// @todo cope sanely with ir_length bigger than 32 bits
-       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);
+       tap->expected = calloc(1, ir_len_bytes);
+       tap->expected_mask = calloc(1, ir_len_bytes);
+       tap->cur_instr = malloc(ir_len_bytes);
+
+       /// @todo cope better with ir_length bigger than 32 bits
+       if (ir_len_bits > 32)
+               ir_len_bits = 32;
 
-       // place TAP in bypass mode
+       buf_set_u32(tap->expected, 0, ir_len_bits, tap->ir_capture_value);
+       buf_set_u32(tap->expected_mask, 0, ir_len_bits, tap->ir_capture_mask);
+
+       // TAP will be in bypass mode after jtag_validate_ircapture()
        tap->bypass = 1;
+       buf_set_ones(tap->cur_instr, tap->ir_length);
+
        // register the reset callback for the TAP
        jtag_register_event_callback(&jtag_reset_callback, tap);
 
@@ -1176,7 +1315,7 @@ void jtag_tap_init(jtag_tap_t *tap)
        jtag_tap_add(tap);
 }
 
-void jtag_tap_free(jtag_tap_t *tap)
+void jtag_tap_free(struct jtag_tap *tap)
 {
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
@@ -1232,7 +1371,7 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
 
 int jtag_init_inner(struct command_context_s *cmd_ctx)
 {
-       jtag_tap_t *tap;
+       struct jtag_tap *tap;
        int retval;
        bool issue_setup = true;
 
@@ -1240,26 +1379,58 @@ int jtag_init_inner(struct command_context_s *cmd_ctx)
 
        tap = jtag_tap_next_enabled(NULL);
        if (tap == NULL) {
-               LOG_ERROR("There are no enabled taps?");
-               return ERROR_JTAG_INIT_FAILED;
+               /* Once JTAG itself is properly set up, and the scan chain
+                * isn't absurdly large, IDCODE autoprobe should work fine.
+                *
+                * But ... IRLEN autoprobe can fail even on systems which
+                * are fully conformant to JTAG.  Also, JTAG setup can be
+                * quite finicky on some systems.
+                *
+                * REVISIT: if TAP autoprobe works OK, then in many cases
+                * we could escape to tcl code and set up targets based on
+                * the TAP's IDCODE values.
+                */
+               LOG_WARNING("There are no enabled taps.  "
+                               "AUTO PROBING MIGHT NOT WORK!!");
+
+               /* REVISIT default clock will often be too fast ... */
        }
 
        jtag_add_tlr();
        if ((retval = jtag_execute_queue()) != ERROR_OK)
                return retval;
 
-       /* examine chain first, as this could discover the real chain layout */
-       if (jtag_examine_chain() != ERROR_OK)
-       {
+       /* Examine DR values first.  This discovers problems which will
+        * prevent communication ... hardware issues like TDO stuck, or
+        * configuring the wrong number of (enabled) TAPs.
+        */
+       retval = jtag_examine_chain();
+       switch (retval) {
+       case ERROR_OK:
+               /* complete success */
+               break;
+       case ERROR_JTAG_INIT_SOFT_FAIL:
+               /* For backward compatibility reasons, try coping with
+                * configuration errors involving only ID mismatches.
+                * We might be able to talk to the devices.
+                */
                LOG_ERROR("Trying to use configured scan chain anyway...");
                issue_setup = false;
+               break;
+       default:
+               /* some hard error; already issued diagnostics */
+               return retval;
        }
 
-       if (jtag_validate_ircapture() != ERROR_OK)
-       {
-               LOG_WARNING("Errors during IR capture, continuing anyway...");
-               issue_setup = false;
-       }
+       /* Now look at IR values.  Problems here will prevent real
+        * communication.  They mostly mean that the IR length is
+        * wrong ... or that the IR capture value is wrong.  (The
+        * latter is uncommon, but easily worked around:  provide
+        * ircapture/irmask values during TAP setup.)
+        */
+       retval = jtag_validate_ircapture();
+       if (retval != ERROR_OK)
+               return retval;
 
        if (issue_setup)
                jtag_notify_event(JTAG_TAP_EVENT_SETUP);
@@ -1291,22 +1462,31 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
        if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
-       LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / TLR");
+       LOG_DEBUG("Initializing with hard TRST+SRST reset");
 
-       /* Reset can happen after a power cycle.
-        *
-        * Ideally we would only assert TRST or run TLR before the target reset.
+       /*
+        * This procedure is used by default when OpenOCD triggers a reset.
+        * It's now done through an overridable Tcl "init_reset" wrapper.
         *
-        * However w/srst_pulls_trst, trst is asserted together with the target
-        * reset whether we want it or not.
+        * This started out as a more powerful "get JTAG working" reset than
+        * jtag_init_inner(), applying TRST because some chips won't activate
+        * JTAG without a TRST cycle (presumed to be async, though some of
+        * those chips synchronize JTAG activation using TCK).
         *
-        * NB! Some targets have JTAG circuitry disabled until a
-        * trst & srst has been asserted.
+        * But some chips only activate JTAG as part of an SRST cycle; SRST
+        * got mixed in.  So it became a hard reset routine, which got used
+        * in more places, and which coped with JTAG reset being forced as
+        * part of SRST (srst_pulls_trst).
         *
-        * NB! here we assume nsrst/ntrst delay are sufficient!
+        * And even more corner cases started to surface:  TRST and/or SRST
+        * assertion timings matter; some chips need other JTAG operations;
+        * TRST/SRST sequences can need to be different from these, etc.
         *
-        * NB! order matters!!!! srst *can* disconnect JTAG circuitry
+        * Systems should override that wrapper to support system-specific
+        * requirements that this not-fully-generic code doesn't handle.
         *
+        * REVISIT once Tcl code can read the reset_config modes, this won't
+        * need to be a C routine at all...
         */
        jtag_add_reset(1, 0); /* TAP_RESET, using TMS+TCK or TRST */
        if (jtag_reset_config & RESET_HAS_SRST)
@@ -1332,9 +1512,15 @@ int jtag_init_reset(struct command_context_s *cmd_ctx)
 int jtag_init(struct command_context_s *cmd_ctx)
 {
        int retval;
+
        if ((retval = jtag_interface_init(cmd_ctx)) != ERROR_OK)
                return retval;
 
+       /* guard against oddball hardware: force resets to be inactive */
+       jtag_add_reset(0, 0);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+
        if (Jim_Eval_Named(interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
                return ERROR_FAIL;
 
@@ -1383,13 +1569,6 @@ static int jtag_set_speed(int speed)
        return jtag ? jtag->speed(speed) : ERROR_OK;
 }
 
-int jtag_config_speed(int speed)
-{
-       LOG_DEBUG("handle jtag speed");
-       clock_mode = CLOCK_MODE_SPEED;
-       return jtag_set_speed(speed);
-}
-
 int jtag_config_khz(unsigned khz)
 {
        LOG_DEBUG("handle jtag khz");