Change return value on error.
[openocd.git] / src / jtag / drivers / ft2232.c
index 82132d3b2d41159eb7974c370ce63a61a74752ff..4b9bdef7dd5ae789faa4796f38fda6412f19f3ce 100644 (file)
  * JTAG adapters based on the FT2232 full and high speed USB parts are
  * popular low cost JTAG debug solutions.  Many FT2232 based JTAG adapters
  * are discrete, but development boards may integrate them as alternatives
- * to more capable (and expensive) third party JTAG pods.  Since JTAG uses
- * only one of the two ports on these devices, on integrated boards the
- * second port often serves as a USB-to-serial adapter for the target's
- * console UART even when the JTAG port is not in use.  (Systems which
- * support ARM's SWD in addition to JTAG, or instead of it, may use that
- * second port for reading SWV trace data.)
+ * to more capable (and expensive) third party JTAG pods.
+ *
+ * JTAG uses only one of the two communications channels ("MPSSE engines")
+ * on these devices.  Adapters based on FT4232 parts have four ports/channels
+ * (A/B/C/D), instead of just two (A/B).
+ *
+ * Especially on development boards integrating one of these chips (as
+ * opposed to discrete pods/dongles), the additional channels can be used
+ * for a variety of purposes, but OpenOCD only uses one channel at a time.
+ *
+ *  - As a USB-to-serial adapter for the target's console UART ...
+ *    which may be able to support ROM boot loaders that load initial
+ *    firmware images to flash (or SRAM).
+ *
+ *  - On systems which support ARM's SWD in addition to JTAG, or instead
+ *    of it, that second port can be used for reading SWV/SWO trace data.
+ *
+ *  - Additional JTAG links, e.g. to a CPLD or * FPGA.
  *
  * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG
  * request/response interactions involve round trips over the USB link.
@@ -69,6 +81,7 @@
 
 /* project specific includes */
 #include <jtag/interface.h>
+#include <transport/transport.h>
 #include <helper/time_support.h>
 
 #if IS_CYGWIN == 1
 /* FT2232 access library includes */
 #if BUILD_FT2232_FTD2XX == 1
 #include <ftd2xx.h>
+#include "ftd2xx_common.h"
+
+enum ftdi_interface
+{
+    INTERFACE_ANY = 0,
+    INTERFACE_A   = 1,
+    INTERFACE_B   = 2,
+    INTERFACE_C   = 3,
+    INTERFACE_D   = 4
+};
+
 #elif BUILD_FT2232_LIBFTDI == 1
 #include <ftdi.h>
 #endif
@@ -131,7 +155,6 @@ static int ft2232_stableclocks(int num_cycles, struct jtag_command* cmd);
 static char *       ft2232_device_desc_A = NULL;
 static char*        ft2232_device_desc = NULL;
 static char*        ft2232_serial  = NULL;
-static char*        ft2232_layout  = NULL;
 static uint8_t         ft2232_latency = 2;
 static unsigned                ft2232_max_tck = FTDI_2232C_MAX_TCK;
 
@@ -145,13 +168,18 @@ struct ft2232_layout {
        int (*init)(void);
        void (*reset)(int trst, int srst);
        void (*blink)(void);
+       int channel;
 };
 
 /* init procedures for supported layouts */
 static int usbjtag_init(void);
 static int jtagkey_init(void);
+static int lm3s811_jtag_init(void);
+static int icdi_jtag_init(void);
 static int olimex_jtag_init(void);
-static int flyswatter_init(void);
+static int flyswatter1_init(void);
+static int flyswatter2_init(void);
+static int minimodule_init(void);
 static int turtle_init(void);
 static int comstick_init(void);
 static int stm32stick_init(void);
@@ -159,14 +187,21 @@ static int axm0432_jtag_init(void);
 static int sheevaplug_init(void);
 static int icebear_jtag_init(void);
 static int cortino_jtag_init(void);
+static int signalyzer_init(void);
 static int signalyzer_h_init(void);
 static int ktlink_init(void);
+static int redbee_init(void);
+static int lisa_l_init(void);
+static int flossjtag_init(void);
+static int xds100v2_init(void);
 
 /* reset procedures for supported layouts */
-static void usbjtag_reset(int trst, int srst);
+static void ftx23_reset(int trst, int srst);
 static void jtagkey_reset(int trst, int srst);
 static void olimex_jtag_reset(int trst, int srst);
-static void flyswatter_reset(int trst, int srst);
+static void flyswatter1_reset(int trst, int srst);
+static void flyswatter2_reset(int trst, int srst);
+static void minimodule_reset(int trst, int srst);
 static void turtle_reset(int trst, int srst);
 static void comstick_reset(int trst, int srst);
 static void stm32stick_reset(int trst, int srst);
@@ -175,43 +210,158 @@ static void sheevaplug_reset(int trst, int srst);
 static void icebear_jtag_reset(int trst, int srst);
 static void signalyzer_h_reset(int trst, int srst);
 static void ktlink_reset(int trst, int srst);
+static void redbee_reset(int trst, int srst);
+static void xds100v2_reset(int trst, int srst);
 
 /* blink procedures for layouts that support a blinking led */
 static void olimex_jtag_blink(void);
-static void flyswatter_jtag_blink(void);
+static void flyswatter1_jtag_blink(void);
+static void flyswatter2_jtag_blink(void);
 static void turtle_jtag_blink(void);
 static void signalyzer_h_blink(void);
 static void ktlink_blink(void);
