+ }
+ break;
+
+ case XWAITSTATE:
+ {
+ /* expected in stream:
+ XWAITSTATE <uint8_t wait_state> <uint8_t end_state> <uint32_t clock_count> <uint32_t usecs>
+ */
+
+ uint8_t clock_buf[4];
+ uint8_t usecs_buf[4];
+ uint8_t wait;
+ uint8_t end;
+ tap_state_t wait_state;
+ tap_state_t end_state;
+ int clock_count;
+ int usecs;
+
+ if (read(xsvf_fd, &wait, 1) < 0
+ || read(xsvf_fd, &end, 1) < 0
+ || read(xsvf_fd, clock_buf, 4) < 0
+ || read(xsvf_fd, usecs_buf, 4) < 0)
+ {
+ do_abort = 1;
+ break;
+ }
+
+ wait_state = xsvf_to_tap(wait);
+ end_state = xsvf_to_tap(end);
+
+ clock_count = be_to_h_u32(clock_buf);
+ usecs = be_to_h_u32(usecs_buf);
+
+ LOG_DEBUG("XWAITSTATE %s %s clocks:%i usecs:%i",
+ tap_state_name(wait_state),
+ tap_state_name(end_state),
+ clock_count, usecs);
+
+ /* the following states are 'stable', meaning that they have a transition
+ * in the state diagram back to themselves. This is necessary because we will
+ * be issuing a number of clocks in this state. This set of allowed states is also
+ * determined by the SVF RUNTEST command's allowed states.
+ */
+ if (wait_state != TAP_IRPAUSE && wait_state != TAP_DRPAUSE && wait_state != TAP_RESET && wait_state != TAP_IDLE)
+ {
+ LOG_ERROR("illegal XWAITSTATE wait_state: \"%s\"", tap_state_name(wait_state));
+ unsupported = 1;
+ }
+
+ jtag_add_statemove(wait_state);
+
+ jtag_add_clocks(clock_count);
+
+ jtag_add_sleep(usecs);
+
+ jtag_add_statemove(end_state);
+ }
+ break;
+
+ case LCOUNT:
+ {
+ /* expected in stream:
+ LCOUNT <uint32_t loop_count>
+ */
+ uint8_t count_buf[4];
+
+ if (read(xsvf_fd, count_buf, 4) < 0)
+ {
+ do_abort = 1;
+ break;
+ }
+
+ loop_count = be_to_h_u32(count_buf);
+ LOG_DEBUG("LCOUNT %d", loop_count);
+ }
+ break;
+
+ case LDELAY:
+ {
+ /* expected in stream:
+ LDELAY <uint8_t wait_state> <uint32_t clock_count> <uint32_t usecs_to_sleep>
+ */
+ uint8_t state;
+ uint8_t clock_buf[4];
+ uint8_t usecs_buf[4];
+
+ if (read(xsvf_fd, &state, 1) < 0
+ || read(xsvf_fd, clock_buf, 4) < 0
+ || read(xsvf_fd, usecs_buf, 4) < 0)
+ {
+ do_abort = 1;
+ break;
+ }
+
+ loop_state = xsvf_to_tap(state);
+ loop_clocks = be_to_h_u32(clock_buf);
+ loop_usecs = be_to_h_u32(usecs_buf);
+
+ LOG_DEBUG("LDELAY %s clocks:%d usecs:%d", tap_state_name(loop_state), loop_clocks, loop_usecs);
+ }
+ break;
+
+ /* LSDR is more like XSDRTDO than it is like XSDR. It uses LDELAY which
+ * comes with clocks !AND! sleep requirements.
+ */
+ case LSDR:
+ {
+ int limit = loop_count;
+ int matched = 0;
+ int attempt;
+
+ LOG_DEBUG("LSDR");
+
+ if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK
+ || xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)
+ {
+ do_abort = 1;
+ break;
+ }
+
+ if (limit < 1)
+ limit = 1;
+
+ for (attempt = 0; attempt < limit; ++attempt)
+ {
+ scan_field_t field;
+
+ jtag_add_statemove(loop_state);
+ jtag_add_clocks(loop_clocks);
+ jtag_add_sleep(loop_usecs);
+
+ field.tap = tap;
+ field.num_bits = xsdrsize;
+ field.out_value = dr_out_buf;
+ field.in_value = calloc(CEIL(field.num_bits, 8), 1);
+
+ if (attempt > 0 && verbose)
+ LOG_USER("LSDR retry %d", attempt);
+
+ if (tap == NULL)
+ jtag_add_plain_dr_scan(1, &field, jtag_set_end_state(TAP_DRPAUSE));
+ else
+ jtag_add_dr_scan(1, &field, jtag_set_end_state(TAP_DRPAUSE));
+
+ jtag_check_value_mask(&field, dr_in_buf, dr_in_mask);
+
+ free(field.in_value);
+
+
+ /* LOG_DEBUG("FLUSHING QUEUE"); */
+ result = jtag_execute_queue();
+ if (result == ERROR_OK)
+ {
+ matched = 1;
+ break;
+ }
+ }
+
+ if (!matched)
+ {
+ LOG_USER("LSDR mismatch");
+ tdo_mismatch = 1;
+ break;
+ }
+ }
+ break;
+
+ case XTRST:
+ {
+ uint8_t trst_mode;
+
+ if (read(xsvf_fd, &trst_mode, 1) < 0)
+ {
+ do_abort = 1;
+ break;
+ }
+
+ switch (trst_mode)
+ {
+ case XTRST_ON:
+ jtag_add_reset(1, 0);
+ break;
+ case XTRST_OFF:
+ case XTRST_Z:
+ jtag_add_reset(0, 0);
+ break;
+ case XTRST_ABSENT:
+ break;
+ default:
+ LOG_ERROR("XTRST mode argument (0x%02X) out of range", trst_mode);
+ do_abort = 1;
+ }
+ }
+ break;
+
+ default:
+ LOG_ERROR("unknown xsvf command (0x%02X)\n", uc);
+ unsupported = 1;