Hello,

This patch replaces bit banging mode with faster byte shift mode.
Tested so far with LPC2132 and Cypress EZ-USB FX2 controller (with
Kolja Waschk's usb_jtag software).

All feedback much appreciated.

-Juha
diff --git a/src/jtag/drivers/usb_blaster.c b/src/jtag/drivers/usb_blaster.c
index 3703323..65d6bd4 100644
--- a/src/jtag/drivers/usb_blaster.c
+++ b/src/jtag/drivers/usb_blaster.c
@@ -4,6 +4,10 @@
  *     (http://www.ixo.de/info/usb_jtag/).                                 *
  *   Some updates by Anthony Liu (2006).                                   *
  *   Minor updates and cleanup by Catalin Patulea (2009).                  *
+ *   Byte shift mode  by Juha Karttunen (2010                             *
+ *                                                                         *
+ *   Copyright (C) 2010 Juha Karttunen                                     *
+ *   [email protected]                                                    *
  *                                                                         *
  *   Copyright (C) 2009 Catalin Patulea                                    *
  *   [email protected]                                                    *
@@ -62,6 +66,47 @@
  * It is also possible to emulate this configuration using a single-chip USB
  * controller like the Cypress FX2 (again, see usb_jtag for details).
  */
+
+
+/* The following code fully utilizes the possibilities of the
+ * USB-Blaster. It buffers data up to the maximum packet size of 64 
+ * bytes.
+ *
+ * USB-Blaster offers a byte-shift mode to transmit up to 504 data
+ * bits (bidirectional) in a single USB packet. A header byte has to be sent as
+ * the first byte in a packet with the following meaning:
+ *
+ *   Bit 7 (0x80): Must be set to indicate byte-shift mode.
+ *   Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
+ *   Bit 5..0:     Define the number N of following bytes
+ *
+ * All N following bytes will then be clocked out serially on TDI. If Bit 6 was
+ * set, it will afterwards return N bytes with TDO data read while clocking out
+ * the TDI data. LSB of the first byte after the header byte will appear first
+ * on TDI.
+ */
+
+/* Simple bit banging mode:
+ *
+ *   Bit 7 (0x80): Must be zero (see byte-shift mode above)
+ *   Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
+ *                 in return.
+ *   Bit 5 (0x20): Output Enable/LED.
+ *   Bit 4 (0x10): TDI Output.
+ *   Bit 3 (0x08): nCS Output (not used in JTAG mode).
+ *   Bit 2 (0x04): nCE Output (not used in JTAG mode).
+ *   Bit 1 (0x02): TMS Output.
+ *   Bit 0 (0x01): TCK Output.
+ *
+ * For transmitting a single data bit, you need to write two bytes. Up to 64
+ * bytes can be combined in a single USB packet (but this is not done in the
+ * code below). It isn't possible to read a data without transmitting data.
+ */
+
+
+
+
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -81,7 +126,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "bitbang.h"
 
 #if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1)
 #error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI "
@@ -100,134 +144,6 @@
 #include <sys/time.h>
 #include <time.h>
 
-static char *usb_blaster_device_desc;
-static uint16_t usb_blaster_vid = 0x09fb; /* Altera */
-static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */
-
-/* last output byte in simple bit banging mode */
-static uint8_t out_value;
-
-#if BUILD_USB_BLASTER_FTD2XX == 1
-static FT_HANDLE ftdih;
-#elif BUILD_USB_BLASTER_LIBFTDI == 1
-static struct ftdi_context ftdic;
-#endif
-
-static int usb_blaster_buf_write(
-       uint8_t *buf, int size, uint32_t *bytes_written)
-{
-#if BUILD_USB_BLASTER_FTD2XX == 1
-       FT_STATUS status;
-       DWORD dw_bytes_written;
-
-#ifdef _DEBUG_JTAG_IO_
-       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
-#endif
-       status = FT_Write(ftdih, buf, size, &dw_bytes_written);
-       if (status != FT_OK)
-       {
-               *bytes_written = dw_bytes_written;
-               LOG_ERROR("FT_Write returned: %lu", status);
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-       *bytes_written = dw_bytes_written;
-       return ERROR_OK;
-#elif BUILD_USB_BLASTER_LIBFTDI == 1
-       int retval;
-#ifdef _DEBUG_JTAG_IO_
-       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
-#endif
-       retval = ftdi_write_data(&ftdic, buf, size);
-       if (retval < 0)
-       {
-               *bytes_written = 0;
-               LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-       *bytes_written = retval;
-       return ERROR_OK;
-#endif
-}
-
-static int
-usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
-{
-#if BUILD_USB_BLASTER_FTD2XX == 1
-       DWORD dw_bytes_read;
-       FT_STATUS status;
-
-       status = FT_Read(ftdih, buf, size, &dw_bytes_read);
-       if (status != FT_OK)
-       {
-               *bytes_read = dw_bytes_read;
-               LOG_ERROR("FT_Read returned: %lu", status);
-               return ERROR_JTAG_DEVICE_ERROR;
-       }
-#ifdef _DEBUG_JTAG_IO_
-       LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
-#endif
-       *bytes_read = dw_bytes_read;
-       return ERROR_OK;
-
-#elif BUILD_USB_BLASTER_LIBFTDI == 1
-       int retval;
-       int timeout = 100;
-
-       *bytes_read = 0;
-       while ((*bytes_read < size) && timeout--)
-       {
-               retval = ftdi_read_data(&ftdic, buf + *bytes_read,
-                               size - *bytes_read);
-               if (retval < 0)
-               {
-                       *bytes_read = 0;
-                       LOG_ERROR("ftdi_read_data: %s",
-                                       ftdi_get_error_string(&ftdic));
-                       return ERROR_JTAG_DEVICE_ERROR;
-               }
-               *bytes_read += retval;
-       }
-#ifdef _DEBUG_JTAG_IO_
-       LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
-#endif
-       return ERROR_OK;
-#endif
-}
-
-/* The following code doesn't fully utilize the possibilities of the
- * USB-Blaster. It writes one byte per JTAG pin state change at a time; it
- * doesn't even try to buffer data up to the maximum packet size of 64 bytes.
- *
- * Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 
data
- * bits (bidirectional) in a single USB packet. A header byte has to be sent as
- * the first byte in a packet with the following meaning:
- *
- *   Bit 7 (0x80): Must be set to indicate byte-shift mode.
- *   Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
- *   Bit 5..0:     Define the number N of following bytes
- *
- * All N following bytes will then be clocked out serially on TDI. If Bit 6 was
- * set, it will afterwards return N bytes with TDO data read while clocking out
- * the TDI data. LSB of the first byte after the header byte will appear first
- * on TDI.
- */
-
-/* Simple bit banging mode:
- *
- *   Bit 7 (0x80): Must be zero (see byte-shift mode above)
- *   Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
- *                 in return.
- *   Bit 5 (0x20): Output Enable/LED.
- *   Bit 4 (0x10): TDI Output.
- *   Bit 3 (0x08): nCS Output (not used in JTAG mode).
- *   Bit 2 (0x04): nCE Output (not used in JTAG mode).
- *   Bit 1 (0x02): TMS Output.
- *   Bit 0 (0x01): TCK Output.
- *
- * For transmitting a single data bit, you need to write two bytes. Up to 64
- * bytes can be combined in a single USB packet (but this is not done in the
- * code below). It isn't possible to read a data without transmitting data.
- */
 
 #define TCK                    (1 << 0)
 #define TMS                    (1 << 1)
@@ -241,44 +157,42 @@ usb_blaster_buf_read(uint8_t *buf, unsigned size, 
uint32_t *bytes_read)
 
 #define READ_TDO       (1 << 0)
 
-static void usb_blaster_write_data(void)
-{
-       uint32_t bytes_written;
-       usb_blaster_buf_write(&out_value, 1, &bytes_written);
-}
 
-static int usb_blaster_read_data(void)
-{
-       int status;
-       uint8_t buf[1];
-       uint32_t bytes_read;
+static void usb_blaster_end_state(tap_state_t state);
+static void usb_blaster_state_move(void);
+static void usb_blaster_path_move(struct pathmove_command *cmd);
+static void usb_blaster_runtest(int num_cycles);
+static void usb_blaster_scan(bool ir_scan,
+        enum scan_type type, uint8_t *buffer, int scan_size);
+static void usb_blaster_reset(int trst, int srst);
+static void usb_blaster_write(int tck, int tms, int tdi);
+static int usb_blaster_read(int tck, int tms, int tdi);
+static int usb_blaster_buf_write(
+       uint8_t *buf, int size, uint32_t *bytes_written);
+static int usb_blaster_buf_read(uint8_t *buf, 
+       unsigned size, uint32_t *bytes_read);
+static void usb_blaster_jtag_tms_send(void);
+static void usb_blaster_jtag_write_and_read(char * buffer, int size);
+static void usb_blaster_jtag_read_tdo(char *buffer, int size);
+static void usb_blaster_jtag_write_tdi(char *buffer, int size);
 
-       out_value |= READ;
-       usb_blaster_write_data();
-       out_value &= ~READ;
 
-       status = usb_blaster_buf_read(buf, 1, &bytes_read);
-       if (status < 0)
-               return 0;
 
-       return !!(buf[0] & READ_TDO);
-}
 
-static void usb_blaster_write(int tck, int tms, int tdi)
-{
-#ifdef _DEBUG_JTAG_IO_
-       LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck, tms, tdi);
+static char tms_chain[64];
+static int tms_chain_index;
+
+static char *usb_blaster_device_desc;
+static uint16_t usb_blaster_vid = 0x09fb; /* Altera */
+static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */
+
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+static FT_HANDLE ftdih;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+static struct ftdi_context ftdic;
 #endif
-       out_value &= ~(TCK | TMS | TDI);
-       if (tck)
-               out_value |= TCK;
-       if (tms)
-               out_value |= TMS;
-       if (tdi)
-               out_value |= TDI;
 
-       usb_blaster_write_data();
-}
 
 static int usb_blaster_speed(int speed)
 {
@@ -301,17 +215,79 @@ static int usb_blaster_speed(int speed)
        return ERROR_OK;
 }
 
-static void usb_blaster_reset(int trst, int srst)
+
+
+static int usb_blaster_execute_queue(void)
 {
-       LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!",
-                       trst, srst);
-}
+       struct jtag_command *cmd = jtag_command_queue; /* currently processed 
command */
+       int scan_size;
+       enum scan_type type;
+       uint8_t *buffer;
 
-static struct bitbang_interface usb_blaster_bitbang = {
-       .read = usb_blaster_read_data,
-       .write = usb_blaster_write,
-       .reset = usb_blaster_reset,
-};
+       while (cmd)
+       {
+               switch (cmd->type)
+               {
+                       case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+                               LOG_DEBUG("reset trst: %i srst %i", 
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+                                if ((cmd->cmd.reset->trst == 1) || 
(cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
+                               {
+                                       tap_set_state(TAP_RESET);
+                               }
+                               usb_blaster_reset(cmd->cmd.reset->trst, 
cmd->cmd.reset->srst);
+                               break;
+                       case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+                               LOG_DEBUG("runtest %i cycles, end in %i", 
cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+#endif
+                               
usb_blaster_end_state(cmd->cmd.runtest->end_state);
+                               
usb_blaster_runtest(cmd->cmd.runtest->num_cycles);
+                               break;
+                       case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               LOG_DEBUG("statemove end in %i", 
cmd->cmd.statemove->end_state);
+#endif
+                               
usb_blaster_end_state(cmd->cmd.statemove->end_state);
+                               usb_blaster_state_move();
+                               break;
+                       case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               LOG_DEBUG("pathmove: %i states, end in %i", 
cmd->cmd.pathmove->num_states,
+                                       
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+#endif
+                               usb_blaster_path_move(cmd->cmd.pathmove);
+                               break;
+                       case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+                               LOG_DEBUG("scan end in %i", 
cmd->cmd.scan->end_state);
+#endif
+                               usb_blaster_end_state(cmd->cmd.scan->end_state);
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, 
&buffer);
+                               type = jtag_scan_type(cmd->cmd.scan);
+                               usb_blaster_scan(cmd->cmd.scan->ir_scan, type, 
buffer, scan_size);
+                               if (jtag_read_buffer(buffer, cmd->cmd.scan) != 
ERROR_OK)
+                                       return ERROR_JTAG_QUEUE_FAILED;
+                               if (buffer)
+                                       free(buffer);
+                               break;
+                       case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+                               LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
+#endif
+                               jtag_sleep(cmd->cmd.sleep->us);
+                                       break;
+                       default:
+                               LOG_ERROR("BUG: unknown JTAG command type 
encountered");
+                               exit(-1);
+               }
+
+               cmd = cmd->next;
+       }
+
+       return ERROR_OK;
+}
 
 static int usb_blaster_init(void)
 {
@@ -440,7 +416,6 @@ static int usb_blaster_init(void)
        ftdi_disable_bitbang(&ftdic);
 #endif
 
-       bitbang_interface = &usb_blaster_bitbang;
 
        usb_blaster_speed(jtag_get_speed());
 
@@ -459,7 +434,6 @@ static int usb_blaster_init(void)
        }
 #endif
 #endif
-
        return ERROR_OK;
 }
 
@@ -477,6 +451,295 @@ static int usb_blaster_quit(void)
        return ERROR_OK;
 }
 
+
+static void usb_blaster_end_state(tap_state_t state)
+{
+       if (tap_is_state_stable(state))
+               tap_set_end_state(state);
+       else
+       {
+               LOG_ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+}
+
+static void usb_blaster_state_move(void)
+{
+       int i = 0;
+       uint8_t tms_scan = tap_get_tms_path(tap_get_state(), 
tap_get_end_state());
+       int tms_count = tap_get_tms_path_len(tap_get_state(), 
tap_get_end_state());
+
+
+       for(i=0;i<tms_count;i++)
+       {
+               tms_chain[i+tms_chain_index] = (char) (tms_scan>>i) & 1;
+       }
+
+       tms_chain_index += tms_count;
+
+
+       tap_set_state(tap_get_end_state());
+}
+
+static void usb_blaster_path_move(struct pathmove_command *cmd)
+{
+       int num_states = cmd->num_states;
+       int state_count, tms = 0;
+
+       /* There may be queued transitions, and before following a specified
+          path, we must flush those queued transitions */
+       usb_blaster_jtag_tms_send();
+
+       state_count = 0;
+       while (num_states)
+       {
+               if (tap_state_transition(tap_get_state(), false) == 
cmd->path[state_count])
+               {
+                       /* LOG_INFO("1"); */
+                       tms = 0;
+               }
+               else if (tap_state_transition(tap_get_state(), true) == 
cmd->path[state_count])
+               {
+                       /* LOG_INFO("2"); */
+                       tms = 1;
+               }
+               else
+               {
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", 
tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
+                       exit(-1);
+               }
+               usb_blaster_write(0, tms, 0);
+               usb_blaster_write(1, tms, 0);
+
+               tap_set_state(cmd->path[state_count]);
+               state_count++;
+               num_states--;
+       }
+       usb_blaster_write(0, tms, 0);
+
+       tap_set_end_state(tap_get_state());
+}
+
+
+static void usb_blaster_runtest(int num_cycles)
+{
+       int i;
+
+       /* only do a state_move when we're not already in IDLE */
+       if (tap_get_state() != TAP_IDLE)
+       {
+               usb_blaster_end_state(TAP_IDLE);
+               usb_blaster_state_move();
+       }
+
+       /* execute num_cycles */
+       if (num_cycles > 0)
+       {
+               usb_blaster_jtag_tms_send();
+       }
+       else
+       {
+               usb_blaster_jtag_tms_send();
+               /* LOG_INFO("NUM CYCLES %i",num_cycles); */
+       }
+
+       for (i = 0; i < num_cycles; i++)
+       {
+               usb_blaster_write(0, 0, 0);
+               usb_blaster_write(1, 0, 0);
+       }
+
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("runtest: cur_state %s end_state %s", 
tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()));
+#endif
+
+       usb_blaster_write(0, 0, 0);
+
+}
+
+static void usb_blaster_scan(bool ir_scan, enum scan_type type, uint8_t 
*buffer, int scan_size)
+{
+       tap_state_t saved_end_state = tap_get_end_state();
+
+
+       if (ir_scan)
+               usb_blaster_end_state(TAP_IRSHIFT);
+       else
+               usb_blaster_end_state(TAP_DRSHIFT);
+
+       /* Only move if we're not already there */
+       if (tap_get_state() != tap_get_end_state())
+               usb_blaster_state_move();
+
+       usb_blaster_end_state(saved_end_state);
+
+       usb_blaster_jtag_tms_send();
+
+       void (*f)(char * buffer, int size);
+       switch (type) {
+       case SCAN_OUT: f = &usb_blaster_jtag_write_tdi; break;
+       case SCAN_IN: f = &usb_blaster_jtag_read_tdo; break;
+       case SCAN_IO: f = &usb_blaster_jtag_write_and_read; break;
+       default:
+               LOG_ERROR("unknown scan type: %i", type);
+               exit(-1);
+       }
+       f((char *)buffer, scan_size);
+
+       /* Move from EXIT to PAUSE state */
+
+       usb_blaster_write(0,0,0);
+       usb_blaster_write(1,0,0);
+       usb_blaster_write(0,0,0);
+
+       /* We know we are at PAUSE */
+       if (ir_scan)
+               tap_set_state(TAP_IRPAUSE);
+       else
+               tap_set_state(TAP_DRPAUSE);
+
+
+
+       if (tap_get_state() != tap_get_end_state())
+               usb_blaster_state_move(); 
+
+
+}
+
+static void usb_blaster_write(int tck, int tms, int tdi)
+{
+       unsigned char output_value = 0x00;
+       uint32_t bytes_written;
+
+       if (tms)
+               output_value |= (1<<1);
+       if (tdi)
+               output_value |= (1<<4);
+       if (tck)
+               output_value |= (1<<0);
+
+       usb_blaster_buf_write(&output_value,1,&bytes_written);
+}
+
+static int usb_blaster_read(int tck, int tms, int tdi)
+{
+       int status;
+        uint8_t ctrl_byte;
+       uint32_t bytes_read,bytes_written;
+
+        ctrl_byte = READ;
+
+       if (tms)
+               ctrl_byte |= TMS;
+       if (tdi)
+               ctrl_byte |= TDI;
+       if (tck)
+               ctrl_byte |= TCK;
+
+       usb_blaster_buf_write(&ctrl_byte,1,&bytes_written);
+
+        status = usb_blaster_buf_read(&ctrl_byte, 1, &bytes_read);
+        if (status < 0)
+                return 0;
+
+        return (ctrl_byte & READ_TDO);
+
+}
+
+static int usb_blaster_buf_write(
+       uint8_t *buf, int size, uint32_t *bytes_written)
+{
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       FT_STATUS status;
+       DWORD dw_bytes_written;
+
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+       status = FT_Write(ftdih, buf, size, &dw_bytes_written);
+       if (status != FT_OK)
+       {
+               *bytes_written = dw_bytes_written;
+               LOG_ERROR("FT_Write returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       *bytes_written = dw_bytes_written;
+       return ERROR_OK;
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       int retval;
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
+#endif
+       retval = ftdi_write_data(&ftdic, buf, size);
+       if (retval < 0)
+       {
+               *bytes_written = 0;
+               LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       *bytes_written = retval;
+       return ERROR_OK;
+#endif
+}
+
+static int
+usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
+{
+
+#if BUILD_USB_BLASTER_FTD2XX == 1
+       DWORD dw_bytes_read;
+       FT_STATUS status;
+
+       status = FT_Read(ftdih, buf, size, &dw_bytes_read);
+       if (status != FT_OK)
+       {
+               *bytes_read = dw_bytes_read;
+               LOG_ERROR("FT_Read returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
+
+#endif
+       *bytes_read = dw_bytes_read;
+       return ERROR_OK;
+
+#elif BUILD_USB_BLASTER_LIBFTDI == 1
+       int retval;
+       int timeout = 100;
+
+       *bytes_read = 0;
+       while ((*bytes_read < size) && timeout--)
+       {
+               retval = ftdi_read_data(&ftdic, buf + *bytes_read,
+                               size - *bytes_read);
+               if (retval < 0)
+               {
+                       *bytes_read = 0;
+                       LOG_ERROR("ftdi_read_data: %s",
+                                       ftdi_get_error_string(&ftdic));
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               *bytes_read += retval;
+       }
+#ifdef _DEBUG_JTAG_IO_
+       LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
+#endif
+       return ERROR_OK;
+#endif
+}
+
+
+
+static void usb_blaster_reset(int trst, int srst)
+{
+       LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!",
+                       trst, srst);
+
+}
+
+
 COMMAND_HANDLER(usb_blaster_handle_device_desc_command)
 {
        if (CMD_ARGC == 1)
@@ -514,6 +777,8 @@ COMMAND_HANDLER(usb_blaster_handle_pin_command)
                const char * const pin_name = CMD_ARGV[0];
                uint8_t mask;
                unsigned int state;
+               unsigned char out_value = 0x00;
+               uint32_t bytes_written;
 
                if (!strcmp(pin_name, "pin6"))
                        mask = NCE;
@@ -530,12 +795,12 @@ COMMAND_HANDLER(usb_blaster_handle_pin_command)
                if (state == 0)
                {
                        out_value &= ~mask;
-                       usb_blaster_write_data();
+                       usb_blaster_buf_write(&out_value,1,&bytes_written);
                }
                else if (state == 1)
                {
                        out_value |= mask;
-                       usb_blaster_write_data();
+                       usb_blaster_buf_write(&out_value,1,&bytes_written);
                }
                else
                {
@@ -577,13 +842,260 @@ static const struct command_registration 
usb_blaster_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
+
+
+
+
+static void usb_blaster_jtag_write_and_read(char * buffer, int size)
+{
+       uint8_t tmp[64];
+       int bufindex = 0, fillindex = 0;
+       int bit,extra = 0, tms;
+       uint32_t bytes_written, send_bits, bytes_read,loops,i,
+               remainder = 0;
+       char swap,rem_bits=0;
+
+       /* 63 byte can be transfered (504 bit) */
+
+
+       /* we must send last bit manually to be able to exit 
+          from DRSHIFT state. Programmer won't do that for us. */
+
+       if ((size % 8) == 0)
+       {
+               size--;
+               extra = 1;
+       }
+
+       while (size > 0)
+       {
+               if (size > 504)
+               {
+                       send_bits = 504;
+                       size = size - 504;
+                       loops = 63;
+               }
+               else
+               {
+                       loops = size / 8;
+                       send_bits = loops * 8;
+                       remainder = size - send_bits;
+                       size = 0;
+               }
+               tmp[0] = SHMODE|READ;
+               tmp[0] |= (send_bits/8) & 0x3F;
+
+
+               for (i = 0; i < loops; i++)
+               {
+                       tmp[1 + i] = buffer[bufindex];
+                       bufindex++;
+               }
+               if (remainder) rem_bits = buffer[bufindex];
+               if (loops>0)
+                       usb_blaster_buf_write(tmp,1+loops,&bytes_written);
+
+               if (bytes_written == 1+loops && loops>0)
+               {
+                       usleep(1);
+                       int timeout = 0;
+                       while (usb_blaster_buf_read(tmp, loops, &bytes_read) < 
0)
+                       {
+                               timeout++;
+                               if (timeout > 10)
+                                       break;
+                       }
+                       if (bytes_read != loops)
+                               printf("%d bytes read of 
%d.\n",bytes_read,loops); 
+                       for (i = 0; i < loops; i++)
+                       {
+                               swap =  tmp[i];
+                               buffer[fillindex] = swap;
+                               fillindex++;
+                       }
+               }
+               else if (loops){
+                       printf("write & read : buf_write failed! loops=%d 
bytes_written=%d\n",loops,bytes_written);
+                       exit(1);
+               }
+               if (remainder) {
+                       buffer[fillindex]=0;
+                       if (extra) remainder++;
+                       for (i=0,tms=0;i<remainder;i++) {
+                               if (i == remainder-1) tms = 1;
+                               bit = ((rem_bits & (1<<i)) >> i);
+                               tmp[0]=usb_blaster_read(0,tms,bit);
+                               usb_blaster_write(1,tms,bit);
+                               buffer[fillindex] |= (tmp[0] << i);
+                       }
+                       fillindex++;
+               }
+       }
+}
+
+static void usb_blaster_jtag_read_tdo(char * buffer, int size)
+{
+       uint8_t tmp[64];
+       int fillindex = 0, extra = 0, tms;
+       uint32_t bytes_written, bytes_read, send_bits, 
+               i, loops,remainder = 0;
+       char swap;
+
+       /* 63 byte can be transfered (504 bit) */
+
+       if ((size % 8) == 0)
+       {
+               size--;
+               extra = 1;
+       }
+
+       while (size > 0)
+       {
+               if (size > 504)
+               {
+                       send_bits = 504;
+                       size = size - 504;
+                       loops = 63;
+               }
+               else
+               {
+                       loops = size / 8;
+                       send_bits = loops * 8;
+                       remainder = size - send_bits;
+                       size = 0;
+               }
+               tmp[0] = SHMODE | READ;
+               tmp[0] |= (send_bits/8) & 0x3F;
+               i = 0;
+
+               for (i = 0; i < loops; i++) tmp[1 + i] = 0;
+
+               if (loops)
+                       usb_blaster_buf_write(tmp,1+loops,&bytes_written);
+
+               if (bytes_written == 1+loops && loops)
+               {
+                       usleep(1);
+                       int timeout = 0;
+                       while (usb_blaster_buf_read(tmp, loops, &bytes_read) < 
0)
+                       {
+                               timeout++;
+                               if (timeout > 10)
+                                       break;
+                       }
+                       if (bytes_read != loops)
+                               printf("%d bytes read of 
%d.\n",bytes_read,loops); 
+
+                       for (i = 0; i < loops; i++)
+                       {
+                               swap =  tmp[i];
+                               buffer[fillindex++] = swap;
+                       }
+               }
+               else if(loops){
+                       printf("read_tdo : needs to have check for sent 
data!\n");
+                       exit(1);
+               }
+               if (remainder) {
+                       buffer[fillindex]=0;
+                       if (extra) remainder++;
+                       for (i=0,tms=0;i<remainder;i++) {
+                               if (i == remainder-1) tms = 1;
+                               tmp[0]=usb_blaster_read(0,tms,0);
+                               usb_blaster_write(1,tms,0);
+                               buffer[fillindex] |= (tmp[0] << i);
+                       }
+               }
+       }
+}
+
+
+static void usb_blaster_jtag_write_tdi(char * buffer, int size)
+{
+       uint8_t tmp[64];
+       int bufindex = 0;
+       int bit, extra = 0, tms;
+       uint32_t bytes_written, send_bits, i, 
+               loops,remainder=0;
+       char rem_bits=0;
+
+       /* 63 byte can be transfered (504 bit) */
+       if ((size % 8) == 0)
+       {
+               size--;
+               extra = 1;
+       }
+
+       while (size > 0)
+       {
+               if (size > 504)
+               {
+                       send_bits = 504;
+                       size = size - 504;
+                       loops = 63;
+               }
+               else
+               {
+                       loops = size / 8;
+                       send_bits = loops * 8;
+                       remainder = size - send_bits;
+                       size = 0;
+               }
+               tmp[0] = SHMODE;
+               tmp[0] |= (send_bits/8) & 0x3F;
+               i = 0;
+
+               for (i = 0; i < loops; i++)
+               {
+                       tmp[1 + i] = buffer[bufindex];
+                       bufindex++;
+               }
+               if (remainder) rem_bits = buffer[bufindex];
+               if (loops)
+                       usb_blaster_buf_write(tmp,1+loops,&bytes_written);
+               if (bytes_written!=1+loops && loops>0)
+                       printf("write_tdi : w/r mismatch loops=%d bytes 
written=%d\n",
+                               loops,bytes_written);
+               if (remainder) {
+                       if (extra) remainder++;
+                       for (i=0,tms=0;i<remainder;i++) {
+                               if (i == remainder-1) tms = 1;
+                               bit = ((rem_bits & (1<<i)) >> i);
+                               usb_blaster_write(0,tms,bit);
+                               usb_blaster_write(1,tms,bit);
+                       }
+               }
+       }
+}
+
+
+
+
+static void usb_blaster_jtag_tms_send(void)
+{
+       int i,tms = 0;
+
+       if (tms_chain_index > 0)
+       {
+               for(i=0;i<tms_chain_index;i++)
+               {
+                       tms = tms_chain[i];
+                       usb_blaster_write(0,tms,0);
+                       usb_blaster_write(1,tms,0);
+               }
+               usb_blaster_write(0,tms,0);
+               tms_chain_index = 0;
+       }
+}
+
 struct jtag_interface usb_blaster_interface = {
        .name = "usb_blaster",
-       .commands = usb_blaster_command_handlers,
-
-       .execute_queue = bitbang_execute_queue,
 
+       .commands = usb_blaster_command_handlers,
+       .execute_queue = usb_blaster_execute_queue,
        .speed = usb_blaster_speed,
        .init = usb_blaster_init,
-       .quit = usb_blaster_quit,
+       .quit = usb_blaster_quit
 };
+
+
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to