+static void lisa_l_blink(void);
+static void flossjtag_blink(void);
+
+/* common transport support options */
+
+//static const char *jtag_and_swd[] = { "jtag", "swd", NULL };
 
 static const struct ft2232_layout  ft2232_layouts[] =
 {
-       { "usbjtag",              usbjtag_init,              usbjtag_reset,      NULL                    },
-       { "jtagkey",              jtagkey_init,              jtagkey_reset,      NULL                    },
-       { "jtagkey_prototype_v1", jtagkey_init,              jtagkey_reset,      NULL                    },
-       { "oocdlink",             jtagkey_init,              jtagkey_reset,      NULL                    },
-       { "signalyzer",           usbjtag_init,              usbjtag_reset,      NULL                    },
-       { "evb_lm3s811",          usbjtag_init,              usbjtag_reset,      NULL                    },
-       { "luminary_icdi",        usbjtag_init,              usbjtag_reset,      NULL                    },
-       { "olimex-jtag",          olimex_jtag_init,          olimex_jtag_reset,  olimex_jtag_blink       },
-       { "flyswatter",           flyswatter_init,           flyswatter_reset,   flyswatter_jtag_blink   },
-       { "turtelizer2",          turtle_init,               turtle_reset,       turtle_jtag_blink       },
-       { "comstick",             comstick_init,             comstick_reset,     NULL                    },
-       { "stm32stick",           stm32stick_init,           stm32stick_reset,   NULL                    },
-       { "axm0432_jtag",         axm0432_jtag_init,         axm0432_jtag_reset, NULL                    },
-       { "sheevaplug",           sheevaplug_init,           sheevaplug_reset,   NULL                    },
-       { "icebear",              icebear_jtag_init,         icebear_jtag_reset, NULL                    },
-       { "cortino",              cortino_jtag_init,         comstick_reset, NULL                        },
-       { "signalyzer-h",         signalyzer_h_init,         signalyzer_h_reset, signalyzer_h_blink      },
-       { "ktlink",               ktlink_init,               ktlink_reset,       ktlink_blink            },
-       { NULL,                   NULL,                      NULL,               NULL                    },
+       { .name = "usbjtag",
+               .init = usbjtag_init,
+               .reset = ftx23_reset,
+       },
+       { .name = "jtagkey",
+               .init = jtagkey_init,
+               .reset = jtagkey_reset,
+       },
+       { .name = "jtagkey_prototype_v1",
+               .init = jtagkey_init,
+               .reset = jtagkey_reset,
+       },
+       { .name = "oocdlink",
+               .init = jtagkey_init,
+               .reset = jtagkey_reset,
+       },
+       { .name = "signalyzer",
+               .init = signalyzer_init,
+               .reset = ftx23_reset,
+       },
+       { .name = "evb_lm3s811",
+               .init = lm3s811_jtag_init,
+               .reset = ftx23_reset,
+       },
+       { .name = "luminary_icdi",
+               .init = icdi_jtag_init,
+               .reset = ftx23_reset,
+       },
+       { .name = "olimex-jtag",
+               .init = olimex_jtag_init,
+               .reset = olimex_jtag_reset,
+               .blink = olimex_jtag_blink
+       },
+       { .name = "flyswatter",
+               .init = flyswatter1_init,
+               .reset = flyswatter1_reset,
+               .blink = flyswatter1_jtag_blink
+       },
+       { .name = "flyswatter2",
+               .init = flyswatter2_init,
+               .reset = flyswatter2_reset,
+               .blink = flyswatter2_jtag_blink
+       },
+       { .name = "minimodule",
+               .init = minimodule_init,
+               .reset = minimodule_reset,
+       },
+       { .name = "turtelizer2",
+               .init = turtle_init,
+               .reset = turtle_reset,
+               .blink = turtle_jtag_blink
+       },
+       { .name = "comstick",
+               .init = comstick_init,
+               .reset = comstick_reset,
+       },
+       { .name = "stm32stick",
+               .init = stm32stick_init,
+               .reset = stm32stick_reset,
+       },
+       { .name = "axm0432_jtag",
+               .init = axm0432_jtag_init,
+               .reset = axm0432_jtag_reset,
+       },
+       { .name = "sheevaplug",
+               .init = sheevaplug_init,
+               .reset = sheevaplug_reset,
+       },
+       { .name = "icebear",
+               .init = icebear_jtag_init,
+               .reset = icebear_jtag_reset,
+       },
+       { .name = "cortino",
+               .init = cortino_jtag_init,
+               .reset = comstick_reset,
+       },
+       { .name = "signalyzer-h",
+               .init = signalyzer_h_init,
+               .reset = signalyzer_h_reset,
+               .blink = signalyzer_h_blink
+       },
+       { .name = "ktlink",
+               .init = ktlink_init,
+               .reset = ktlink_reset,
+               .blink = ktlink_blink
+       },
+       { .name = "redbee-econotag",
+               .init = redbee_init,
+               .reset = redbee_reset,
+       },
+       { .name = "redbee-usb",
+               .init = redbee_init,
+               .reset = redbee_reset,
+               .channel = INTERFACE_B,
+       },
+       { .name = "lisa-l",
+               .init = lisa_l_init,
+               .reset = ftx23_reset,
+               .blink = lisa_l_blink,
+               .channel = INTERFACE_B,
+       },
+       { .name = "flossjtag",
+               .init = flossjtag_init,
+               .reset = ftx23_reset,
+               .blink = flossjtag_blink,
+       },
+       { .name = "xds100v2",
+               .init = xds100v2_init,
+               .reset = xds100v2_reset,
+       },
+       { .name = NULL, /* END OF TABLE */ },
 };
 
-static uint8_t                  nTRST, nTRSTnOE, nSRST, nSRSTnOE;
+/* bitmask used to drive nTRST; usually a GPIOLx signal */
+static uint8_t                  nTRST;
+static uint8_t                  nTRSTnOE;
+/* bitmask used to drive nSRST; usually a GPIOLx signal */
+static uint8_t                  nSRST;
+static uint8_t                  nSRSTnOE;
 
+/** the layout being used with this debug session */
 static const struct ft2232_layout *layout;
+
+/** default bitmask values driven on DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */
 static uint8_t                  low_output     = 0x0;
+
+/* note that direction bit == 1 means that signal is an output */
+
+/** default direction bitmask for DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */
 static uint8_t                  low_direction  = 0x0;
+/** default value bitmask for CBUS GPIOH(0..4) */
 static uint8_t                  high_output    = 0x0;
+/** default direction bitmask for CBUS GPIOH(0..4) */
 static uint8_t                  high_direction = 0x0;
 
 #if BUILD_FT2232_FTD2XX == 1
@@ -238,6 +388,12 @@ static int             require_send;
        a comment would have been nice.
 */
 
+#if BUILD_FT2232_FTD2XX == 1
+#define FT2232_BUFFER_READ_QUEUE_SIZE  (64*64)
+#else
+#define FT2232_BUFFER_READ_QUEUE_SIZE  (64*4)
+#endif
+
 #define FT2232_BUFFER_SIZE 131072
 
 static uint8_t*             ft2232_buffer = NULL;
