jtag/core: get rid of variable 'jtag'
[openocd.git] / src / jtag / core.c
index 2f7effe377b690e8b3158706061f9200b2c16581..f0c000a2418657ad9bbf80fc208d745f96567158 100644 (file)
@@ -23,9 +23,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -36,6 +34,8 @@
 #include "swd.h"
 #include "interface.h"
 #include <transport/transport.h>
+#include <helper/jep106.h>
+#include "helper/system.h"
 
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
@@ -45,6 +45,9 @@
 #include "svf/svf.h"
 #include "xsvf/xsvf.h"
 
+/* ipdbg are utilities to debug IP-cores. It uses JTAG for transport. */
+#include "server/ipdbg.h"
+
 /** The number of JTAG queue flushes (for profiling and debugging purposes). */
 static int jtag_flush_queue_count;
 
@@ -90,11 +93,6 @@ static int jtag_srst = -1;
  * List all TAPs that have been created.
  */
 static struct jtag_tap *__jtag_all_taps;
-/**
- * The number of TAPs in the __jtag_all_taps list, used to track the
- * assigned chain position to new TAPs
- */
-static unsigned jtag_num_taps;
 
 static enum reset_types jtag_reset_config = RESET_NONE;
 tap_state_t cmd_queue_cur_state = TAP_RESET;
@@ -130,14 +128,15 @@ static int speed_khz;
 /* speed to fallback to when RCLK is requested but not supported */
 static int rclk_fallback_speed_khz;
 static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
-static int jtag_speed;
 
-static struct jtag_interface *jtag;
+extern struct adapter_driver *adapter_driver;
 
-const struct swd_driver *swd;
+static bool adapter_initialized;
 
-/* configuration */
-struct jtag_interface *jtag_interface;
+static bool is_adapter_initialized(void)
+{
+       return adapter_initialized;
+}
 
 void jtag_set_flush_queue_sleep(int ms)
 {
@@ -168,6 +167,9 @@ bool is_jtag_poll_safe(void)
         * It is also implicitly disabled while TRST is active and
         * while SRST is gating the JTAG clock.
         */
+       if (!transport_is_jtag())
+               return jtag_poll;
+
        if (!jtag_poll || jtag_trst != 0)
                return false;
        return jtag_srst == 0 || (jtag_reset_config & RESET_SRST_NO_GATING);
@@ -192,7 +194,13 @@ struct jtag_tap *jtag_all_taps(void)
 
 unsigned jtag_tap_count(void)
 {
-       return jtag_num_taps;
+       struct jtag_tap *t = jtag_all_taps();
+       unsigned n = 0;
+       while (t) {
+               n++;
+               t = t->next_tap;
+       }
+       return n;
 }
 
 unsigned jtag_tap_count_enabled(void)
@@ -208,14 +216,17 @@ unsigned jtag_tap_count_enabled(void)
 }
 
 /** Append a new TAP to the chain of all taps. */
-void jtag_tap_add(struct jtag_tap *t)
+static void jtag_tap_add(struct jtag_tap *t)
 {
-       t->abs_chain_position = jtag_num_taps++;
+       unsigned jtag_num_taps = 0;
 
        struct jtag_tap **tap = &__jtag_all_taps;
-       while (*tap != NULL)
+       while (*tap) {
+               jtag_num_taps++;
                tap = &(*tap)->next_tap;
+       }
        *tap = t;
+       t->abs_chain_position = jtag_num_taps;
 }
 
 /* returns a pointer to the n-th device in the scan chain */
@@ -235,7 +246,7 @@ struct jtag_tap *jtag_tap_by_string(const char *s)
        struct jtag_tap *t = jtag_all_taps();
 
        while (t) {
-               if (0 == strcmp(t->dotted_name, s))
+               if (strcmp(t->dotted_name, s) == 0)
                        return t;
                t = t->next_tap;
        }
@@ -270,7 +281,7 @@ struct jtag_tap *jtag_tap_next_enabled(struct jtag_tap *p)
 
 const char *jtag_tap_name(const struct jtag_tap *tap)
 {
-       return (tap == NULL) ? "(unknown)" : tap->dotted_name;
+       return (!tap) ? "(unknown)" : tap->dotted_name;
 }
 
 
