+ retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("runtest %i cycles, end in %s",
+ cmd->cmd.runtest->num_cycles,
+ tap_state_name(cmd->cmd.runtest->end_state));
+
+ /* only send the maximum buffer size that FT2232C can handle */
+ predicted_size = 0;
+ if (tap_get_state() != TAP_IDLE)
+ predicted_size += 3;
+ predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7);
+ if ( cmd->cmd.runtest->end_state != TAP_IDLE)
+ predicted_size += 3;
+ if ( tap_get_end_state() != TAP_IDLE)
+ predicted_size += 3;
+ if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+ {
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ require_send = 0;
+ first_unsent = cmd;
+ }
+ if (tap_get_state() != TAP_IDLE)
+ {
+ move_to_state( TAP_IDLE );
+ require_send = 1;
+ }
+ i = cmd->cmd.runtest->num_cycles;
+ while (i > 0)
+ {
+ /* there are no state transitions in this code, so omit state tracking */
+
+ /* command "Clock Data to TMS/CS Pin (no Read)" */
+ buffer_write( 0x4b );
+
+ /* scan 7 bits */
+ buffer_write( (i > 7) ? 6 : (i - 1) );
+
+ /* TMS data bits */
+ buffer_write( 0x0 );
+ tap_set_state(TAP_IDLE);
+
+ i -= (i > 7) ? 7 : i;
+ /* LOG_DEBUG("added TMS scan (no read)"); */
+ }
+
+ ft2232_end_state(cmd->cmd.runtest->end_state);
+
+ if ( tap_get_state() != tap_get_end_state() )
+ {
+ move_to_state( tap_get_end_state() );
+ }
+
+ require_send = 1;
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG( "runtest: %i, end in %s", cmd->cmd.runtest->num_cycles, tap_state_name( tap_get_end_state() ) );
+#endif
+
+ return retval;
+}
+
+
+static int ft2232_execute_statemove(jtag_command_t *cmd)
+{
+ int predicted_size = 0;
+ int retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
+
+ /* only send the maximum buffer size that FT2232C can handle */
+ predicted_size = 3;
+ if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+ {
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ require_send = 0;
+ first_unsent = cmd;
+ }
+ ft2232_end_state(cmd->cmd.statemove->end_state);
+
+ /* move to end state */
+ if ( tap_get_state() != tap_get_end_state() )
+ {
+ move_to_state( tap_get_end_state() );
+ require_send = 1;
+ }
+
+ return retval;
+}
+
+static int ft2232_execute_pathmove(jtag_command_t *cmd)
+{
+ int predicted_size = 0;
+ int retval = ERROR_OK;
+
+ tap_state_t* path = cmd->cmd.pathmove->path;
+ int num_states = cmd->cmd.pathmove->num_states;
+
+ DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states,
+ tap_state_name( tap_get_state() ),
+ tap_state_name( path[num_states-1] )
+ );
+
+ /* only send the maximum buffer size that FT2232C can handle */
+ predicted_size = 3 * CEIL(num_states, 7);
+ if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+ {
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+
+ require_send = 0;
+ first_unsent = cmd;
+ }
+
+ ft2232_add_pathmove( path, num_states );
+ require_send = 1;
+
+ return retval;
+}
+
+
+static int ft2232_execute_scan(jtag_command_t *cmd)
+{
+ u8* buffer;
+ int scan_size; /* size of IR or DR scan */
+ int predicted_size = 0;
+ int retval = ERROR_OK;
+
+ enum scan_type type = jtag_scan_type(cmd->cmd.scan);
+
+ DEBUG_JTAG_IO( "%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", type );
+
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+
+ predicted_size = ft2232_predict_scan_out(scan_size, type);
+ if ( (predicted_size + 1) > FT2232_BUFFER_SIZE )
+ {
+ LOG_DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");
+ /* unsent commands before this */
+ if (first_unsent != cmd)
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+
+ /* current command */
+ ft2232_end_state(cmd->cmd.scan->end_state);
+ ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size);
+ require_send = 0;
+ first_unsent = cmd->next;
+ if (buffer)
+ free(buffer);
+ return retval;
+ }
+ else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+ {
+ LOG_DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)",
+ first_unsent,
+ cmd);
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ require_send = 0;
+ first_unsent = cmd;
+ }
+ ft2232_expect_read += ft2232_predict_scan_in(scan_size, type);
+ /* LOG_DEBUG("new read size: %i", ft2232_expect_read); */
+ ft2232_end_state(cmd->cmd.scan->end_state);
+ ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+ require_send = 1;
+ if (buffer)
+ free(buffer);
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG( "%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size,
+ tap_state_name( tap_get_end_state() ) );
+#endif
+ return retval;
+
+}
+
+static int ft2232_execute_reset(jtag_command_t *cmd)
+{
+ int retval;
+ int predicted_size = 0;
+ retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("reset trst: %i srst %i",
+ cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+
+ /* only send the maximum buffer size that FT2232C can handle */
+ predicted_size = 3;
+ if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+ {
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ require_send = 0;
+ first_unsent = cmd;
+ }
+
+ layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+ require_send = 1;
+
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+ return retval;
+}
+
+static int ft2232_execute_sleep(jtag_command_t *cmd)
+{
+ int retval;
+ retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("sleep %i", cmd->cmd.sleep->us);
+
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ first_unsent = cmd->next;
+ jtag_sleep(cmd->cmd.sleep->us);
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG( "sleep %i usec while in %s", cmd->cmd.sleep->us, tap_state_name( tap_get_state() ) );
+#endif
+
+ return retval;
+}
+
+static int ft2232_execute_stableclocks(jtag_command_t *cmd)
+{
+ int retval;
+ retval = ERROR_OK;
+
+ /* this is only allowed while in a stable state. A check for a stable
+ * state was done in jtag_add_clocks()
+ */
+ if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG( "clocks %i while in %s", cmd->cmd.stableclocks->num_cycles, tap_state_name( tap_get_state() ) );
+#endif
+
+ return retval;
+}
+
+static int ft2232_execute_command(jtag_command_t *cmd)
+{
+ int retval;
+ retval = ERROR_OK;
+
+ switch (cmd->type)
+ {
+ case JTAG_RESET: retval = ft2232_execute_reset(cmd); break;
+ case JTAG_RUNTEST: retval = ft2232_execute_runtest(cmd); break;
+ case JTAG_STATEMOVE: retval = ft2232_execute_statemove(cmd); break;
+ case JTAG_PATHMOVE: retval = ft2232_execute_pathmove(cmd); break;
+ case JTAG_SCAN: retval = ft2232_execute_scan(cmd); break;
+ case JTAG_SLEEP: retval = ft2232_execute_sleep(cmd); break;
+ case JTAG_STABLECLOCKS: retval = ft2232_execute_stableclocks(cmd); break;
+ default:
+ LOG_ERROR("BUG: unknown JTAG command type encountered");
+ exit(-1);
+ }
+ return retval;
+}
+
+static int ft2232_execute_queue()
+{
+ jtag_command_t* cmd = jtag_command_queue; /* currently processed command */
+ int retval;
+
+ first_unsent = cmd; /* next command that has to be sent */
+ require_send = 0;
+