@@ -364,17 +520,16 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written)
 {
 #if BUILD_FT2232_FTD2XX == 1
        FT_STATUS status;
-       DWORD dw_bytes_written;
+       DWORD dw_bytes_written = 0;
        if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
        {
                *bytes_written = dw_bytes_written;
-               LOG_ERROR("FT_Write returned: %lu", status);
+               LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
        else
        {
                *bytes_written = dw_bytes_written;
-               return ERROR_OK;
        }
 #elif BUILD_FT2232_LIBFTDI == 1
        int retval;
@@ -387,9 +542,15 @@ static int ft2232_write(uint8_t* buf, int size, uint32_t* bytes_written)
        else
        {
                *bytes_written = retval;
-               return ERROR_OK;
        }
 #endif
+
+       if (*bytes_written != (uint32_t)size)
+       {
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
 }
 
 static int ft2232_read(uint8_t* buf, uint32_t size, uint32_t* bytes_read)
@@ -406,7 +567,7 @@ static int ft2232_read(uint8_t* buf, uint32_t size, uint32_t* bytes_read)
                                          *bytes_read, &dw_bytes_read)) != FT_OK)
                {
                        *bytes_read = 0;
-                       LOG_ERROR("FT_Read returned: %lu", status);
+                       LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
                *bytes_read += dw_bytes_read;
@@ -463,8 +624,9 @@ static int ft2232h_ft4232h_adaptive_clocking(bool enable)
        LOG_DEBUG("%2.2x", buf);
 
        uint32_t bytes_written;
-       int retval = ft2232_write(&buf, 1, &bytes_written);
-       if ((ERROR_OK != retval) || (bytes_written != 1))
+       int retval;
+
+       if ((retval = ft2232_write(&buf, sizeof(buf), &bytes_written)) != ERROR_OK)
        {
                LOG_ERROR("couldn't write command to %s adaptive clocking"
                        , enable ? "enable" : "disable");
@@ -483,8 +645,8 @@ static int ft2232h_ft4232h_clk_divide_by_5(bool enable)
 {
        uint32_t bytes_written;
        uint8_t buf = enable ?  0x8b : 0x8a;
-       int retval = ft2232_write(&buf, 1, &bytes_written);
-       if ((ERROR_OK != retval) || (bytes_written != 1))
+
+       if (ft2232_write(&buf, sizeof(buf), &bytes_written) != ERROR_OK)
        {
                LOG_ERROR("couldn't write command to %s clk divide by 5"
                        , enable ? "enable" : "disable");
@@ -521,7 +683,7 @@ static int ft2232_speed(int speed)
        buf[2] = (speed >> 8) & 0xff;   /* valueH */
 
        LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-       if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if ((retval = ft2232_write(buf, sizeof(buf), &bytes_written)) != ERROR_OK)
        {
                LOG_ERROR("couldn't set FT2232 TCK speed");
                return retval;
@@ -631,7 +793,7 @@ static void ft2232_debug_dump_buffer(void)
 
        for (i = 0; i < ft2232_buffer_size; i++)
        {
-               line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]);
+               line_p += snprintf(line_p, sizeof(line) - (line_p - line), "%2.2x ", ft2232_buffer[i]);
                if (i % 16 == 15)
                {
                        LOG_DEBUG("%s", line);
@@ -1191,7 +1353,6 @@ static int ft2232_large_scan(struct scan_command* cmd, enum scan_type type, uint
                LOG_DEBUG("thisrun_read: %i, bytes_read: %i",
                          thisrun_read,
                          (int)bytes_read);
-               receive_pointer += bytes_read;
        }
 
        return ERROR_OK;
@@ -1246,7 +1407,8 @@ static int ft2232_predict_scan_in(int scan_size, enum scan_type type)
        return predicted_size;
 }
 
-static void usbjtag_reset(int trst, int srst)
+/* semi-generic FT2232/FT4232 reset code */
+static void ftx23_reset(int trst, int srst)
 {
        enum reset_types jtag_reset_config = jtag_get_reset_config();
        if (trst == 1)
@@ -1417,6 +1579,34 @@ static void flyswatter_reset(int trst, int srst)
        LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction);
 }
 
+static void flyswatter1_reset(int trst, int srst)
+{
+       flyswatter_reset(trst, srst);
+}
+
+static void flyswatter2_reset(int trst, int srst)
+{
+       flyswatter_reset(trst, !srst);
+}
+
+static void minimodule_reset(int trst, int srst)
+{
+       if (srst == 1)
+       {
+               low_output &= ~nSRST;
+       }
+       else if (srst == 0)
+       {
+               low_output |= nSRST;
+       }
+
+       /* command "set data bits low byte" */
+       buffer_write(0x80);
+       buffer_write(low_output);
+       buffer_write(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;
@@ -1517,6 +1707,66 @@ static void sheevaplug_reset(int trst, int srst)
        LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
 }
 
+static void redbee_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               tap_set_state(TAP_RESET);
+               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 low byte" */
+       buffer_write(0x82);
+       buffer_write(high_output);
+       buffer_write(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 xds100v2_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               tap_set_state(TAP_RESET);
+               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 low byte" */
+       buffer_write(0x82);
+       buffer_write(high_output);
+       buffer_write(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_runtest(struct jtag_command *cmd)
 {
        int retval;
@@ -1618,6 +1868,72 @@ static int ft2232_execute_statemove(struct jtag_command *cmd)
        return retval;
 }
 
+/**
+ * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG
+ * (or SWD) state machine.
+ */
+static int ft2232_execute_tms(struct jtag_command *cmd)
+{
+       int             retval = ERROR_OK;
+       unsigned        num_bits = cmd->cmd.tms->num_bits;
+       const uint8_t   *bits = cmd->cmd.tms->bits;
+       unsigned        count;
+
+       DEBUG_JTAG_IO("TMS: %d bits", num_bits);
+
+       /* only send the maximum buffer size that FT2232C can handle */
+       count = 3 * DIV_ROUND_UP(num_bits, 4);
+       if (ft2232_buffer_size + 3*count + 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;
+       }
+
+       /* Shift out in batches of at most 6 bits; there's a report of an
+        * FT2232 bug in this area, where shifting exactly 7 bits can make
+        * problems with TMS signaling for the last clock cycle:
+        *
+        *    http://developer.intra2net.com/mailarchive/html/
+        *              libftdi/2009/msg00292.html
+        *
+        * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)"
+        *
+        * Note that pathmoves in JTAG are not often seven bits, so that
+        * isn't a particularly likely situation outside of "special"
+        * signaling such as switching between JTAG and SWD modes.
+        */
+       while (num_bits) {
+               if (num_bits <= 6) {
+                       buffer_write(0x4b);
+                       buffer_write(num_bits - 1);
+                       buffer_write(*bits & 0x3f);
+                       break;
+               }
+
+               /* Yes, this is lazy ... we COULD shift out more data
+                * bits per operation, but doing it in nybbles is easy
+                */
+               buffer_write(0x4b);
+               buffer_write(3);
+               buffer_write(*bits & 0xf);
+               num_bits -= 4;
+
+               count  = (num_bits > 4) ? 4 : num_bits;
+
+               buffer_write(0x4b);
+               buffer_write(count - 1);
+               buffer_write((*bits >> 4) & 0xf);
+               num_bits -= count;
+
+               bits++;
+       }
+
+       require_send = 1;
+       return retval;
+}
+
 static int ft2232_execute_pathmove(struct jtag_command *cmd)
 {
        int     predicted_size = 0;
@@ -1770,20 +2086,23 @@ static int ft2232_execute_stableclocks(struct jtag_command *cmd)
 static int ft2232_execute_command(struct jtag_command *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_TLR_RESET: 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;
+       case JTAG_TMS:
+               retval = ft2232_execute_tms(cmd);
+               break;
        default:
                LOG_ERROR("BUG: unknown JTAG command type encountered");
-               exit(-1);
+               retval = ERROR_JTAG_QUEUE_FAILED;
+               break;
        }
        return retval;
 }
@@ -1810,12 +2129,20 @@ static int ft2232_execute_queue(void)
 
        while (cmd)
        {
+               /* fill the write buffer with the desired command */
                if (ft2232_execute_command(cmd) != ERROR_OK)
                        retval = ERROR_JTAG_QUEUE_FAILED;
-               /* Start reading input before FT2232 TX buffer fills up */
+               /* Start reading input before FT2232 TX buffer fills up.
+                * Sometimes this happens because we don't know the
+                * length of the last command before we execute it. So
+                * we simple inform the user.
+                */
                cmd = cmd->next;
-               if (ft2232_expect_read > 256)
+
+               if (ft2232_expect_read >= FT2232_BUFFER_READ_QUEUE_SIZE )
                {
+                       if (ft2232_expect_read > (FT2232_BUFFER_READ_QUEUE_SIZE+1) )
+                               LOG_DEBUG("read buffer size looks too high %d/%d",ft2232_expect_read,(FT2232_BUFFER_READ_QUEUE_SIZE+1));
                        if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
                                retval = ERROR_JTAG_QUEUE_FAILED;
                        first_unsent = cmd;
@@ -1840,7 +2167,12 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
        char*   openex_string = NULL;
        uint8_t latency_timer;
 
-       LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", ft2232_layout, vid, pid);
+       if (layout == NULL) {
+               LOG_WARNING("No ft2232 layout specified'");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", layout->name, vid, pid);
 
 #if IS_WIN32 == 0
        /* Add non-standard Vid/Pid to the linux driver */
@@ -1888,7 +2220,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
                        } 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",
+                               LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'",
                                                        ft2232_device_desc,
                                                        ft2232_device_desc_A);
                        }
@@ -1901,11 +2233,13 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
 
                if (more)
                {
-                       LOG_WARNING("unable to open ftdi device (trying more): %lu", status);
+                       LOG_WARNING("unable to open ftdi device (trying more): %s",
+                                       ftd2xx_status_string(status));
                        *try_more = 1;
                        return ERROR_JTAG_INIT_FAILED;
                }
-               LOG_ERROR("unable to open ftdi device: %lu", status);
+               LOG_ERROR("unable to open ftdi device: %s",
+                               ftd2xx_status_string(status));
                status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
                if (status == FT_OK)
                {
@@ -1921,7 +2255,7 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
 
                        if (status == FT_OK)
                        {
-                               LOG_ERROR("ListDevices: %lu\n", num_devices);
+                               LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices);
                                for (i = 0; i < num_devices; i++)
                                        LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]);
                        }
@@ -1933,21 +2267,35 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
                }
                else
                {
-                       LOG_ERROR("ListDevices: NONE\n");
+                       LOG_ERROR("ListDevices: NONE");
                }
                return ERROR_JTAG_INIT_FAILED;
        }
 
        if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK)
        {
-               LOG_ERROR("unable to set latency timer: %lu", status);
+               LOG_ERROR("unable to set latency timer: %s",
+                               ftd2xx_status_string(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;
+               /* ftd2xx 1.04 (linux) has a bug when calling FT_GetLatencyTimer
+                * so ignore errors if using this driver version */
+               DWORD dw_version;
+
+               status = FT_GetDriverVersion(ftdih, &dw_version);
+               LOG_ERROR("unable to get latency timer: %s",
+                               ftd2xx_status_string(status));
+
+               if ((status == FT_OK) && (dw_version == 0x10004)) {
+                       LOG_ERROR("ftd2xx 1.04 detected - this has known issues " \
+                                       "with FT_GetLatencyTimer, upgrade to a newer version");
+               }
+               else {
+                       return ERROR_JTAG_INIT_FAILED;
+               }
        }
        else
        {
@@ -1956,19 +2304,22 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
 
        if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)
        {
-               LOG_ERROR("unable to set timeouts: %lu", status);
+               LOG_ERROR("unable to set timeouts: %s",
+                               ftd2xx_status_string(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);
+               LOG_ERROR("unable to enable bit i/o mode: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_INIT_FAILED;
        }
 
        if ((status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID, SerialNumber, Description, NULL)) != FT_OK)
        {
-               LOG_ERROR("unable to get FT_GetDeviceInfo: %lu", status);
+               LOG_ERROR("unable to get FT_GetDeviceInfo: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_INIT_FAILED;
        }
        else
@@ -1978,8 +2329,8 @@ static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int* try_mor
                unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1;
                unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types)
                        ? ftdi_device : FT_DEVICE_UNKNOWN;
-               LOG_INFO("device: %lu \"%s\"", ftdi_device, type_str[type_index]);
-               LOG_INFO("deviceID: %lu", deviceID);
+               LOG_INFO("device: %" PRIu32 " \"%s\"", (uint32_t)ftdi_device, type_str[type_index]);
+               LOG_INFO("deviceID: %" PRIu32, (uint32_t)deviceID);
                LOG_INFO("SerialNumber: %s", SerialNumber);
                LOG_INFO("Description: %s", Description);
        }
@@ -1993,7 +2344,8 @@ static int ft2232_purge_ftd2xx(void)
 
        if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
        {
-               LOG_ERROR("error purging ftd2xx device: %lu", status);
+               LOG_ERROR("error purging ftd2xx device: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_INIT_FAILED;
        }
 
@@ -2003,17 +2355,25 @@ static int ft2232_purge_ftd2xx(void)
 #endif /* BUILD_FT2232_FTD2XX == 1 */
 
 #if BUILD_FT2232_LIBFTDI == 1
-static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int* try_more)
+static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int* try_more, int channel)
 {
        uint8_t latency_timer;
 
+       if (layout == NULL) {
+               LOG_WARNING("No ft2232 layout specified'");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
        LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)",
-                       ft2232_layout, vid, pid);
+                       layout->name, vid, pid);
 
        if (ftdi_init(&ftdic) < 0)
                return ERROR_JTAG_INIT_FAILED;
 
-       if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)
+       /* default to INTERFACE_A */
+       if(channel == INTERFACE_ANY) { channel = INTERFACE_A; }
+
+       if (ftdi_set_interface(&ftdic, channel) < 0)
        {
                LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);
                return ERROR_JTAG_INIT_FAILED;