@@ -278,7 +289,7 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv)
 {
        struct jtag_event_callback **callbacks_p = &jtag_event_callbacks;
 
-       if (callback == NULL)
+       if (!callback)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        if (*callbacks_p) {
@@ -299,7 +310,7 @@ int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv)
 {
        struct jtag_event_callback **p = &jtag_event_callbacks, *temp;
 
-       if (callback == NULL)
+       if (!callback)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        while (*p) {
@@ -387,7 +398,7 @@ void jtag_add_ir_scan(struct jtag_tap *active, struct scan_field *in_fields, tap
 void jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
        tap_state_t state)
 {
-       assert(out_bits != NULL);
+       assert(out_bits);
        assert(state != TAP_RESET);
 
        jtag_prelude(state);
@@ -421,8 +432,7 @@ static void jtag_add_scan_check(struct jtag_tap *active, void (*jtag_add_scan)(
        jtag_add_scan(active, in_num_fields, in_fields, state);
 
        for (int i = 0; i < in_num_fields; i++) {
-               if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL)) {
-                       /* this is synchronous for a minidriver */
+               if ((in_fields[i].check_value) && (in_fields[i].in_value)) {
                        jtag_add_callback4(jtag_check_value_mask_callback,
                                (jtag_callback_data_t)in_fields[i].in_value,
                                (jtag_callback_data_t)in_fields[i].check_value,
@@ -461,7 +471,7 @@ void jtag_add_dr_scan(struct jtag_tap *active,
 void jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits,
        tap_state_t state)
 {
-       assert(out_bits != NULL);
+       assert(out_bits);
        assert(state != TAP_RESET);
 
        jtag_prelude(state);
@@ -483,7 +493,7 @@ void jtag_add_tlr(void)
 
 /**
  * If supported by the underlying adapter, this clocks a raw bit sequence
- * onto TMS for switching betwen JTAG and SWD modes.
+ * onto TMS for switching between JTAG and SWD modes.
  *
  * DO NOT use this to bypass the integrity checks and logging provided
  * by the jtag_add_pathmove() and jtag_add_statemove() calls.
@@ -499,7 +509,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
 {
        int retval;
 
-       if (!(jtag->supported & DEBUG_CAP_TMS_SEQ))
+       if (!(adapter_driver->jtag_ops->supported & DEBUG_CAP_TMS_SEQ))
                return ERROR_JTAG_NOT_IMPLEMENTED;
 
        jtag_checks();
@@ -607,22 +617,91 @@ void jtag_add_clocks(int num_cycles)
        }
 }
 
-void swd_add_reset(int req_srst)
+static int adapter_system_reset(int req_srst)
 {
+       int retval;
+
        if (req_srst) {
                if (!(jtag_reset_config & RESET_HAS_SRST)) {
                        LOG_ERROR("BUG: can't assert SRST");
-                       jtag_set_error(ERROR_FAIL);
-                       return;
+                       return ERROR_FAIL;
                }
                req_srst = 1;
        }
 
        /* Maybe change SRST signal state */
        if (jtag_srst != req_srst) {
+               retval = adapter_driver->reset(0, req_srst);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("SRST error");
+                       return ERROR_FAIL;
+               }
+               jtag_srst = req_srst;
+
+               if (req_srst) {
+                       LOG_DEBUG("SRST line asserted");
+                       if (adapter_nsrst_assert_width)
+                               jtag_sleep(adapter_nsrst_assert_width * 1000);
+               } else {
+                       LOG_DEBUG("SRST line released");
+                       if (adapter_nsrst_delay)
+                               jtag_sleep(adapter_nsrst_delay * 1000);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static void legacy_jtag_add_reset(int req_tlr_or_trst, int req_srst)
+{
+       int trst_with_tlr = 0;
+       int new_srst = 0;
+       int new_trst = 0;
+
+       /* Without SRST, we must use target-specific JTAG operations
+        * on each target; callers should not be requesting SRST when
+        * that signal doesn't exist.
+        *
+        * RESET_SRST_PULLS_TRST is a board or chip level quirk, which
+        * can kick in even if the JTAG adapter can't drive TRST.
+        */
+       if (req_srst) {
+               if (!(jtag_reset_config & RESET_HAS_SRST)) {
+                       LOG_ERROR("BUG: can't assert SRST");
+                       jtag_set_error(ERROR_FAIL);
+                       return;
+               }
+               if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0
+                               && !req_tlr_or_trst) {
+                       LOG_ERROR("BUG: can't assert only SRST");
+                       jtag_set_error(ERROR_FAIL);
+                       return;
+               }
+               new_srst = 1;
+       }
+
+       /* JTAG reset (entry to TAP_RESET state) can always be achieved
+        * using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE
+        * state first.  TRST accelerates it, and bypasses those states.
+        *
+        * RESET_TRST_PULLS_SRST is a board or chip level quirk, which
+        * can kick in even if the JTAG adapter can't drive SRST.
+        */
+       if (req_tlr_or_trst) {
+               if (!(jtag_reset_config & RESET_HAS_TRST))
+                       trst_with_tlr = 1;
+               else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0
+                        && !req_srst)
+                       trst_with_tlr = 1;
+               else
+                       new_trst = 1;
+       }
+
+       /* Maybe change TRST and/or SRST signal state */
+       if (jtag_srst != new_srst || jtag_trst != new_trst) {
                int retval;
 
-               retval = interface_jtag_add_reset(0, req_srst);
+               retval = interface_jtag_add_reset(new_trst, new_srst);
                if (retval != ERROR_OK)
                        jtag_set_error(retval);
                else
@@ -632,9 +711,11 @@ void swd_add_reset(int req_srst)
                        LOG_ERROR("TRST/SRST error");
                        return;
                }
+       }
 
-               /* SRST resets everything hooked up to that signal */
-               jtag_srst = req_srst;
+       /* SRST resets everything hooked up to that signal */
+       if (jtag_srst != new_srst) {
+               jtag_srst = new_srst;
                if (jtag_srst) {
                        LOG_DEBUG("SRST line asserted");
                        if (adapter_nsrst_assert_width)
@@ -645,14 +726,53 @@ void swd_add_reset(int req_srst)
                                jtag_add_sleep(adapter_nsrst_delay * 1000);
                }
        }
+
+       /* Maybe enter the JTAG TAP_RESET state ...
+        *  - using only TMS, TCK, and the JTAG state machine
+        *  - or else more directly, using TRST
+        *
+        * TAP_RESET should be invisible to non-debug parts of the system.
+        */
+       if (trst_with_tlr) {
+               LOG_DEBUG("JTAG reset with TLR instead of TRST");
+               jtag_add_tlr();
+
+       } else if (jtag_trst != new_trst) {
+               jtag_trst = new_trst;
+               if (jtag_trst) {
+                       LOG_DEBUG("TRST line asserted");
+                       tap_set_state(TAP_RESET);
+                       if (jtag_ntrst_assert_width)
+                               jtag_add_sleep(jtag_ntrst_assert_width * 1000);
+               } else {
+                       LOG_DEBUG("TRST line released");
+                       if (jtag_ntrst_delay)
+                               jtag_add_sleep(jtag_ntrst_delay * 1000);
+
+                       /* We just asserted nTRST, so we're now in TAP_RESET.
+                        * Inform possible listeners about this, now that
+                        * JTAG instructions and data can be shifted.  This
+                        * sequence must match jtag_add_tlr().
+                        */
+                       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+                       jtag_notify_event(JTAG_TRST_ASSERTED);
+               }
+       }
 }
 
+/* FIXME: name is misleading; we do not plan to "add" reset into jtag queue */
 void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 {
+       int retval;
        int trst_with_tlr = 0;
        int new_srst = 0;
        int new_trst = 0;
 
+       if (!adapter_driver->reset) {
+               legacy_jtag_add_reset(req_tlr_or_trst, req_srst);
+               return;
+       }
+
        /* Without SRST, we must use target-specific JTAG operations
         * on each target; callers should not be requesting SRST when
         * that signal doesn't exist.
@@ -694,15 +814,12 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
 
        /* Maybe change TRST and/or SRST signal state */
        if (jtag_srst != new_srst || jtag_trst != new_trst) {
-               int retval;
-
-               retval = interface_jtag_add_reset(new_trst, new_srst);
-               if (retval != ERROR_OK)
-                       jtag_set_error(retval);
-               else
-                       retval = jtag_execute_queue();
+               /* guarantee jtag queue empty before changing reset status */
+               jtag_execute_queue();
 
+               retval = adapter_driver->reset(new_trst, new_srst);
                if (retval != ERROR_OK) {
+                       jtag_set_error(retval);
                        LOG_ERROR("TRST/SRST error");
                        return;
                }
@@ -731,6 +848,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (trst_with_tlr) {
                LOG_DEBUG("JTAG reset with TLR instead of TRST");
                jtag_add_tlr();
+               jtag_execute_queue();
 
        } else if (jtag_trst != new_trst) {
                jtag_trst = new_trst;
@@ -779,8 +897,8 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
 
                /* NOTE:  we've lost diagnostic context here -- 'which tap' */
 
-               captured_str = buf_to_str(captured, bits, 16);
-               in_check_value_str = buf_to_str(in_check_value, bits, 16);
+               captured_str = buf_to_hex_str(captured, bits);
+               in_check_value_str = buf_to_hex_str(in_check_value, bits);
 
                LOG_WARNING("Bad value '%s' captured during DR or IR scan:",
                        captured_str);
@@ -792,7 +910,7 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
                if (in_check_mask) {
                        char *in_check_mask_str;
 
-                       in_check_mask_str = buf_to_str(in_check_mask, bits, 16);
+                       in_check_mask_str = buf_to_hex_str(in_check_mask, bits);
                        LOG_WARNING(" check_mask: 0x%s", in_check_mask_str);
                        free(in_check_mask_str);
                }
@@ -804,9 +922,9 @@ static int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value,
 
 void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *mask)
 {
-       assert(field->in_value != NULL);
+       assert(field->in_value);
 
-       if (value == NULL) {
+       if (!value) {
                /* no checking to do */
                return;
        }
@@ -819,14 +937,88 @@ void jtag_check_value_mask(struct scan_field *field, uint8_t *value, uint8_t *ma
 
 int default_interface_jtag_execute_queue(void)
 {
-       if (NULL == jtag) {
+       if (!is_adapter_initialized()) {
                LOG_ERROR("No JTAG interface configured yet.  "
                        "Issue 'init' command in startup scripts "
                        "before communicating with targets.");
                return ERROR_FAIL;
        }
 
-       return jtag->execute_queue();
+       if (!transport_is_jtag()) {
+               /*
+                * FIXME: This should not happen!
+                * There could be old code that queues jtag commands with non jtag interfaces so, for
+                * the moment simply highlight it by log an error and return on empty execute_queue.
+                * We should fix it quitting with assert(0) because it is an internal error.
+                * The fix can be applied immediately after next release (v0.11.0 ?)
+                */
+               LOG_ERROR("JTAG API jtag_execute_queue() called on non JTAG interface");
+               if (!adapter_driver->jtag_ops || !adapter_driver->jtag_ops->execute_queue)
+                       return ERROR_OK;
+       }
+
+       int result = adapter_driver->jtag_ops->execute_queue();
+
+       struct jtag_command *cmd = jtag_command_queue;
+       while (debug_level >= LOG_LVL_DEBUG_IO && cmd) {
+               switch (cmd->type) {
+                       case JTAG_SCAN:
+                               LOG_DEBUG_IO("JTAG %s SCAN to %s",
+                                               cmd->cmd.scan->ir_scan ? "IR" : "DR",
+                                               tap_state_name(cmd->cmd.scan->end_state));
+                               for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
+                                       struct scan_field *field = cmd->cmd.scan->fields + i;
+                                       if (field->out_value) {
+                                               char *str = buf_to_hex_str(field->out_value, field->num_bits);
+                                               LOG_DEBUG_IO("  %db out: %s", field->num_bits, str);
+                                               free(str);
+                                       }
+                                       if (field->in_value) {
+                                               char *str = buf_to_hex_str(field->in_value, field->num_bits);
+                                               LOG_DEBUG_IO("  %db  in: %s", field->num_bits, str);
+                                               free(str);
+                                       }
+                               }
+                               break;
+                       case JTAG_TLR_RESET:
+                               LOG_DEBUG_IO("JTAG TLR RESET to %s",
+                                               tap_state_name(cmd->cmd.statemove->end_state));
+                               break;
+                       case JTAG_RUNTEST:
+                               LOG_DEBUG_IO("JTAG RUNTEST %d cycles to %s",
+                                               cmd->cmd.runtest->num_cycles,
+                                               tap_state_name(cmd->cmd.runtest->end_state));
+                               break;
+                       case JTAG_RESET:
+                               {
+                                       const char *reset_str[3] = {
+                                               "leave", "deassert", "assert"
+                                       };
+                                       LOG_DEBUG_IO("JTAG RESET %s TRST, %s SRST",
+                                                       reset_str[cmd->cmd.reset->trst + 1],
+                                                       reset_str[cmd->cmd.reset->srst + 1]);
+                               }
+                               break;
+                       case JTAG_PATHMOVE:
+                               LOG_DEBUG_IO("JTAG PATHMOVE (TODO)");
+                               break;
+                       case JTAG_SLEEP:
+                               LOG_DEBUG_IO("JTAG SLEEP (TODO)");
+                               break;
+                       case JTAG_STABLECLOCKS:
+                               LOG_DEBUG_IO("JTAG STABLECLOCKS (TODO)");
+                               break;
+                       case JTAG_TMS:
+                               LOG_DEBUG_IO("JTAG TMS (TODO)");
+                               break;
+                       default:
+                               LOG_ERROR("Unknown JTAG command: %d", cmd->type);
+                               break;
+               }
+               cmd = cmd->next;
+       }
+
+       return result;
 }
 
 void jtag_execute_queue_noclear(void)
@@ -881,11 +1073,7 @@ void jtag_sleep(uint32_t us)
                alive_sleep((us+999)/1000);
 }
 
-/* Maximum number of enabled JTAG devices we expect in the scan chain,
- * plus one (to detect garbage at the end).  Devices that don't support
- * IDCODE take up fewer bits, possibly allowing a few more devices.
- */
-#define JTAG_MAX_CHAIN_SIZE 20
+#define JTAG_MAX_AUTO_TAPS 20
 
 #define EXTRACT_MFG(X)  (((X) & 0xffe) >> 1)
 #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
@@ -908,7 +1096,7 @@ static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcod
        };
 
        /* initialize to the end of chain ID value */
-       for (unsigned i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+       for (unsigned i = 0; i < num_idcode; i++)
                buf_set_u32(idcode_buffer, i * 32, 32, END_OF_CHAIN_FLAG);
 
        jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, TAP_DRPAUSE);
@@ -950,10 +1138,11 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg,
 {
        log_printf_lf(level, __FILE__, __LINE__, __func__,
                "JTAG tap: %s %16.16s: 0x%08x "
-               "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+               "(mfg: 0x%3.3x (%s), part: 0x%4.4x, ver: 0x%1.1x)",
                name, msg,
                (unsigned int)idcode,
                (unsigned int)EXTRACT_MFG(idcode),
+               jep106_manufacturer(EXTRACT_MFG(idcode)),
                (unsigned int)EXTRACT_PART(idcode),
                (unsigned int)EXTRACT_VER(idcode));
 }
@@ -993,38 +1182,33 @@ 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 && !idcode)
+       if (tap->expected_ids_cnt == 0 || !tap->hasidcode)
                return true;
 
        /* optionally ignore the JTAG version field - bits 28-31 of IDCODE */
-       uint32_t mask = tap->ignore_version ? ~(0xf << 28) : ~0;
-
-       idcode &= mask;
+       uint32_t mask = tap->ignore_version ? ~(0xfU << 28) : ~0U;
+       uint32_t idcode = tap->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++) {
+       for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
                uint32_t expected = tap->expected_ids[ii] & mask;
 
                if (idcode == expected)
                        return true;
 
                /* treat "-expected-id 0" as a "don't-warn" wildcard */
-               if (0 == tap->expected_ids[ii])
+               if (tap->expected_ids[ii] == 0)
                        return true;
        }
 
        /* 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 < limit; ii++) {
+       for (unsigned ii = 0; ii < tap->expected_ids_cnt; ii++) {
                char msg[32];
 
-               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, limit);
+               snprintf(msg, sizeof(msg), "expected %u of %u", ii + 1, tap->expected_ids_cnt);
                jtag_examine_chain_display(LOG_LVL_ERROR, msg,
                        tap->dotted_name, tap->expected_ids[ii]);
        }
@@ -1036,130 +1220,109 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap *tap)
  */
 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;
+       unsigned max_taps = jtag_tap_count();
+
+       /* Autoprobe up to this many. */
+       if (max_taps < JTAG_MAX_AUTO_TAPS)
+               max_taps = JTAG_MAX_AUTO_TAPS;
+
+       /* Add room for end-of-chain marker. */
+       max_taps++;
+
+       uint8_t *idcode_buffer = calloc(4, max_taps);
+       if (!idcode_buffer)
+               return ERROR_JTAG_INIT_FAILED;
 
        /* DR scan to collect BYPASS or IDCODE register contents.
         * Then make sure the scan data has both ones and zeroes.
         */
        LOG_DEBUG("DR scan interrogation for IDCODE/BYPASS");
-       retval = jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
+       retval = jtag_examine_chain_execute(idcode_buffer, max_taps);
        if (retval != ERROR_OK)
-               return retval;
-       if (!jtag_examine_chain_check(idcode_buffer, JTAG_MAX_CHAIN_SIZE))
-               return ERROR_JTAG_INIT_FAILED;
+               goto out;
+       if (!jtag_examine_chain_check(idcode_buffer, max_taps)) {
+               retval = ERROR_JTAG_INIT_FAILED;
+               goto out;
+       }
 
-       /* point at the 1st tap */
+       /* Point at the 1st predefined tap, if any */
        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;
-            tap = jtag_tap_next_enabled(tap)) {
+       unsigned bit_count = 0;
+       unsigned autocount = 0;
+       for (unsigned i = 0; i < max_taps; i++) {
+               assert(bit_count < max_taps * 32);
                uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32);
 
+               /* No predefined TAP? Auto-probe. */
+               if (!tap) {
+                       /* Is there another TAP? */
+                       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) {
+                               retval = ERROR_FAIL;
+                               goto out;
+                       }
+
+                       tap->chip = alloc_printf("auto%u", autocount++);
+                       tap->tapname = strdup("tap");
+                       tap->dotted_name = alloc_printf("%s.%s", tap->chip, tap->tapname);
+
+                       tap->ir_length = 0; /* ... signifying irlen autoprobe */
+                       tap->ir_capture_mask = 0x03;
+                       tap->ir_capture_value = 0x01;
+
+                       tap->enabled = true;
+
+                       jtag_tap_init(tap);
+               }
+
                if ((idcode & 1) == 0) {
                        /* Zero for LSB indicates a device in bypass */
-                       LOG_INFO("TAP %s does not have IDCODE",
-                               tap->dotted_name);
-                       idcode = 0;
+                       LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%" PRIx32 ")",
+                                       tap->dotted_name, idcode);
                        tap->hasidcode = false;
+                       tap->idcode = 0;
 
                        bit_count += 1;
                } else {
                        /* Friendly devices support IDCODE */
                        tap->hasidcode = true;
-                       jtag_examine_chain_display(LOG_LVL_INFO,
-                               "tap/device found",
-                               tap->dotted_name, idcode);
+                       tap->idcode = idcode;
+                       jtag_examine_chain_display(LOG_LVL_INFO, "tap/device found", tap->dotted_name, idcode);
 
                        bit_count += 32;
                }
-               tap->idcode = idcode;
 
                /* ensure the TAP ID matches what was expected */
                if (!jtag_examine_chain_match_tap(tap))
                        retval = ERROR_JTAG_INIT_SOFT_FAIL;
-       }
-
-       /* Fail if too many TAPs were enabled for us to verify them all. */
-       if (tap) {
-               LOG_ERROR("Too many TAPs enabled; '%s' ignored.",
-                       tap->dotted_name);
-               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);
+               tap = jtag_tap_next_enabled(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, missing TAPs, ...)");
-               return ERROR_JTAG_INIT_FAILED;
+       if (jtag_examine_chain_end(idcode_buffer, bit_count, max_taps * 32)) {
+               LOG_ERROR("double-check your JTAG setup (interface, speed, ...)");
+               retval = ERROR_JTAG_INIT_FAILED;
+               goto out;
        }
 
        /* Return success or, for backwards compatibility if only
         * some IDCODE values mismatched, a soft/continuable fault.
         */
+out:
+       free(idcode_buffer);
        return retval;
 }
 
@@ -1174,26 +1337,25 @@ static int jtag_examine_chain(void)
 static int jtag_validate_ircapture(void)
 {
        struct jtag_tap *tap;
-       int total_ir_length = 0;
        uint8_t *ir_test = NULL;
        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) {
+       /* when autoprobing, accommodate huge IR lengths */
+       int total_ir_length = 0;
+       for (tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
                if (tap->ir_length == 0)
                        total_ir_length += JTAG_IRLEN_MAX;
+               else
+                       total_ir_length += tap->ir_length;
        }
 
        /* increase length to add 2 bit sentinel after scan */
        total_ir_length += 2;
 
        ir_test = malloc(DIV_ROUND_UP(total_ir_length, 8));
-       if (ir_test == NULL)
+       if (!ir_test)
                return ERROR_FAIL;
 
        /* after this scan, all TAPs will capture BYPASS instructions */
@@ -1215,14 +1377,14 @@ static int jtag_validate_ircapture(void)
 
        for (;; ) {
                tap = jtag_tap_next_enabled(tap);
-               if (tap == NULL)
+               if (!tap)
                        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.  Or if
-                * (c) an IR length is longer than 32 bits -- which is only
+                * (c) an IR length is longer than JTAG_IRLEN_MAX bits,
                 * an implementation limit, which could someday be raised.
                 *
                 * REVISIT optimization:  if there's a *single* TAP we can
@@ -1236,12 +1398,13 @@ 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 <= 32) {
+                       while (buf_get_u64(ir_test, chain_pos, tap->ir_length + 1) == 1
+                                       && tap->ir_length < JTAG_IRLEN_MAX) {
                                tap->ir_length++;
                        }
-                       LOG_WARNING("AUTO %s - use \"... -irlen %d\"",
-                               jtag_tap_name(tap), tap->ir_length);
+                       LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %d "
+                                       "-expected-id 0x%08" PRIx32 "\"",
+                                       tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode);
                }
 
                /* Validate the two LSBs, which must be 01 per JTAG spec.
@@ -1251,27 +1414,25 @@ static int jtag_validate_ircapture(void)
                 * 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);
+               uint64_t val = buf_get_u64(ir_test, chain_pos, tap->ir_length);
                if ((val & tap->ir_capture_mask) != tap->ir_capture_value) {
-                       LOG_ERROR("%s: IR capture error; saw 0x%0*x not 0x%0*x",
+                       LOG_ERROR("%s: IR capture error; saw 0x%0*" PRIx64 " not 0x%0*" PRIx32,
                                jtag_tap_name(tap),
-                               (tap->ir_length + 7) / tap->ir_length,
-                               val,
-                               (tap->ir_length + 7) / tap->ir_length,
-                               (unsigned) tap->ir_capture_value);
+                               (tap->ir_length + 7) / tap->ir_length, val,
+                               (tap->ir_length + 7) / tap->ir_length, tap->ir_capture_value);
 
                        retval = ERROR_JTAG_INIT_FAILED;
                        goto done;
                }
-               LOG_DEBUG("%s: IR capture 0x%0*x", jtag_tap_name(tap),
+               LOG_DEBUG("%s: IR capture 0x%0*" PRIx64, jtag_tap_name(tap),
                        (tap->ir_length + 7) / tap->ir_length, val);
                chain_pos += tap->ir_length;
        }
 
        /* verify the '11' sentinel we wrote is returned at the end */
-       val = buf_get_u32(ir_test, chain_pos, 2);
+       uint64_t val = buf_get_u64(ir_test, chain_pos, 2);
        if (val != 0x3) {
-               char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
+               char *cbuf = buf_to_hex_str(ir_test, total_ir_length);
 
                LOG_ERROR("IR capture error at bit %d, saw 0x%s not 0x...3",
                        chain_pos, cbuf);
@@ -1294,7 +1455,7 @@ void jtag_tap_init(struct jtag_tap *tap)
        unsigned ir_len_bytes;
 
        /* if we're autoprobing, cope with potentially huge ir_length */
-       ir_len_bits = tap->ir_length ? : JTAG_IRLEN_MAX;
+       ir_len_bits = tap->ir_length ? tap->ir_length : JTAG_IRLEN_MAX;
        ir_len_bytes = DIV_ROUND_UP(ir_len_bits, 8);
 
        tap->expected = calloc(1, ir_len_bytes);
@@ -1327,12 +1488,21 @@ void jtag_tap_free(struct jtag_tap *tap)
 {
        jtag_unregister_event_callback(&jtag_reset_callback, tap);
 
-       /** @todo is anything missing? no memory leaks please */
-       free((void *)tap->expected);
-       free((void *)tap->expected_ids);
-       free((void *)tap->chip);
-       free((void *)tap->tapname);
-       free((void *)tap->dotted_name);
+       struct jtag_tap_event_action *jteap = tap->event_action;
+       while (jteap) {
+               struct jtag_tap_event_action *next = jteap->next;
+               Jim_DecrRefCount(jteap->interp, jteap->body);
+               free(jteap);
+               jteap = next;
+       }
+
+       free(tap->expected);
+       free(tap->expected_mask);
+       free(tap->expected_ids);
+       free(tap->cur_instr);
+       free(tap->chip);
+       free(tap->tapname);
+       free(tap->dotted_name);
        free(tap);
 }
 
@@ -1342,43 +1512,30 @@ void jtag_tap_free(struct jtag_tap *tap)
  */
 int adapter_init(struct command_context *cmd_ctx)
 {
-       if (jtag)
+       if (is_adapter_initialized())
                return ERROR_OK;
 
-       if (!jtag_interface) {
-               /* nothing was previously specified by "interface" command */
+       if (!adapter_driver) {
+               /* nothing was previously specified by "adapter driver" command */
                LOG_ERROR("Debug Adapter has to be specified, "
-                       "see \"interface\" command");
+                       "see \"adapter driver\" command");
                return ERROR_JTAG_INVALID_INTERFACE;
        }
 
        int retval;
-       retval = jtag_interface->init();
+       retval = adapter_driver->init();
        if (retval != ERROR_OK)
                return retval;
-       jtag = jtag_interface;
+       adapter_initialized = true;
 
-       /* LEGACY SUPPORT ... adapter drivers  must declare what
-        * transports they allow.  Until they all do so, assume
-        * the legacy drivers are JTAG-only
-        */
-       if (!transports_are_declared()) {
-               LOG_ERROR("Adapter driver '%s' did not declare "
-                       "which transports it allows; assuming "
-                       "JTAG-only", jtag->name);
-               retval = allow_transports(cmd_ctx, jtag_only);
-               if (retval != ERROR_OK)
-                       return retval;
-       }
-
-       if (jtag->speed == NULL) {
+       if (!adapter_driver->speed) {
                LOG_INFO("This adapter doesn't support configurable speed");
                return ERROR_OK;
        }
 
-       if (CLOCK_MODE_UNSELECTED == clock_mode) {
+       if (clock_mode == CLOCK_MODE_UNSELECTED) {
                LOG_ERROR("An adapter speed is not selected in the init script."
-                       " Insert a call to adapter_khz or jtag_rclk to proceed.");
+                       " Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
                return ERROR_JTAG_INIT_FAILED;
        }
 
@@ -1388,16 +1545,16 @@ int adapter_init(struct command_context *cmd_ctx)
        retval = jtag_get_speed(&jtag_speed_var);
        if (retval != ERROR_OK)
                return retval;
-       retval = jtag->speed(jtag_speed_var);
+       retval = adapter_driver->speed(jtag_speed_var);
        if (retval != ERROR_OK)
                return retval;
        retval = jtag_get_speed_readable(&actual_khz);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                LOG_INFO("adapter-specific clock speed value %d", jtag_speed_var);
        else if (actual_khz) {
                /* Adaptive clocking -- JTAG-specific */
-               if ((CLOCK_MODE_RCLK == clock_mode)
-                               || ((CLOCK_MODE_KHZ == clock_mode) && !requested_khz)) {
+               if ((clock_mode == CLOCK_MODE_RCLK)
+                               || ((clock_mode == CLOCK_MODE_KHZ) && !requested_khz)) {
                        LOG_INFO("RCLK (adaptive clock speed) not supported - fallback to %d kHz"
                        , actual_khz);
                } else
@@ -1417,7 +1574,7 @@ int jtag_init_inner(struct command_context *cmd_ctx)
        LOG_DEBUG("Init JTAG chain");
 
        tap = jtag_tap_next_enabled(NULL);
-       if (tap == NULL) {
+       if (!tap) {
                /* Once JTAG itself is properly set up, and the scan chain
                 * isn't absurdly large, IDCODE autoprobe should work fine.
                 *
@@ -1490,30 +1647,38 @@ int jtag_init_inner(struct command_context *cmd_ctx)
 
 int adapter_quit(void)
 {
-       if (!jtag || !jtag->quit)
-               return ERROR_OK;
+       if (is_adapter_initialized() && adapter_driver->quit) {
+               /* close the JTAG interface */
+               int result = adapter_driver->quit();
+               if (result != ERROR_OK)
+                       LOG_ERROR("failed: %d", result);
+       }
 
-       /* close the JTAG interface */
-       int result = jtag->quit();
-       if (ERROR_OK != result)
-               LOG_ERROR("failed: %d", result);
+       struct jtag_tap *t = jtag_all_taps();
+       while (t) {
+               struct jtag_tap *n = t->next_tap;
+               jtag_tap_free(t);
+               t = n;
+       }
 
        return ERROR_OK;
 }
 
 int swd_init_reset(struct command_context *cmd_ctx)
 {
-       int retval = adapter_init(cmd_ctx);
+       int retval, retval1;
+
+       retval = adapter_init(cmd_ctx);
        if (retval != ERROR_OK)
                return retval;
 
        LOG_DEBUG("Initializing with hard SRST reset");
 
        if (jtag_reset_config & RESET_HAS_SRST)
-               swd_add_reset(1);
-       swd_add_reset(0);
-       retval = jtag_execute_queue();
-       return retval;
+               retval = adapter_system_reset(1);
+       retval1 = adapter_system_reset(0);
+
+       return (retval == ERROR_OK) ? retval1 : retval;
 }
 
 int jtag_init_reset(struct command_context *cmd_ctx)
@@ -1548,11 +1713,12 @@ int jtag_init_reset(struct command_context *cmd_ctx)
         * 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) {
                jtag_add_reset(1, 1);
                if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
                        jtag_add_reset(0, 1);
+       } else {
+               jtag_add_reset(1, 0);   /* TAP_RESET, using TMS+TCK or TRST */
        }
 
        /* some targets enable us to connect with srst asserted */
@@ -1614,21 +1780,25 @@ static int adapter_khz_to_speed(unsigned khz, int *speed)
 {
        LOG_DEBUG("convert khz to interface specific speed value");
        speed_khz = khz;
-       if (jtag != NULL) {
-               LOG_DEBUG("have interface set up");
-               int speed_div1;
-               int retval = jtag->khz(jtag_get_speed_khz(), &speed_div1);
-               if (ERROR_OK != retval)
-                       return retval;
-               *speed = speed_div1;
+       if (!is_adapter_initialized())
+               return ERROR_OK;
+       LOG_DEBUG("have interface set up");
+       if (!adapter_driver->khz) {
+               LOG_ERROR("Translation from khz to jtag_speed not implemented");
+               return ERROR_FAIL;
        }
+       int speed_div1;
+       int retval = adapter_driver->khz(jtag_get_speed_khz(), &speed_div1);
+       if (retval != ERROR_OK)
+               return retval;
+       *speed = speed_div1;
        return ERROR_OK;
 }
 
 static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed)
 {
        int retval = adapter_khz_to_speed(0, speed);
-       if ((ERROR_OK != retval) && fallback_speed_khz) {
+       if ((retval != ERROR_OK) && fallback_speed_khz) {
                LOG_DEBUG("trying fallback speed...");
                retval = adapter_khz_to_speed(fallback_speed_khz, speed);
        }
@@ -1637,10 +1807,9 @@ static int jtag_rclk_to_speed(unsigned fallback_speed_khz, int *speed)
 
 static int jtag_set_speed(int speed)
 {
-       jtag_speed = speed;
        /* this command can be called during CONFIG,
         * in which case jtag isn't initialized */
-       return jtag ? jtag->speed(speed) : ERROR_OK;
+       return is_adapter_initialized() ? adapter_driver->speed(speed) : ERROR_OK;
 }
 
 int jtag_config_khz(unsigned khz)
@@ -1649,7 +1818,7 @@ int jtag_config_khz(unsigned khz)
        clock_mode = CLOCK_MODE_KHZ;
        int speed = 0;
        int retval = adapter_khz_to_speed(khz, &speed);
-       return (ERROR_OK != retval) ? retval : jtag_set_speed(speed);
+       return (retval != ERROR_OK) ? retval : jtag_set_speed(speed);
 }
 
 int jtag_config_rclk(unsigned fallback_speed_khz)
@@ -1659,7 +1828,7 @@ int jtag_config_rclk(unsigned fallback_speed_khz)
        rclk_fallback_speed_khz = fallback_speed_khz;
        int speed = 0;
        int retval = jtag_rclk_to_speed(fallback_speed_khz, &speed);
-       return (ERROR_OK != retval) ? retval : jtag_set_speed(speed);
+       return (retval != ERROR_OK) ? retval : jtag_set_speed(speed);
 }
 
 int jtag_get_speed(int *speed)
@@ -1684,7 +1853,13 @@ int jtag_get_speed_readable(int *khz)
        int retval = jtag_get_speed(&jtag_speed_var);
        if (retval != ERROR_OK)
                return retval;
-       return jtag ? jtag->speed_div(jtag_speed_var, khz) : ERROR_OK;
+       if (!is_adapter_initialized())
+               return ERROR_OK;
+       if (!adapter_driver->speed_div) {
+               LOG_ERROR("Translation from jtag_speed to khz not implemented");
+               return ERROR_FAIL;
+       }
+       return adapter_driver->speed_div(jtag_speed_var, khz);
 }
 
 void jtag_set_verify(bool enable)
@@ -1692,7 +1867,7 @@ void jtag_set_verify(bool enable)
        jtag_verify = enable;
 }
 
-bool jtag_will_verify()
+bool jtag_will_verify(void)
 {
        return jtag_verify;
 }
@@ -1702,25 +1877,33 @@ void jtag_set_verify_capture_ir(bool enable)
        jtag_verify_capture_ir = enable;
 }
 
-bool jtag_will_verify_capture_ir()
+bool jtag_will_verify_capture_ir(void)
 {
        return jtag_verify_capture_ir;
 }
 
 int jtag_power_dropout(int *dropout)
 {
-       if (jtag == NULL) {
+       if (!is_adapter_initialized()) {
                /* TODO: as the jtag interface is not valid all
                 * we can do at the moment is exit OpenOCD */
                LOG_ERROR("No Valid JTAG Interface Configured.");
                exit(-1);
        }
-       return jtag->power_dropout(dropout);
+       if (adapter_driver->power_dropout)
+               return adapter_driver->power_dropout(dropout);
+
+       *dropout = 0; /* by default we can't detect power dropout */
+       return ERROR_OK;
 }
 
 int jtag_srst_asserted(int *srst_asserted)
 {
-       return jtag->srst_asserted(srst_asserted);
+       if (adapter_driver->srst_asserted)
+               return adapter_driver->srst_asserted(srst_asserted);
+
+       *srst_asserted = 0; /* by default we can't detect srst asserted */
+       return ERROR_OK;
 }
 
 enum reset_types jtag_get_reset_config(void)
@@ -1734,11 +1917,11 @@ void jtag_set_reset_config(enum reset_types type)
 
 int jtag_get_trst(void)
 {
-       return jtag_trst;
+       return jtag_trst == 1;
 }
 int jtag_get_srst(void)
 {
-       return jtag_srst;
+       return jtag_srst == 1;
 }
 
 void jtag_set_nsrst_delay(unsigned delay)
@@ -1794,7 +1977,12 @@ static int jtag_select(struct command_context *ctx)
        if (retval != ERROR_OK)
                return retval;
 
-       return xsvf_register_commands(ctx);
+       retval = xsvf_register_commands(ctx);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       return ipdbg_register_commands(ctx);
 }
 
 static struct transport jtag_transport = {
@@ -1817,31 +2005,109 @@ bool transport_is_jtag(void)
        return get_current_transport() == &jtag_transport;
 }
 
-void adapter_assert_reset(void)
+int adapter_resets(int trst, int srst)
+{
+       if (!get_current_transport()) {
+               LOG_ERROR("transport is not selected");
+               return ERROR_FAIL;
+       }
+
+       if (transport_is_jtag()) {
+               if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+                       LOG_ERROR("adapter has no srst signal");
+                       return ERROR_FAIL;
+               }
+
+               /* adapters without trst signal will eventually use tlr sequence */
+               jtag_add_reset(trst, srst);
+               /*
+                * The jtag queue is still used for reset by some adapter. Flush it!
+                * FIXME: To be removed when all adapter drivers will be updated!
+                */
+               jtag_execute_queue();
+               return ERROR_OK;
+       } else if (transport_is_swd() || transport_is_hla() ||
+                          transport_is_dapdirect_swd() || transport_is_dapdirect_jtag() ||
+                          transport_is_swim()) {
+               if (trst == TRST_ASSERT) {
+                       LOG_ERROR("transport %s has no trst signal",
+                               get_current_transport()->name);
+                       return ERROR_FAIL;
+               }
+
+               if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
+                       LOG_ERROR("adapter has no srst signal");
+                       return ERROR_FAIL;
+               }
+               adapter_system_reset(srst);
+               return ERROR_OK;
+       }
+
+       if (trst == TRST_DEASSERT && srst == SRST_DEASSERT)
+               return ERROR_OK;
+
+       LOG_ERROR("reset is not supported on transport %s",
+               get_current_transport()->name);
+
+       return ERROR_FAIL;
+}
+
+int adapter_assert_reset(void)
 {
        if (transport_is_jtag()) {
                if (jtag_reset_config & RESET_SRST_PULLS_TRST)
                        jtag_add_reset(1, 1);
                else
                        jtag_add_reset(0, 1);
-       } else if (transport_is_swd())
-               swd_add_reset(1);
-       else if (get_current_transport() != NULL)
+               return ERROR_OK;
+       } else if (transport_is_swd() || transport_is_hla() ||
+                          transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
+                          transport_is_swim())
+               return adapter_system_reset(1);
+       else if (get_current_transport())
                LOG_ERROR("reset is not supported on %s",
                        get_current_transport()->name);
        else
                LOG_ERROR("transport is not selected");
+       return ERROR_FAIL;
 }
 
-void adapter_deassert_reset(void)
+int adapter_deassert_reset(void)
 {
-       if (transport_is_jtag())
+       if (transport_is_jtag()) {
                jtag_add_reset(0, 0);
-       else if (transport_is_swd())
-               swd_add_reset(0);
-       else if (get_current_transport() != NULL)
+               return ERROR_OK;
+       } else if (transport_is_swd() || transport_is_hla() ||
+                          transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
+                          transport_is_swim())
+               return adapter_system_reset(0);
+       else if (get_current_transport())
                LOG_ERROR("reset is not supported on %s",
                        get_current_transport()->name);
        else
                LOG_ERROR("transport is not selected");
+       return ERROR_FAIL;
+}
+
+int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
+               uint32_t port_size, unsigned int *trace_freq,
+               unsigned int traceclkin_freq, uint16_t *prescaler)
+{
+       if (adapter_driver->config_trace) {
+               return adapter_driver->config_trace(enabled, pin_protocol, port_size, trace_freq,
+                       traceclkin_freq, prescaler);
+       } else if (enabled) {
+               LOG_ERROR("The selected interface does not support tracing");
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+int adapter_poll_trace(uint8_t *buf, size_t *size)
+{
+       if (adapter_driver->poll_trace)
+               return adapter_driver->poll_trace(buf, size);
+
+       return ERROR_FAIL;
 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)