+ tap = jtag_tap_by_jim_obj(interp, args[1]);
+ if (tap == NULL) {
+ return JIM_ERR;
+ }
+
+ num_fields = (argc-2)/2;
+ assert(num_fields > 0);
+ fields = malloc(sizeof(struct scan_field) * num_fields);
+ for (i = 2; i < argc; i += 2)
+ {
+ long bits;
+ int len;
+ const char *str;
+
+ Jim_GetLong(interp, args[i], &bits);
+ str = Jim_GetString(args[i + 1], &len);
+
+ fields[field_count].num_bits = bits;
+ void * t = malloc(DIV_ROUND_UP(bits, 8));
+ fields[field_count].out_value = t;
+ str_to_buf(str, len, t, bits, 0);
+ fields[field_count].in_value = t;
+ field_count++;
+ }
+
+ jtag_add_dr_scan(tap, num_fields, fields, endstate);
+
+ retval = jtag_execute_queue();
+ if (retval != ERROR_OK)
+ {
+ Jim_SetResultString(interp, "drscan: jtag execute failed",-1);
+ return JIM_ERR;
+ }
+
+ field_count = 0;
+ Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
+ for (i = 2; i < argc; i += 2)
+ {
+ long bits;
+ char *str;
+
+ Jim_GetLong(interp, args[i], &bits);
+ str = buf_to_str(fields[field_count].in_value, bits, 16);
+ free((void *)fields[field_count].out_value);
+
+ Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));
+ free(str);
+ field_count++;
+ }
+
+ Jim_SetResult(interp, list);
+
+ free(fields);
+
+ return JIM_OK;
+}
+
+
+static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *args)
+{
+ tap_state_t states[8];
+
+ if ((argc < 2) || ((size_t)argc > (ARRAY_SIZE(states) + 1)))
+ {
+ Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
+ return JIM_ERR;
+ }
+
+ script_debug(interp, "pathmove", argc, args);
+
+ int i;
+ for (i = 0; i < argc-1; i++)
+ {
+ const char *cp;
+ cp = Jim_GetString(args[i + 1], NULL);
+ states[i] = tap_state_by_name(cp);
+ if (states[i] < 0)
+ {
+ /* update the error message */
+ Jim_SetResultFormatted(interp,"endstate: %s invalid", cp);
+ return JIM_ERR;
+ }
+ }
+
+ if ((jtag_add_statemove(states[0]) != ERROR_OK) || (jtag_execute_queue()!= ERROR_OK))
+ {
+ Jim_SetResultString(interp, "pathmove: jtag execute failed",-1);
+ return JIM_ERR;
+ }
+
+ jtag_add_pathmove(argc-2, states + 1);
+
+ if (jtag_execute_queue()!= ERROR_OK)
+ {
+ Jim_SetResultString(interp, "pathmove: failed",-1);
+ return JIM_ERR;
+ }
+
+ return JIM_OK;
+}
+
+
+static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args)
+{
+ script_debug(interp, "flush_count", argc, args);
+
+ Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
+
+ return JIM_OK;
+}
+
+/* REVISIT Just what about these should "move" ... ?
+ * These registrations, into the main JTAG table?
+ *
+ * There's a minor compatibility issue, these all show up twice;
+ * that's not desirable:
+ * - jtag drscan ... NOT DOCUMENTED!
+ * - drscan ...
+ *
+ * The "irscan" command (for example) doesn't show twice.
+ */
+static const struct command_registration jtag_command_handlers_to_move[] = {
+ {
+ .name = "drscan",
+ .mode = COMMAND_EXEC,
+ .jim_handler = Jim_Command_drscan,
+ .help = "Execute Data Register (DR) scan for one TAP. "
+ "Other TAPs must be in BYPASS mode.",
+ .usage = "tap_name [num_bits value]* ['-endstate' state_name]",
+ },
+ {
+ .name = "flush_count",
+ .mode = COMMAND_EXEC,
+ .jim_handler = Jim_Command_flush_count,
+ .help = "Returns the number of times the JTAG queue "
+ "has been flushed.",
+ },
+ {
+ .name = "pathmove",
+ .mode = COMMAND_EXEC,
+ .jim_handler = Jim_Command_pathmove,
+ .usage = "start_state state1 [state2 [state3 ...]]",
+ .help = "Move JTAG state machine from current state "
+ "(start_state) to state1, then state2, state3, etc.",
+ },
+ COMMAND_REGISTRATION_DONE
+};