@@ -2080,13 +2440,51 @@ static int ft2232_purge_libftdi(void)
 
 #endif /* BUILD_FT2232_LIBFTDI == 1 */
 
+static int ft2232_set_data_bits_low_byte( uint8_t value, uint8_t direction )
+{
+       uint8_t  buf[3];
+       uint32_t bytes_written;
+
+       buf[0] = 0x80;          /* command "set data bits low byte" */
+       buf[1] = value;         /* value */
+       buf[2] = direction;     /* direction */
+
+       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+
+       if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize data bits low byte");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int ft2232_set_data_bits_high_byte( uint8_t value, uint8_t direction )
+{
+       uint8_t  buf[3];
+       uint32_t bytes_written;
+
+       buf[0] = 0x82;          /* command "set data bits high byte" */
+       buf[1] = value;         /* value */
+       buf[2] = direction;     /* direction */
+
+       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+
+       if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize data bits high byte");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
 static int ft2232_init(void)
 {
        uint8_t  buf[1];
        int retval;
        uint32_t bytes_written;
-       const struct ft2232_layout* cur_layout = ft2232_layouts;
-       int i;
 
        if (tap_get_tms_path_len(TAP_IRPAUSE,TAP_IRPAUSE) == 7)
        {
@@ -2097,29 +2495,12 @@ static int ft2232_init(void)
                LOG_DEBUG("ft2232 interface using shortest path jtag state transitions");
 
        }
-       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);
+       if (layout == NULL) {
+               LOG_WARNING("No ft2232 layout specified'");
                return ERROR_JTAG_INIT_FAILED;
        }
 
-       for (i = 0; 1; i++)
+       for (int i = 0; 1; i++)
        {
                /*
                 * "more indicates that there are more IDs to try, so we should
@@ -2138,7 +2519,7 @@ static int ft2232_init(void)
                                more, &try_more);
 #elif BUILD_FT2232_LIBFTDI == 1
                retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i],
-                               more, &try_more);
+                                            more, &try_more, layout->channel);
 #endif
                if (retval >= 0)
                        break;
@@ -2166,10 +2547,8 @@ static int ft2232_init(void)
                        return ERROR_JTAG_INIT_FAILED;
        }
 
-       ft2232_speed(jtag_get_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))
+       if ((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK)
        {
                LOG_ERROR("couldn't write to FT2232 to disable loopback");
                return ERROR_JTAG_INIT_FAILED;
@@ -2184,60 +2563,21 @@ static int ft2232_init(void)
        return ERROR_OK;
 }
 
-static int usbjtag_init(void)
+/** Updates defaults for DBUS signals:  the four JTAG signals
+ * (TCK, TDI, TDO, TMS) and * the four GPIOL signals.
+ */
+static inline void ftx232_dbus_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x0b;
+}
 
-       if (strcmp(ft2232_layout, "usbjtag") == 0)
-       {
-               nTRST    = 0x10;
-               nTRSTnOE = 0x10;
-               nSRST    = 0x40;
-               nSRSTnOE = 0x40;
-       }
-       else if (strcmp(ft2232_layout, "signalyzer") == 0)
-       {
-               nTRST    = 0x10;
-               nTRSTnOE = 0x10;
-               nSRST    = 0x20;
-               nSRSTnOE = 0x20;
-       }
-       else if (strcmp(ft2232_layout, "evb_lm3s811") == 0)
-       {
-               /* There are multiple revisions of LM3S811 eval boards:
-                * - Rev B (and older?) boards have no SWO trace support.
-                * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN;
-                *   they should use the "luminary_icdi" layout instead.
-                */
-               nTRST = 0x0;
-               nTRSTnOE = 0x00;
-               nSRST = 0x20;
-               nSRSTnOE = 0x20;
-               low_output    = 0x88;
-               low_direction = 0x8b;
-       }
-       else if (strcmp(ft2232_layout, "luminary_icdi") == 0)
-       {
-               /* Most Luminary eval boards support SWO trace output,
-                * and should use this "luminary_icdi" layout.
-                */
-               nTRST = 0x0;
-               nTRSTnOE = 0x00;
-               nSRST = 0x20;
-               nSRSTnOE = 0x20;
-               low_output    = 0x88;
-               low_direction = 0xcb;
-       }
-       else
-       {
-               LOG_ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout);
-               return ERROR_JTAG_INIT_FAILED;
-       }
-
+/** Initializes DBUS signals:  the four JTAG signals (TCK, TDI, TDO, TMS),
+ * the four GPIOL signals.  Initialization covers value and direction,
+ * as customized for each layout.
+ */
+static int ftx232_dbus_write(void)
+{
        enum reset_types jtag_reset_config = jtag_get_reset_config();
        if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
        {
@@ -2262,35 +2602,111 @@ static int usbjtag_init(void)
        }
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, xRST high) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
-               LOG_ERROR("couldn't initialize FT2232 with 'USBJTAG' layout");
+               LOG_ERROR("couldn't initialize FT2232 DBUS");
                return ERROR_JTAG_INIT_FAILED;
        }
 
        return ERROR_OK;
 }
 
