- switch(cmd->type)
- {
- case JTAG_END_STATE:
- if (cmd->cmd.end_state->end_state != -1)
- ft2232_end_state(cmd->cmd.end_state->end_state);
- break;
- case JTAG_RESET:
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 3;
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
- {
- ft2232_send_and_recv(first_unsent, cmd);
- require_send = 0;
- first_unsent = cmd;
- }
-
- layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
- require_send = 1;
-
-#ifdef _DEBUG_JTAG_IO_
- DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
-#endif
- break;
- case JTAG_RUNTEST:
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 0;
- if (cur_state != TAP_RTI)
- predicted_size += 3;
- predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7);
- if ((cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_RTI))
- predicted_size += 3;
- if ((cmd->cmd.runtest->end_state == -1) && (end_state != TAP_RTI))
- predicted_size += 3;
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
- {
- ft2232_send_and_recv(first_unsent, cmd);
- require_send = 0;
- first_unsent = cmd;
- }
- if (cur_state != TAP_RTI)
- {
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- BUFFER_ADD = 0x4b;
- /* scan 7 bit */
- BUFFER_ADD = 0x6;
- /* TMS data bits */
- BUFFER_ADD = TAP_MOVE(cur_state, TAP_RTI);
- cur_state = TAP_RTI;
- require_send = 1;
- }
- i = cmd->cmd.runtest->num_cycles;
- while (i > 0)
- {
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- BUFFER_ADD = 0x4b;
- /* scan 7 bit */
- BUFFER_ADD = (i > 7) ? 6 : (i - 1);
- /* TMS data bits */
- BUFFER_ADD = 0x0;
- cur_state = TAP_RTI;
- i -= (i > 7) ? 7 : i;
- //DEBUG("added TMS scan (no read)");
- }
- if (cmd->cmd.runtest->end_state != -1)
- ft2232_end_state(cmd->cmd.runtest->end_state);
- if (cur_state != end_state)
- {
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- BUFFER_ADD = 0x4b;
- /* scan 7 bit */
- BUFFER_ADD = 0x6;
- /* TMS data bits */
- BUFFER_ADD = TAP_MOVE(cur_state, end_state);
- cur_state = end_state;
- //DEBUG("added TMS scan (no read)");
- }
- require_send = 1;
-#ifdef _DEBUG_JTAG_IO_
- DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state);
-#endif
- break;
- case JTAG_STATEMOVE:
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 3;
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
- {
- ft2232_send_and_recv(first_unsent, cmd);
- require_send = 0;
- first_unsent = cmd;
- }
- if (cmd->cmd.statemove->end_state != -1)
- ft2232_end_state(cmd->cmd.statemove->end_state);
- /* command "Clock Data to TMS/CS Pin (no Read)" */
- BUFFER_ADD = 0x4b;
- /* scan 7 bit */
- BUFFER_ADD = 0x6;
- /* TMS data bits */
- BUFFER_ADD = TAP_MOVE(cur_state, end_state);
- //DEBUG("added TMS scan (no read)");
- cur_state = end_state;
- require_send = 1;
-#ifdef _DEBUG_JTAG_IO_
- DEBUG("statemove: %i", end_state);
-#endif
- break;
- case JTAG_PATHMOVE:
- /* only send the maximum buffer size that FT2232C can handle */
- predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7);
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
- {
- ft2232_send_and_recv(first_unsent, cmd);
- require_send = 0;
- first_unsent = cmd;
- }
- ft2232_add_pathmove(cmd->cmd.pathmove);
- require_send = 1;
-#ifdef _DEBUG_JTAG_IO_
- DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
-#endif
- break;
- case JTAG_SCAN:
- scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
- type = jtag_scan_type(cmd->cmd.scan);
- predicted_size = ft2232_predict_scan_out(scan_size, type);
- if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
- {
- DEBUG("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd);
- ft2232_send_and_recv(first_unsent, cmd);
- require_send = 0;
- first_unsent = cmd;
- }
- ft2232_expect_read += ft2232_predict_scan_in(scan_size, type);
- //DEBUG("new read size: %i", ft2232_expect_read);
- if (cmd->cmd.scan->end_state != -1)
- 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_
- DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state);
-#endif
- break;
- case JTAG_SLEEP:
- ft2232_send_and_recv(first_unsent, cmd);
- first_unsent = cmd->next;
- jtag_sleep(cmd->cmd.sleep->us);
-#ifdef _DEBUG_JTAG_IO_
- DEBUG("sleep %i usec", cmd->cmd.sleep->us);
-#endif
- break;
- default:
- ERROR("BUG: unknown JTAG command type encountered");
- exit(-1);
- }
- cmd = cmd->next;
+ high_output &= ~nSRST;
+ }
+ else if (srst == 0)
+ {
+ high_output |= nSRST;
+ }
+
+ /* command "set data bits low byte" */
+ BUFFER_ADD = 0x82;
+ BUFFER_ADD = high_output;
+ BUFFER_ADD = high_direction;
+ LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output,
+ high_direction);
+}
+
+
+static void flyswatter_reset(int trst, int srst)
+{
+ if (trst == 1)
+ {
+ low_output &= ~nTRST;
+ }
+ else if (trst == 0)
+ {
+ low_output |= nTRST;
+ }
+
+ if (srst == 1)
+ {
+ low_output |= nSRST;
+ }
+ else if (srst == 0)
+ {
+ low_output &= ~nSRST;
+ }
+
+ /* command "set data bits low byte" */
+ BUFFER_ADD = 0x80;
+ BUFFER_ADD = low_output;
+ BUFFER_ADD = low_direction;
+ LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction);
+}
+
+
+static void turtle_reset(int trst, int srst)
+{
+ trst = trst;
+
+ if (srst == 1)
+ {
+ low_output |= nSRST;
+ }
+ else if (srst == 0)
+ {
+ low_output &= ~nSRST;
+ }
+
+ /* command "set data bits low byte" */
+ BUFFER_ADD = 0x80;
+ BUFFER_ADD = low_output;
+ BUFFER_ADD = low_direction;
+ LOG_DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction);
+}
+
+
+static void comstick_reset(int trst, int srst)
+{
+ if (trst == 1)
+ {
+ high_output &= ~nTRST;
+ }
+ else if (trst == 0)
+ {
+ high_output |= nTRST;
+ }
+
+ if (srst == 1)
+ {
+ high_output &= ~nSRST;
+ }
+ else if (srst == 0)
+ {
+ high_output |= nSRST;
+ }
+
+ /* command "set data bits high byte" */
+ BUFFER_ADD = 0x82;
+ BUFFER_ADD = high_output;
+ BUFFER_ADD = high_direction;
+ LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output,
+ high_direction);
+}
+
+
+static void stm32stick_reset(int trst, int srst)
+{
+ if (trst == 1)
+ {
+ high_output &= ~nTRST;
+ }
+ else if (trst == 0)
+ {
+ high_output |= nTRST;
+ }
+
+ if (srst == 1)
+ {
+ low_output &= ~nSRST;
+ }
+ else if (srst == 0)
+ {
+ low_output |= nSRST;
+ }
+
+ /* command "set data bits low byte" */
+ BUFFER_ADD = 0x80;
+ BUFFER_ADD = low_output;
+ BUFFER_ADD = low_direction;
+
+ /* command "set data bits high byte" */
+ BUFFER_ADD = 0x82;
+ BUFFER_ADD = high_output;
+ BUFFER_ADD = high_direction;
+ LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output,
+ high_direction);
+}
+
+
+
+static void sheevaplug_reset(int trst, int srst)
+{
+ if (trst == 1)
+ high_output &= ~nTRST;
+ else if (trst == 0)
+ high_output |= nTRST;
+
+ if (srst == 1)
+ high_output &= ~nSRSTnOE;
+ else if (srst == 0)
+ high_output |= nSRSTnOE;
+
+ /* command "set data bits high byte" */
+ BUFFER_ADD = 0x82;
+ BUFFER_ADD = high_output;
+ BUFFER_ADD = high_direction;
+ LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
+}
+
+static int ft2232_execute_end_state(jtag_command_t *cmd)
+{
+ int retval;
+ retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("end_state: %i", cmd->cmd.end_state->end_state);
+
+ if (cmd->cmd.end_state->end_state != TAP_INVALID)
+ ft2232_end_state(cmd->cmd.end_state->end_state);
+
+ return retval;
+}
+
+
+static int ft2232_execute_runtest(jtag_command_t *cmd)
+{
+ int retval;
+ int i;
+ int predicted_size = 0;
+ retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("runtest %i cycles, end in %i",
+ cmd->cmd.runtest->num_cycles,
+ 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_INVALID) && (cmd->cmd.runtest->end_state != TAP_IDLE) )
+ predicted_size += 3;
+ if ( (cmd->cmd.runtest->end_state == TAP_INVALID) && (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)
+ {
+ /* command "Clock Data to TMS/CS Pin (no Read)" */
+ BUFFER_ADD = 0x4b;
+ BUFFER_ADD = 0x6; /* scan 7 bits */
+
+ /* TMS data bits */
+ BUFFER_ADD = tap_get_tms_path(tap_get_state(), TAP_IDLE);
+ tap_set_state(TAP_IDLE);
+ require_send = 1;
+ }
+ i = cmd->cmd.runtest->num_cycles;
+ while (i > 0)
+ {
+ /* command "Clock Data to TMS/CS Pin (no Read)" */
+ BUFFER_ADD = 0x4b;
+
+ /* scan 7 bits */
+ BUFFER_ADD = (i > 7) ? 6 : (i - 1);
+
+ /* TMS data bits */
+ BUFFER_ADD = 0x0;
+ tap_set_state(TAP_IDLE);
+ i -= (i > 7) ? 7 : i;
+ /* LOG_DEBUG("added TMS scan (no read)"); */
+ }
+
+ if (cmd->cmd.runtest->end_state != TAP_INVALID)
+ ft2232_end_state(cmd->cmd.runtest->end_state);
+
+ if ( tap_get_state() != tap_get_end_state() )
+ {
+ /* command "Clock Data to TMS/CS Pin (no Read)" */
+ BUFFER_ADD = 0x4b;
+ /* scan 7 bit */
+ BUFFER_ADD = 0x6;
+ /* TMS data bits */
+ BUFFER_ADD = tap_get_tms_path( tap_get_state(), tap_get_end_state() );
+ tap_set_state( tap_get_end_state() );
+ /* LOG_DEBUG("added TMS scan (no read)"); */
+ }
+ 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 retval;
+ int predicted_size = 0;
+ 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;
+ }
+ if (cmd->cmd.statemove->end_state != TAP_INVALID)
+ ft2232_end_state(cmd->cmd.statemove->end_state);
+
+ /* command "Clock Data to TMS/CS Pin (no Read)" */
+ BUFFER_ADD = 0x4b;
+
+ BUFFER_ADD = 0x6; /* scan 7 bits */
+
+ /* TMS data bits */
+ BUFFER_ADD = tap_get_tms_path( tap_get_state(), tap_get_end_state() );
+ /* LOG_DEBUG("added TMS scan (no read)"); */
+ tap_set_state( tap_get_end_state() );
+ require_send = 1;
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG( "statemove: %s", tap_state_name( tap_get_end_state() ) );
+#endif
+
+ return retval;
+}
+
+static int ft2232_execute_pathmove(jtag_command_t *cmd)
+{
+ int retval;
+ int predicted_size = 0;
+ retval = ERROR_OK;
+
+ DEBUG_JTAG_IO("pathmove: %i states, end in %i",
+ cmd->cmd.pathmove->num_states,
+ cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+ /* only send the maximum buffer size that FT2232C can handle */
+ predicted_size = 3 * CEIL(cmd->cmd.pathmove->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(cmd->cmd.pathmove);
+ require_send = 1;
+#ifdef _DEBUG_JTAG_IO_
+ LOG_DEBUG( "pathmove: %i states, end in %s", cmd->cmd.pathmove->num_states,
+ tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]) );
+#endif
+ return retval;
+}
+
+static int ft2232_execute_scan(jtag_command_t *cmd)
+{
+ int retval;
+ u8* buffer;
+ int scan_size; /* size of IR or DR scan */
+ enum scan_type type;
+ int predicted_size = 0;
+ retval = ERROR_OK;
+
+ scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+ type = jtag_scan_type(cmd->cmd.scan);
+ 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 */
+ if (cmd->cmd.scan->end_state != TAP_INVALID)
+ 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); */
+ if (cmd->cmd.scan->end_state != TAP_INVALID)
+ 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;
+ }
+
+ if ( (cmd->cmd.reset->trst == 1) || ( cmd->cmd.reset->srst && (jtag_reset_config & RESET_SRST_PULLS_TRST) ) )
+ {
+ tap_set_state(TAP_RESET);
+ }
+ 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_END_STATE: retval = ft2232_execute_end_state(cmd); break;
+ 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;
+
+ /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check
+ * that wasn't handled by a caller-provided error handler
+ */
+ retval = ERROR_OK;
+
+ ft2232_buffer_size = 0;
+ ft2232_expect_read = 0;
+
+ /* blink, if the current layout has that feature */
+ if (layout->blink)
+ layout->blink();
+
+ while (cmd)
+ {
+ if (ft2232_execute_command(cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ /* Start reading input before FT2232 TX buffer fills up */
+ cmd = cmd->next;
+ if (ft2232_expect_read > 256)
+ {
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+ first_unsent = cmd;
+ }
+ }
+
+ if (require_send > 0)
+ if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+ retval = ERROR_JTAG_QUEUE_FAILED;
+
+ return retval;
+}
+
+
+#if BUILD_FT2232_FTD2XX == 1
+static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int* try_more)
+{
+ FT_STATUS status;
+ DWORD openex_flags = 0;
+ char* openex_string = NULL;
+ u8 latency_timer;
+
+ LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", ft2232_layout, vid, pid);
+
+#if IS_WIN32 == 0
+ /* Add non-standard Vid/Pid to the linux driver */
+ if ( ( status = FT_SetVIDPID(vid, pid) ) != FT_OK )
+ {
+ LOG_WARNING("couldn't add %4.4x:%4.4x", vid, pid);
+ }
+#endif
+
+ if (ft2232_device_desc && ft2232_serial)
+ {
+ LOG_WARNING("can't open by device description and serial number, giving precedence to serial");
+ ft2232_device_desc = NULL;
+ }
+
+ if (ft2232_device_desc)
+ {
+ openex_string = ft2232_device_desc;
+ openex_flags = FT_OPEN_BY_DESCRIPTION;
+ }
+ else if (ft2232_serial)
+ {
+ openex_string = ft2232_serial;
+ openex_flags = FT_OPEN_BY_SERIAL_NUMBER;
+ }
+ else
+ {
+ LOG_ERROR("neither device description nor serial number specified");
+ LOG_ERROR("please add \"ft2232_device_desc <string>\" or \"ft2232_serial <string>\" to your .cfg file");
+
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ status = FT_OpenEx(openex_string, openex_flags, &ftdih);
+ if( status != FT_OK ){
+ // under Win32, the FTD2XX driver appends an "A" to the end
+ // of the description, if we tried by the desc, then
+ // try by the alternate "A" description.
+ if( openex_string == ft2232_device_desc ){
+ // Try the alternate method.
+ openex_string = ft2232_device_desc_A;
+ status = FT_OpenEx(openex_string, openex_flags, &ftdih);
+ if( status == FT_OK ){
+ // yea, the "alternate" method worked!
+ } else {
+ // drat, give the user a meaningfull message.
+ // telling the use we tried *BOTH* methods.
+ LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'\n",
+ ft2232_device_desc,
+ ft2232_device_desc_A );
+ }
+ }
+ }
+
+ if ( status != FT_OK )
+ {
+ DWORD num_devices;
+
+ if (more)
+ {
+ LOG_WARNING("unable to open ftdi device (trying more): %lu", status);
+ *try_more = 1;
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ LOG_ERROR("unable to open ftdi device: %lu", status);
+ status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
+ if (status == FT_OK)
+ {
+ char** desc_array = malloc( sizeof(char*) * (num_devices + 1) );
+ u32 i;
+
+ for (i = 0; i < num_devices; i++)
+ desc_array[i] = malloc(64);
+
+ desc_array[num_devices] = NULL;
+
+ status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags);
+
+ if (status == FT_OK)
+ {
+ LOG_ERROR("ListDevices: %lu\n", num_devices);
+ for (i = 0; i < num_devices; i++)
+ LOG_ERROR("%i: \"%s\"", i, desc_array[i]);
+ }
+
+ for (i = 0; i < num_devices; i++)
+ free(desc_array[i]);
+
+ free(desc_array);
+ }
+ else
+ {
+ LOG_ERROR("ListDevices: NONE\n");
+ }
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if ( ( status = FT_SetLatencyTimer(ftdih, ft2232_latency) ) != FT_OK )
+ {
+ LOG_ERROR("unable to set latency timer: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if ( ( status = FT_GetLatencyTimer(ftdih, &latency_timer) ) != FT_OK )
+ {
+ LOG_ERROR("unable to get latency timer: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ else
+ {
+ LOG_DEBUG("current latency timer: %i", latency_timer);
+ }
+
+ if ( ( status = FT_SetTimeouts(ftdih, 5000, 5000) ) != FT_OK )
+ {
+ LOG_ERROR("unable to set timeouts: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if ( ( status = FT_SetBitMode(ftdih, 0x0b, 2) ) != FT_OK )
+ {
+ LOG_ERROR("unable to enable bit i/o mode: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
+
+static int ft2232_purge_ftd2xx(void)
+{
+ FT_STATUS status;
+
+ if ( ( status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX) ) != FT_OK )
+ {
+ LOG_ERROR("error purging ftd2xx device: %lu", status);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
+
+#endif /* BUILD_FT2232_FTD2XX == 1 */
+
+#if BUILD_FT2232_LIBFTDI == 1
+static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int* try_more)
+{
+ u8 latency_timer;
+
+ LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)",
+ ft2232_layout, vid, pid);
+
+ if (ftdi_init(&ftdic) < 0)
+ return ERROR_JTAG_INIT_FAILED;
+
+ /* context, vendor id, product id */
+ if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc,
+ ft2232_serial) < 0)
+ {
+ if (more)
+ LOG_WARNING("unable to open ftdi device (trying more): %s",
+ ftdic.error_str);
+ else
+ LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
+ *try_more = 1;
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)
+ {
+ LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_usb_reset(&ftdic) < 0)
+ {
+ LOG_ERROR("unable to reset ftdi device");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0)
+ {
+ LOG_ERROR("unable to set latency timer");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
+ {
+ LOG_ERROR("unable to get latency timer");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+ else
+ {
+ LOG_DEBUG("current latency timer: %i", latency_timer);
+ }
+
+ ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */
+
+ return ERROR_OK;
+}
+
+
+static int ft2232_purge_libftdi(void)
+{
+ if (ftdi_usb_purge_buffers(&ftdic) < 0)
+ {
+ LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
+
+#endif /* BUILD_FT2232_LIBFTDI == 1 */
+
+static int ft2232_init(void)
+{
+ u8 buf[1];
+ int retval;
+ u32 bytes_written;
+ ft2232_layout_t* cur_layout = ft2232_layouts;
+ int i;
+
+ if ( (ft2232_layout == NULL) || (ft2232_layout[0] == 0) )
+ {
+ ft2232_layout = "usbjtag";
+ LOG_WARNING("No ft2232 layout specified, using default 'usbjtag'");
+ }
+
+ while (cur_layout->name)
+ {
+ if (strcmp(cur_layout->name, ft2232_layout) == 0)
+ {
+ layout = cur_layout;
+ break;
+ }
+ cur_layout++;
+ }
+
+ if (!layout)
+ {
+ LOG_ERROR("No matching layout found for %s", ft2232_layout);
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ for (i = 0; 1; i++)
+ {
+ /*
+ * "more indicates that there are more IDs to try, so we should
+ * not print an error for an ID mismatch (but for anything
+ * else, we should).
+ *
+ * try_more indicates that the error code returned indicates an
+ * ID mismatch (and nothing else) and that we should proceeed
+ * with the next ID pair.
+ */
+ int more = ft2232_vid[i + 1] || ft2232_pid[i + 1];
+ int try_more = 0;
+
+#if BUILD_FT2232_FTD2XX == 1
+ retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i],
+ more, &try_more);
+#elif BUILD_FT2232_LIBFTDI == 1
+ retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i],
+ more, &try_more);
+#endif
+ if (retval >= 0)
+ break;
+ if (!more || !try_more)
+ return retval;
+ }
+
+ ft2232_buffer_size = 0;
+ ft2232_buffer = malloc(FT2232_BUFFER_SIZE);
+
+ if (layout->init() != ERROR_OK)
+ return ERROR_JTAG_INIT_FAILED;
+
+ ft2232_speed(jtag_speed);
+
+ buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */
+ if ( ( ( retval = ft2232_write(buf, 1, &bytes_written) ) != ERROR_OK ) || (bytes_written != 1) )
+ {
+ LOG_ERROR("couldn't write to FT2232 to disable loopback");
+ return ERROR_JTAG_INIT_FAILED;