-static int axm0432_jtag_init(void)
+static int usbjtag_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
+       /*
+        * NOTE:  This is now _specific_ to the "usbjtag" layout.
+        * Don't try cram any more layouts into this.
+        */
+       ftx232_dbus_init();
+
+       nTRST    = 0x10;
+       nTRSTnOE = 0x10;
+       nSRST    = 0x40;
+       nSRSTnOE = 0x40;
 
+       return ftx232_dbus_write();
+}
+
+static int lm3s811_jtag_init(void)
+{
+       ftx232_dbus_init();
+
+       /* There are multiple revisions of LM3S811 eval boards:
+        * - Rev B (and older?) boards have no SWO trace support.
+        * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN;
+        *   they should use the "luminary_icdi" layout instead.
+        */
+       nTRST = 0x0;
+       nTRSTnOE = 0x00;
+       nSRST = 0x20;
+       nSRSTnOE = 0x20;
+       low_output    = 0x88;
+       low_direction = 0x8b;
+
+       return ftx232_dbus_write();
+}
+
+static int icdi_jtag_init(void)
+{
+       ftx232_dbus_init();
+
+       /* Most Luminary eval boards support SWO trace output,
+        * and should use this "luminary_icdi" layout.
+        *
+        * ADBUS 0..3 are used for JTAG as usual.  GPIOs are used
+        * to switch between JTAG and SWD, or switch the ft2232 UART
+        * on the second MPSSE channel/interface (BDBUS)
+        * between (i) the stellaris UART (on Luminary boards)
+        * or (ii) SWO trace data (generic).
+        *
+        * We come up in JTAG mode and may switch to SWD later (with
+        * SWO/trace option if SWD is active).
+        *
+        * DBUS == GPIO-Lx
+        * CBUS == GPIO-Hx
+        */
+
+
+#define ICDI_JTAG_EN (1 << 7)          /* ADBUS 7 (a.k.a. DBGMOD) */
+#define ICDI_DBG_ENn (1 << 6)          /* ADBUS 6 */
+#define ICDI_SRST (1 << 5)             /* ADBUS 5 */
+
+
+       /* GPIOs on second channel/interface (UART) ... */
+#define ICDI_SWO_EN (1 << 4)           /* BDBUS 4 */
+#define ICDI_TX_SWO (1 << 1)           /* BDBUS 1 */
+#define ICDI_VCP_RX (1 << 0)           /* BDBUS 0 (to stellaris UART) */
+
+       nTRST = 0x0;
+       nTRSTnOE = 0x00;
+       nSRST = ICDI_SRST;
+       nSRSTnOE = ICDI_SRST;
+
+       low_direction |= ICDI_JTAG_EN | ICDI_DBG_ENn;
+       low_output    |= ICDI_JTAG_EN;
+       low_output    &= ~ICDI_DBG_ENn;
+
+       return ftx232_dbus_write();
+}
+
+static int signalyzer_init(void)
+{
+       ftx232_dbus_init();
+
+       nTRST    = 0x10;
+       nTRSTnOE = 0x10;
+       nSRST    = 0x20;
+       nSRSTnOE = 0x20;
+       return ftx232_dbus_write();
+}
+
+static int axm0432_jtag_init(void)
+{
        low_output    = 0x08;
        low_direction = 0x2b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2331,13 +2747,8 @@ static int axm0432_jtag_init(void)
                high_output |= nSRST;
        }
 
-       /* initialize high port */
-       buf[0] = 0x82;              /* command "set data bits high byte" */
-       buf[1] = high_output;       /* value */
-       buf[2] = high_direction;    /* all outputs (xRST and xRSTnOE) */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2346,21 +2757,62 @@ static int axm0432_jtag_init(void)
        return ERROR_OK;
 }
 
-static int jtagkey_init(void)
+static int redbee_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
+       low_output    = 0x08;
+       low_direction = 0x2b;
+
+       /* initialize low byte for jtag */
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       nTRST    = 0x08;
+       nTRSTnOE = 0x0;     /* No output enable for TRST*/
+       nSRST    = 0x04;
+       nSRSTnOE = 0x0;     /* No output enable for SRST*/
+
+       high_output    = 0x0;
+       high_direction = 0x0c;
+
+       enum reset_types jtag_reset_config = jtag_get_reset_config();
+       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+       {
+               LOG_ERROR("can't set nTRSTOE to push-pull on redbee");
+       }
+       else
+       {
+               high_output |= nTRST;
+       }
+
+       if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+       {
+               LOG_ERROR("can't set nSRST to push-pull on redbee");
+       }
+       else
+       {
+               high_output |= nSRST;
+       }
+
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
 
+static int jtagkey_init(void)
+{
        low_output    = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2413,13 +2865,8 @@ static int jtagkey_init(void)
                high_output &= ~nSRST;
        }
 
-       /* initialize high port */
-       buf[0] = 0x82;              /* command "set data bits high byte" */
-       buf[1] = high_output;       /* value */
-       buf[2] = high_direction;    /* all outputs (xRST and xRSTnOE) */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2430,19 +2877,11 @@ static int jtagkey_init(void)
 
 static int olimex_jtag_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2480,13 +2919,8 @@ static int olimex_jtag_init(void)
        /* turn red LED on */
        high_output |= 0x08;
 
-       /* initialize high port */
-       buf[0] = 0x82;              /* command "set data bits high byte" */
-       buf[1] = high_output;       /* value */
-       buf[2] = high_direction;    /* all outputs (xRST and xRSTnOE) */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2495,21 +2929,21 @@ static int olimex_jtag_init(void)
        return ERROR_OK;
 }
 
-static int flyswatter_init(void)
+static int flyswatter_init(int rev)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x18;
-       low_direction = 0xfb;
+       low_direction = 0x7b;
 
-       /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE[12]=out, n[ST]srst = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       if ((rev < 0) || (rev > 3)) {
+               LOG_ERROR("bogus 'flyswatter' revision supplied (%i)", rev);
+               return ERROR_JTAG_INIT_FAILED;
+       }
 
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (rev == 1)
+               low_direction |= 1 << 7;
+
+       /* initialize low byte for jtag */
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2521,18 +2955,17 @@ static int flyswatter_init(void)
        nSRSTnOE = 0x00;    /* no output enable for nSRST */
 
        high_output    = 0x00;
-       high_direction = 0x0c;
+
+       if (rev == 1)
+               high_direction = 0x0c;
+       else
+               high_direction = 0x01;
 
        /* turn red LED3 on, LED2 off */
        high_output |= 0x08;
 
-       /* initialize high port */
-       buf[0] = 0x82;              /* command "set data bits high byte" */
-       buf[1] = high_output;       /* value */
-       buf[2] = high_direction;    /* all outputs (xRST and xRSTnOE) */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2541,21 +2974,54 @@ static int flyswatter_init(void)
        return ERROR_OK;
 }
 
-static int turtle_init(void)
+static int flyswatter1_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
+       return flyswatter_init(1);
+}
 
+static int flyswatter2_init(void)
+{
+       return flyswatter_init(2);
+}
+
+static int minimodule_init(void)
+{
+       low_output    = 0x18;//check if srst should be 1 or 0 initially. (0x08) (flyswatter was 0x18)
+       low_direction = 0xfb;//0xfb;
+
+       /* initialize low byte for jtag */
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+
+       nSRST    = 0x20;
+
+       high_output    = 0x00;
+       high_direction = 0x05;
+
+       /* turn red LED3 on, LED2 off */
+       //high_output |= 0x08;
+
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int turtle_init(void)
+{
        low_output    = 0x08;
        low_direction = 0x5b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2566,13 +3032,8 @@ static int turtle_init(void)
        high_output    = 0x00;
        high_direction = 0x0C;
 
-       /* initialize high port */
-       buf[0] = 0x82; /* command "set data bits high byte" */
-       buf[1] = high_output;
-       buf[2] = high_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2583,19 +3044,11 @@ static int turtle_init(void)
 
 static int comstick_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x0b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2609,13 +3062,8 @@ static int comstick_init(void)
        high_output    = 0x03;
        high_direction = 0x03;
 
-       /* initialize high port */
-       buf[0] = 0x82; /* command "set data bits high byte" */
-       buf[1] = high_output;
-       buf[2] = high_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2626,19 +3074,11 @@ static int comstick_init(void)
 
 static int stm32stick_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x88;
        low_direction = 0x8b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2652,13 +3092,8 @@ static int stm32stick_init(void)
        high_output    = 0x01;
        high_direction = 0x03;
 
-       /* initialize high port */
-       buf[0] = 0x82; /* command "set data bits high byte" */
-       buf[1] = high_output;
-       buf[2] = high_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2669,19 +3104,11 @@ static int stm32stick_init(void)
 
 static int sheevaplug_init(void)
 {
-       uint8_t buf[3];
-       uint32_t bytes_written;
-
        low_output = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80; /* command "set data bits low byte" */
-       buf[1] = low_output; /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2703,13 +3130,8 @@ static int sheevaplug_init(void)
        high_output |= nSRSTnOE;
        high_output &= ~nSRST;
 
-       /* initialize high port */
-       buf[0] = 0x82; /* command "set data bits high byte" */
-       buf[1] = high_output; /* value */
-       buf[2] = high_direction;   /* all outputs - xRST */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2720,19 +3142,11 @@ static int sheevaplug_init(void)
 
 static int cortino_jtag_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_output    = 0x08;
        low_direction = 0x1b;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;    /* value (TMS = 1,TCK = 0, TDI = 0, nOE = 0) */
-       buf[2] = low_direction; /* dir (output = 1), TCK/TDI/TMS = out, TDO = in, nOE = out */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -2746,15 +3160,119 @@ static int cortino_jtag_init(void)
        high_output    = 0x03;
        high_direction = 0x03;
 
-       /* initialize high port */
-       buf[0] = 0x82; /* command "set data bits high byte" */
-       buf[1] = high_output;
-       buf[2] = high_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int lisa_l_init(void)
+{
+       ftx232_dbus_init();
+
+       nTRST    = 0x10;
+       nTRSTnOE = 0x10;
+       nSRST    = 0x40;
+       nSRSTnOE = 0x40;
 
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       high_output = 0x00;
+       high_direction = 0x18;
+
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
-               LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout");
+               LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ftx232_dbus_write();
+}
+
+static int flossjtag_init(void)
+{
+       ftx232_dbus_init();
+
+       nTRST    = 0x10;
+       nTRSTnOE = 0x10;
+       nSRST    = 0x40;
+       nSRSTnOE = 0x40;
+
+       high_output = 0x00;
+       high_direction = 0x18;
+
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ftx232_dbus_write();
+}
+
+/*
+ * The reference schematic from TI for the XDS100v2 has a CPLD on which opens
+ * the door for a number of different configurations
+ *
+ * Known Implementations:
+ * http://processors.wiki.ti.com/images/9/93/TMS570LS20216_USB_STICK_Schematic.pdf
+ *
+ * http://processors.wiki.ti.com/index.php/XDS100 (rev2)
+ *     * CLPD logic: Rising edge to enable outputs (XDS100_PWR_RST)
+ *             * ACBUS3 to transition 0->1 (OE rising edge)
+ *     * CPLD logic: Put the EMU0/1 pins in Hi-Z:
+ *             * ADBUS5/GPIOL1 = EMU_EN = 1
+ *             * ADBUS6/GPIOL2 = EMU0 = 0
+ *             * ACBUS4/SPARE0 = EMU1 = 0
+ *     * CPLD logic: Disable loopback
+ *             * ACBUS6/SPARE2 = LOOPBACK = 0
+ */
+#define XDS100_nEMU_EN (1<<5)
+#define XDS100_nEMU0   (1<<6)
+
+#define XDS100_PWR_RST (1<<3)
+#define XDS100_nEMU1   (1<<4)
+#define XDS100_LOOPBACK        (1<<6)
+static int xds100v2_init(void)
+{
+       /* These are in the lower byte */
+       nTRST    = 0x10;
+       nTRSTnOE = 0x10;
+
+       /* These aren't actually used on 14 pin connectors */
+       /* These are in the upper byte */
+       nSRST    = 0x01;
+       nSRSTnOE = 0x01;
+
+       low_output    = 0x08 | nTRST | XDS100_nEMU_EN;
+       low_direction = 0x0b | nTRSTnOE | XDS100_nEMU_EN | XDS100_nEMU0;
+
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't initialize FT2232 with 'xds100v2' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       high_output = 0;
+       high_direction = nSRSTnOE | XDS100_LOOPBACK | XDS100_PWR_RST | XDS100_nEMU1;
+
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't put CPLD in to reset with 'xds100v2' layout");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       high_output |= XDS100_PWR_RST;
+
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
+       {
+               LOG_ERROR("couldn't bring CPLD out of reset with 'xds100v2' layout");
                return ERROR_JTAG_INIT_FAILED;
        }
 
@@ -2766,15 +3284,48 @@ static void olimex_jtag_blink(void)
        /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
         * ACBUS3 is bit 3 of the GPIOH port
         */
+       high_output ^= 0x08;
+
+       buffer_write(0x82);
+       buffer_write(high_output);
+       buffer_write(high_direction);
+}
+
+static void flyswatter_jtag_blink(unsigned char led)
+{
+       buffer_write(0x82);
+       buffer_write(high_output ^ led);
+       buffer_write(high_direction);
+}
+
+static void flyswatter1_jtag_blink(void)
+{
+       /*
+        * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3
+        */
+       flyswatter_jtag_blink(0xc);
+}
+
+static void flyswatter2_jtag_blink(void)
+{
+       /*
+        * Flyswatter2 only has one LED connected to ACBUS2
+        */
+       flyswatter_jtag_blink(0x4);
+}
+
+static void turtle_jtag_blink(void)
+{
+       /*
+        * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3
+        */
        if (high_output & 0x08)
        {
-               /* set port pin high */
-               high_output &= 0x07;
+               high_output = 0x04;
        }
        else
        {
-               /* set port pin low */
-               high_output |= 0x08;
+               high_output = 0x08;
        }
 
        buffer_write(0x82);
@@ -2782,30 +3333,37 @@ static void olimex_jtag_blink(void)
        buffer_write(high_direction);
 }
 
-static void flyswatter_jtag_blink(void)
+static void lisa_l_blink(void)
 {
        /*
-        * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3
+        * Lisa/L has two LEDs connected to BCBUS3 and BCBUS4
         */
-       high_output ^= 0x0c;
+       if (high_output & 0x10)
+       {
+               high_output = 0x08;
+       }
+       else
+       {
+               high_output = 0x10;
+       }
 
        buffer_write(0x82);
        buffer_write(high_output);
        buffer_write(high_direction);
 }
 
-static void turtle_jtag_blink(void)
+static void flossjtag_blink(void)
 {
        /*
-        * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3
+        * Floss-JTAG has two LEDs connected to ACBUS3 and ACBUS4
         */
-       if (high_output & 0x08)
+       if (high_output & 0x10)
        {
-               high_output = 0x04;
+               high_output = 0x08;
        }
        else
        {
-               high_output = 0x08;
+               high_output = 0x10;
        }
 
        buffer_write(0x82);
@@ -2873,7 +3431,7 @@ COMMAND_HANDLER(ft2232_handle_serial_command)
        }
        else
        {
-               LOG_ERROR("expected exactly one argument to ft2232_serial <serial-number>");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        return ERROR_OK;
@@ -2881,13 +3439,27 @@ COMMAND_HANDLER(ft2232_handle_serial_command)
 
 COMMAND_HANDLER(ft2232_handle_layout_command)
 {
-       if (CMD_ARGC == 0)
-               return ERROR_OK;
+       if (CMD_ARGC != 1) {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
 
-       ft2232_layout = malloc(strlen(CMD_ARGV[0]) + 1);
-       strcpy(ft2232_layout, CMD_ARGV[0]);
+       if (layout) {
+               LOG_ERROR("already specified ft2232_layout %s",
+                               layout->name);
+               return (strcmp(layout->name, CMD_ARGV[0]) != 0)
+                               ? ERROR_FAIL
+                               : ERROR_OK;
+       }
 
-       return ERROR_OK;
+       for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) {
+               if (strcmp(l->name, CMD_ARGV[0]) == 0) {
+                       layout = l;
+                       return ERROR_OK;
+               }
+       }
+
+       LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]);
+       return ERROR_FAIL;
 }
 
 COMMAND_HANDLER(ft2232_handle_vid_pid_command)
@@ -2931,7 +3503,7 @@ COMMAND_HANDLER(ft2232_handle_latency_command)
        }
        else
        {
-               LOG_ERROR("expected exactly one argument to ft2232_latency <ms>");
+           return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        return ERROR_OK;
@@ -3006,9 +3578,6 @@ static int ft2232_stableclocks(int num_cycles, struct jtag_command* cmd)
  * ADBUS7 -   GND
  */
 static int icebear_jtag_init(void) {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
-
        low_direction   = 0x0b; /* output: TCK TDI TMS; input: TDO */
        low_output      = 0x08; /* high: TMS; low: TCK TDI */
        nTRST           = 0x10;
@@ -3027,12 +3596,7 @@ static int icebear_jtag_init(void) {
        low_output      |= nSRST;
 
        /* initialize low byte for jtag */
-       buf[0] = 0x80;          /* command "set data bits low byte" */
-       buf[1] = low_output;
-       buf[2] = low_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) {
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK) {
                LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)");
                return ERROR_JTAG_INIT_FAILED;
        }
@@ -3040,14 +3604,8 @@ static int icebear_jtag_init(void) {
        high_output    = 0x0;
        high_direction = 0x00;
 
-
-       /* initialize high port */
-       buf[0] = 0x82;              /* command "set data bits high byte" */
-       buf[1] = high_output;       /* value */
-       buf[2] = high_direction;    /* all outputs (xRST and xRSTnOE) */
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3)) {
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK) {
                LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)");
                return ERROR_JTAG_INIT_FAILED;
        }
@@ -3165,7 +3723,8 @@ static int signalyzer_h_led_set(unsigned char channel, unsigned char led,
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
                        ((uint32_t)(channel << 8) | led))) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write  returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write  returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3173,7 +3732,8 @@ static int signalyzer_h_led_set(unsigned char channel, unsigned char led,
                        (SIGNALYZER_DATA_BUFFER_ADDR + 1),
                        ((uint32_t)(on_time << 8) | off_time))) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write  returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write  returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3181,14 +3741,16 @@ static int signalyzer_h_led_set(unsigned char channel, unsigned char led,
                        (SIGNALYZER_DATA_BUFFER_ADDR + 2),
                        ((uint32_t)cycles))) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write  returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write  returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
                        SIGNALYZER_COMMAND_LED_SET)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write  returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write  returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3244,8 +3806,6 @@ static int signalyzer_h_init(void)
        char *end_of_desc;
 
        uint16_t read_buf[12] = { 0 };
-       uint8_t  buf[3];
-       uint32_t bytes_written;
 
        /* turn on center green led */
        signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN,
@@ -3279,7 +3839,8 @@ static int signalyzer_h_init(void)
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
                        SIGNALYZER_COMMAND_VERSION)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3289,8 +3850,8 @@ static int signalyzer_h_init(void)
                        (SIGNALYZER_DATA_BUFFER_ADDR + i),
                        &read_buf[i])) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_read returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_read returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
        }
@@ -3303,21 +3864,24 @@ static int signalyzer_h_init(void)
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
                        (uint32_t)(signalyzer_h_side << 8))) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1,
                        0x0404)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
                        SIGNALYZER_COMMAND_GPIO_STATE)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3325,28 +3889,32 @@ static int signalyzer_h_init(void)
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR,
                        ((uint32_t)(signalyzer_h_side << 8) | 0x01))) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
        if ((status = signalyzer_h_ctrl_write(
                        (SIGNALYZER_DATA_BUFFER_ADDR + 1), 0xA000)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
        if ((status = signalyzer_h_ctrl_write(
                        (SIGNALYZER_DATA_BUFFER_ADDR + 2), 0x0008)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
        if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
                        SIGNALYZER_COMMAND_I2C)) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_write returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3355,7 +3923,8 @@ static int signalyzer_h_init(void)
        if ((status = signalyzer_h_ctrl_read(SIGNALYZER_COMMAND_ADDR,
                        &read_buf[0])) != FT_OK)
        {
-               LOG_ERROR("signalyzer_h_ctrl_read returned: %lu", status);
+               LOG_ERROR("signalyzer_h_ctrl_read returned: %s",
+                               ftd2xx_status_string(status));
                return ERROR_JTAG_DEVICE_ERROR;
        }
 
@@ -3369,8 +3938,8 @@ static int signalyzer_h_init(void)
                                        (SIGNALYZER_DATA_BUFFER_ADDR + i),
                                        &read_buf[i])) != FT_OK)
                        {
-                               LOG_ERROR("signalyzer_h_ctrl_read returned: %lu",
-                                       status);
+                               LOG_ERROR("signalyzer_h_ctrl_read returned: %s",
+                                               ftd2xx_status_string(status));
                                return ERROR_JTAG_DEVICE_ERROR;
                        }
                }
@@ -3434,16 +4003,16 @@ static int signalyzer_h_init(void)
                                ((uint32_t)(signalyzer_h_side << 8) | 0x01)))
                        != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                               status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
                if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
                                SIGNALYZER_COMMAND_POWERCONTROL_SET)) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3452,8 +4021,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR,
                                (uint32_t)(signalyzer_h_side << 8))) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3461,16 +4030,16 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000))
                        != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
                if ((status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR,
                                SIGNALYZER_COMMAND_GPIO_MODE)) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3479,8 +4048,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR,
                                (uint32_t)(signalyzer_h_side << 8))) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3488,8 +4057,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x4040))
                        != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3497,8 +4066,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_COMMAND_ADDR,
                                SIGNALYZER_COMMAND_GPIO_STATE)) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 #endif
@@ -3569,8 +4138,8 @@ static int signalyzer_h_init(void)
                                ((uint32_t)(signalyzer_h_side << 8) | 0x01)))
                        != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3578,8 +4147,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_COMMAND_ADDR,
                                SIGNALYZER_COMMAND_POWERCONTROL_SET)) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3590,8 +4159,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR,
                                (uint32_t)(signalyzer_h_side << 8))) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3599,8 +4168,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0060))
                        != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3608,8 +4177,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_COMMAND_ADDR,
                                SIGNALYZER_COMMAND_GPIO_MODE)) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3620,8 +4189,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR,
                                (uint32_t)(signalyzer_h_side << 8))) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3629,8 +4198,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000))
                        != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 
@@ -3638,8 +4207,8 @@ static int signalyzer_h_init(void)
                                SIGNALYZER_COMMAND_ADDR,
                                SIGNALYZER_COMMAND_GPIO_STATE)) != FT_OK)
                {
-                       LOG_ERROR("signalyzer_h_ctrl_write returned: %lu",
-                                       status);
+                       LOG_ERROR("signalyzer_h_ctrl_write returned: %s",
+                                       ftd2xx_status_string(status));
                        return ERROR_JTAG_DEVICE_ERROR;
                }
 #endif
@@ -3690,12 +4259,7 @@ static int signalyzer_h_init(void)
        }
 
        /* initialize low byte of controller for jtag operation */
-       buf[0] = 0x80;
-       buf[1] = low_output;
-       buf[2] = low_direction;
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK)
-                       || (bytes_written != 3))
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize Signalyzer-H layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -3705,12 +4269,7 @@ static int signalyzer_h_init(void)
        if (ftdi_device == FT_DEVICE_2232H)
        {
                /* initialize high byte of controller for jtag operation */
-               buf[0] = 0x82;
-               buf[1] = high_output;
-               buf[2] = high_direction;
-
-               if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK)
-                               || (bytes_written != 3))
+               if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
                {
                        LOG_ERROR("couldn't initialize Signalyzer-H layout");
                        return ERROR_JTAG_INIT_FAILED;
@@ -3720,12 +4279,7 @@ static int signalyzer_h_init(void)
        if (ftdi_device == TYPE_2232H)
        {
                /* initialize high byte of controller for jtag operation */
-               buf[0] = 0x82;
-               buf[1] = high_output;
-               buf[2] = high_direction;
-
-               if ((ft2232_write(buf, 3, &bytes_written) != ERROR_OK)
-                               || (bytes_written != 3))
+               if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
                {
                        LOG_ERROR("couldn't initialize Signalyzer-H layout");
                        return ERROR_JTAG_INIT_FAILED;
@@ -3896,20 +4450,13 @@ static void signalyzer_h_blink(void)
  *******************************************************************/
 static int ktlink_init(void)
 {
-       uint8_t  buf[3];
-       uint32_t bytes_written;
        uint8_t  swd_en = 0x20; //0x20 SWD disable, 0x00 SWD enable (ADBUS5)
 
        low_output    = 0x08 | swd_en; // value; TMS=1,TCK=0,TDI=0,SWD=swd_en
        low_direction = 0x3B;          // out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in
 
-       // initialize low port
-       buf[0] = 0x80;          // command "set data bits low byte"
-       buf[1] = low_output;
-       buf[2] = low_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize low byte for jtag */
+       if (ft2232_set_data_bits_low_byte(low_output,low_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -3941,13 +4488,8 @@ static int ktlink_init(void)
                high_output &= ~nSRST;
        }
 
-       // initialize high port
-       buf[0] = 0x82;              // command "set data bits high byte"
-       buf[1] = high_output;       // value
-       buf[2] = high_direction;
-       LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
-
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       /* initialize high byte for jtag */
+       if (ft2232_set_data_bits_high_byte(high_output,high_direction) != ERROR_OK)
        {
                LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout");
                return ERROR_JTAG_INIT_FAILED;
@@ -3993,10 +4535,7 @@ static void ktlink_reset(int trst, int srst)
 static void ktlink_blink(void)
 {
        /* LED connected to ACBUS7 */
-       if (high_output & 0x80)
-               high_output &= 0x7F;
-       else
-               high_output |= 0x80;
+       high_output ^= 0x80;
 
        buffer_write(0x82);  // command "set data bits high byte"
        buffer_write(high_output);
@@ -4045,7 +4584,9 @@ static const struct command_registration ft2232_command_handlers[] = {
 
 struct jtag_interface ft2232_interface = {
        .name = "ft2232",
+       .supported = DEBUG_CAP_TMS_SEQ,
        .commands = ft2232_command_handlers,
+       .transports = jtag_only,
 
        .init = ft2232_init,
        .quit = ft2232_quit,

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)