From 92c0c55e98fa63a93d609c91e4ce6f99415514a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnim=20L=C3=A4uger?= Date: Tue, 20 May 2008 20:35:08 +0000 Subject: [PATCH] ft2232 and usbblaster cable drivers ported to usbconn layer git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1244 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- jtag/ChangeLog | 16 + jtag/configure.ac | 52 +- jtag/doc/UrJTAG.txt | 39 +- jtag/include/usbconn.h | 7 +- jtag/include/usbconn/libftdx.h | 36 + jtag/include/usbconn/libusb.h | 2 +- jtag/src/tap/Makefile.am | 18 +- jtag/src/tap/cable/cmd_xfer.c | 323 ++++ jtag/src/tap/cable/cmd_xfer.h | 61 + jtag/src/tap/cable/ft2232.c | 2421 +++++++++++++------------- jtag/src/tap/cable/generic_usbconn.c | 82 +- jtag/src/tap/cable/generic_usbconn.h | 2 +- jtag/src/tap/cable/usbblaster.c | 241 ++- jtag/src/tap/parport.c | 26 +- jtag/src/tap/parport/ftd2xx.c | 490 ------ jtag/src/tap/parport/ftdi.c | 602 ------- jtag/src/tap/usbconn.c | 36 +- jtag/src/tap/usbconn/libftd2xx.c | 482 +++++ jtag/src/tap/usbconn/libftdi.c | 542 ++++++ jtag/src/tap/usbconn/libusb.c | 12 +- 20 files changed, 3086 insertions(+), 2404 deletions(-) create mode 100644 jtag/include/usbconn/libftdx.h create mode 100644 jtag/src/tap/cable/cmd_xfer.c create mode 100644 jtag/src/tap/cable/cmd_xfer.h delete mode 100644 jtag/src/tap/parport/ftd2xx.c delete mode 100644 jtag/src/tap/parport/ftdi.c create mode 100644 jtag/src/tap/usbconn/libftd2xx.c create mode 100644 jtag/src/tap/usbconn/libftdi.c diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 11bead17..7a244a8f 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,3 +1,19 @@ +2008-05-20 Arnim Laeuger + + * src/tap/cable/ft2232.c, src/tap/cable/usbblaster.c: + run on top of usbconn drivers + * src/tap/cable/cmd_xfer.c, src/tap/cable/cmd_xfer.h: + provide command queueing functions to ft2232.c and usbblaster.c + * src/tap/usbconn/libftd2xx.c, src/tap/usbconn/libftdi.c, + include/usbconn/libftdx.h, src/tap/parport/ftdi.c, + src/tap/parport/ftd2xx.c, src/tap/parport.c, src/tap/Makefile.am, + src/tap/usbconn.c, src/tap/cable/generic_usbconn.c, + src/tap/cable/generic_usbconn.h, doc/UrJTAG.txt: + ftdi & ftd2xx drivers ported from parport to usbconn + * src/tap/usbconn/libusb.c, include/usbconn.h: added read and write + * configure.ac: --enable-parport renamed to --enable-lowlevel + respective renaming for Makefile and C macros + 2008-05-13 Kolja Waschk * src/tap/cable/generic_usbconn.c: Read VID/PID as hexadecimal, fixes diff --git a/jtag/configure.ac b/jtag/configure.ac index d36434ba..4a76f7ab 100644 --- a/jtag/configure.ac +++ b/jtag/configure.ac @@ -487,45 +487,45 @@ CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [wiggler], [ENABLE_CA CHECK_DRIVER([$cabledrivers], [enabled_cable_drivers], [xpc], [ENABLE_CABLE_XPC]) -# Enable parport drivers -AC_DEFUN([DEF_ENABLE_PARPORTDRIVERS], [\ +# Enable lowlevel drivers +AC_DEFUN([DEF_ENABLE_LOWLEVELDRIVERS], [\ direct ftdi ftd2xx ppdev ppi]) -AC_ARG_ENABLE(parport, -[AS_HELP_STRING([--enable-parport], [Enable default set or specific parport drivers:])] -[AS_HELP_STRING([], ['default' enables:])] -[AS_HELP_STRING([],DEF_ENABLE_PARPORTDRIVERS)] +AC_ARG_ENABLE(lowlevel, +[AS_HELP_STRING([--enable-lowlevel], [Enable default set or specific lowlevel drivers:])] +[AS_HELP_STRING([], ['default' enables:])] +[AS_HELP_STRING([],DEF_ENABLE_LOWLEVELDRIVERS)] , [AS_CASE([${enableval}], - [yes], [parportdrivers=default], - [no], [parportdrivers=none], - [none], [parportdrivers=none], - [parportdrivers=`echo ${enableval} | $SED -e 's/,/ /g'`])], -[parportdrivers=default]) -# expand 'default' to default enabled parportdrivers -parportdrivers=`echo ${parportdrivers} | $SED -e "s/default/DEF_ENABLE_PARPORTDRIVERS/"` -# automatically disable parport drivers when a required feature is not available + [yes], [lowleveldrivers=default], + [no], [lowleveldrivers=none], + [none], [lowleveldrivers=none], + [lowleveldrivers=`echo ${enableval} | $SED -e 's/,/ /g'`])], +[lowleveldrivers=default]) +# expand 'default' to default enabled lowlevel drivers +lowleveldrivers=`echo ${lowleveldrivers} | $SED -e "s/default/DEF_ENABLE_LOWLEVELDRIVERS/"` +# automatically disable lowlevel drivers when a required feature is not available AS_IF([test "x$HAVELIBFTDI" != "xyes"], [ - parportdrivers=`echo ${parportdrivers} | $SED -e "s/ftdi//"` + lowleveldrivers=`echo ${lowleveldrivers} | $SED -e "s/ftdi//"` ]) AS_IF([test "x$HAVELIBFTD2XX" != "xyes"], [ - parportdrivers=`echo ${parportdrivers} | $SED -e "s/ftd2xx//"` + lowleveldrivers=`echo ${lowleveldrivers} | $SED -e "s/ftd2xx//"` ]) AS_IF([test "x$HAVE_LINUX_PPDEV_H" != "xyes"], [ - parportdrivers=`echo ${parportdrivers} | $SED -e "s/ppdev//"` + lowleveldrivers=`echo ${lowleveldrivers} | $SED -e "s/ppdev//"` ]) AS_IF([test "x$HAVE_DEV_PPBUS_PPI_H" != "xyes"], [ - parportdrivers=`echo ${parportdrivers} | $SED -e "s/ppi//"` + lowleveldrivers=`echo ${lowleveldrivers} | $SED -e "s/ppi//"` ]) AS_IF([test "x$HAVE_IOPERM" != "xyes" -a "x$HAVE_I386_SET_IOPERM" != "xyes"], [ - parportdrivers=`echo ${parportdrivers} | $SED -e "s/direct//"` + lowleveldrivers=`echo ${lowleveldrivers} | $SED -e "s/direct//"` ]) # -enabled_parport_drivers='' -CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [direct], [ENABLE_PARPORT_DIRECT]) -CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [ftd2xx], [ENABLE_PARPORT_FTD2XX]) -CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [ftdi], [ENABLE_PARPORT_FTDI]) -CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [ppdev], [ENABLE_PARPORT_PPDEV]) -CHECK_DRIVER([$parportdrivers], [enabled_parport_drivers], [ppi], [ENABLE_PARPORT_PPI]) +enabled_lowlevel_drivers='' +CHECK_DRIVER([$lowleveldrivers], [enabled_lowlevel_drivers], [direct], [ENABLE_LOWLEVEL_DIRECT]) +CHECK_DRIVER([$lowleveldrivers], [enabled_lowlevel_drivers], [ftd2xx], [ENABLE_LOWLEVEL_FTD2XX]) +CHECK_DRIVER([$lowleveldrivers], [enabled_lowlevel_drivers], [ftdi], [ENABLE_LOWLEVEL_FTDI]) +CHECK_DRIVER([$lowleveldrivers], [enabled_lowlevel_drivers], [ppdev], [ENABLE_LOWLEVEL_PPDEV]) +CHECK_DRIVER([$lowleveldrivers], [enabled_lowlevel_drivers], [ppi], [ENABLE_LOWLEVEL_PPI]) dnl Enable a relocatable jtag? @@ -580,5 +580,5 @@ jtag is now configured for Build BSDL subsystem : $FLAG_BSDL Bus drivers : $enabled_bus_drivers Cable drivers : $enabled_cable_drivers - Parport drivers : $enabled_parport_drivers + Lowlevel drivers : $enabled_lowlevel_drivers ]) diff --git a/jtag/doc/UrJTAG.txt b/jtag/doc/UrJTAG.txt index 5898cd08..ff4c11a3 100644 --- a/jtag/doc/UrJTAG.txt +++ b/jtag/doc/UrJTAG.txt @@ -397,13 +397,13 @@ host: ==== Driver tailoring ==== -The configure script enables all default bus, cable and parport drivers. You +The configure script enables all default bus, cable and lowlevel drivers. You can include and exclude specific drivers if required. For a list of parameters run ./configure --help -to figure out the appropriate --enable-bus, --enable-cable and --enable-parport +to figure out the appropriate --enable-bus, --enable-cable and --enable-lowlevel options. @@ -661,21 +661,26 @@ the jtag shell): UrJTAG now also supports some USB cables. Unfortunately, there is no standard for "JTAG over USB", so this support is limited to a few selected cables only. For cables based on the FT2232 chip from FTDI, the cable command has to be -given cable name, driver name, and USB Vendor and Product ID of the cable: +given cable name and optionally the driver name, USB Vendor, and Product ID of +the cable: - jtag> cable ARM-USB-OCD ftdi-mpsse 15ba:3 + jtag> cable ARM-USB-OCD vid=15ba pid=0003 driver=ftdi-mpsse -For some cables, UrJTAG knows the VID:PID and you can just say ":" +For all known cables, UrJTAG knows the VID and PID so you can just say - jtag> cable JTAGkey ftdi-mpsse : + jtag> cable ARM-USB-OCD -On Windows, if UrJTAG was compiled to use the drivers supplied by -FTDI, the command should instead look like this: +If your cable isn't detected automatically though it's listed as a known and +supported cable, feel free to report its VID and PID. It might be a different +revision and should be added to the known & tested list of cables. - jtag> cable ARM-USB-OCD ftd2xx-mpsse 15ba:3 - -The support for USB-based cables and their configuration is work -in progress; the above syntax may change (i.e. become simpler) soon. +As stated above, the driver name is not mandatory for the cable +command. UrJTAG will select the driver automatically based on UrJTAG's +configuration. In case your system provides just one of libftdi or FTD2XX +the respective driver is selected. If both libraries are available, then +FTD2XX is selected. That's simply because FTD2XX showed some performance +advantages over libftdi in the past. You can still force libftdi with the +respective parameter. ===== detect ===== @@ -1192,15 +1197,19 @@ All parport drivers present a common API for setting and reading signals. ===== usbconn ===== The usbconn drivers provide a common API to search for and connect with USB -devices. At the moment, there's only a libusb driver, but others will follow -(e.g. to communicate with FTDI chip based cables through libftdi and/or FTD2XX, -to communicate with Cypress FX2 using EZUSB.SYS or CyUSB.sys, and more). +devices. At the moment, there are drivers for libusd, libftdi and FTD2XX +(e.g. to communicate with FTDI chip based cables through libftdi and/or +FTD2XX, to communicate with Cypress FX2 using EZUSB.SYS or CyUSB.sys, and +more). +///////////////////////////////////////////////////////////////////////////// +arniml, 18-may-2008: Obsolete? In contrast to the parport API, the usbconn drivers provide only the functions for connecting, disconnecting, and for releasing ressources. The actual communication must be implemented using the underlying library's functions, e.g. usb_write from libusb, or ftdi_write from libftdi. Therefore, each driver using usbconn usually only works together with one particular usbconn driver. +///////////////////////////////////////////////////////////////////////////// ==== Bus drivers ==== diff --git a/jtag/include/usbconn.h b/jtag/include/usbconn.h index c733f06d..3f8a7543 100644 --- a/jtag/include/usbconn.h +++ b/jtag/include/usbconn.h @@ -1,5 +1,5 @@ /* - * $Id: usbconn.h 809 2007-12-04 07:06:49Z kawk $ + * $Id$ * * USB Device Connection Driver Interface * Copyright (C) 2008 K. Waschk @@ -27,6 +27,7 @@ #define USBCONN_H #include +#include typedef struct usbconn_t usbconn_t; @@ -47,6 +48,8 @@ typedef struct { void (*free)( usbconn_t * ); int (*open)( usbconn_t * ); int (*close)( usbconn_t * ); + int (*read)( usbconn_t *, uint8_t *, int ); + int (*write)( usbconn_t *, uint8_t *, int, int ); } usbconn_driver_t; struct usbconn_t { @@ -59,6 +62,8 @@ usbconn_t *usbconn_connect( const char **, int, usbconn_cable_t *); int usbconn_free( usbconn_t *conn ); int usbconn_open( usbconn_t *conn ); int usbconn_close( usbconn_t *conn ); +int usbconn_read( usbconn_t *conn, uint8_t *buf, int len ); +int usbconn_write( usbconn_t *conn, uint8_t *buf, int len, int recv ); extern usbconn_driver_t *usbconn_drivers[]; #endif /* USBCONN_H */ diff --git a/jtag/include/usbconn/libftdx.h b/jtag/include/usbconn/libftdx.h new file mode 100644 index 00000000..ba224ac1 --- /dev/null +++ b/jtag/include/usbconn/libftdx.h @@ -0,0 +1,36 @@ +/* + * $Id$ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by A. Laeuger, 2008 + * + */ + +#ifndef _USBCONN_LIBFTDX_H +#define _USBCONN_LIBFTDX_H 1 + +#define FTDX_MAXSEND 4096 + +/* Maximum chunk to receive from ftdi/ftd2xx driver. + Larger values might speed up comm, but there's an upper limit + when too many bytes are sent and the underlying libftdi or libftd2xx + don't fetch the returned data in time -> deadlock */ +#define FTDI_MAXRECV ( 4 * 64) +#define FTD2XX_MAXRECV (63 * 64) +#define FTDX_MAXRECV (FTD2XX_MAXRECV < FTDI_MAXRECV ? FTD2XX_MAXRECV : FTDI_MAXRECV) + +#endif diff --git a/jtag/include/usbconn/libusb.h b/jtag/include/usbconn/libusb.h index 4b1f95df..9cbd2234 100644 --- a/jtag/include/usbconn/libusb.h +++ b/jtag/include/usbconn/libusb.h @@ -1,5 +1,5 @@ /* - * $Id: usbconn/libusb.h,v 1.7 2003/08/19 09:05:25 telka Exp $ + * $Id$ * * Link driver for accessing USB devices via libusb * diff --git a/jtag/src/tap/Makefile.am b/jtag/src/tap/Makefile.am index a70fe950..8cea4d1c 100644 --- a/jtag/src/tap/Makefile.am +++ b/jtag/src/tap/Makefile.am @@ -41,7 +41,9 @@ libtap_a_SOURCES = \ cable/generic_usbconn.h \ cable/generic_usbconn.c \ cable/generic_parport.h \ - cable/generic_parport.c + cable/generic_parport.c \ + cable/cmd_xfer.h \ + cable/cmd_xfer.c if ENABLE_CABLE_ARCOM libtap_a_SOURCES += \ @@ -126,27 +128,27 @@ libtap_a_SOURCES += \ cable/jim.c endif -if ENABLE_PARPORT_FTDI +if ENABLE_LOWLEVEL_FTDI libtap_a_SOURCES += \ - parport/ftdi.c + usbconn/libftdi.c endif -if ENABLE_PARPORT_FTD2XX +if ENABLE_LOWLEVEL_FTD2XX libtap_a_SOURCES += \ - parport/ftd2xx.c + usbconn/libftd2xx.c endif -if ENABLE_PARPORT_DIRECT +if ENABLE_LOWLEVEL_DIRECT libtap_a_SOURCES += \ parport/direct.c endif -if ENABLE_PARPORT_PPDEV +if ENABLE_LOWLEVEL_PPDEV libtap_a_SOURCES += \ parport/ppdev.c endif -if ENABLE_PARPORT_PPI +if ENABLE_LOWLEVEL_PPI libtap_a_SOURCES += \ parport/ppi.c endif diff --git a/jtag/src/tap/cable/cmd_xfer.c b/jtag/src/tap/cable/cmd_xfer.c new file mode 100644 index 00000000..756284d5 --- /dev/null +++ b/jtag/src/tap/cable/cmd_xfer.c @@ -0,0 +1,323 @@ +/* + * $Id$ + * + * Generic command buffer handler. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger, 2008. + * + */ + +#include +#include + +#include "sysdep.h" + +#include "generic.h" +#include "generic_usbconn.h" + +#include "cmd_xfer.h" + + +/***************************************************************************** + * extend_cmd_buffer( cmd ) + * + * Extends the buffer of the given command if a new byte wouldn't fit into + * the current buffer size. + * + * cmd : pointer to cx_cmd_t + * + * Return value: + * 0 : Error occured, not enough memory + * 1 : All ok + * + ****************************************************************************/ +static int +extend_cmd_buffer( cx_cmd_t *cmd ) +{ + /* check size of cmd buffer and increase it if not sufficient */ + if (cmd->buf_pos >= cmd->buf_len) + { + cmd->buf_len *= 2; + if (cmd->buf) + cmd->buf = (uint8_t *)realloc( cmd->buf, cmd->buf_len ); + } + + return cmd->buf ? 1 : 0; +} + + +/***************************************************************************** + * cx_cmd_push( cmd, d ) + * + * Pushes the byte value d to the buffer of the current last command. + * + * cmd_root : pointer to cx_cmd_root_t struct + * d : new value to be pushed + * + * Return value: + * 0 : Error occured + * 1 : All ok + * + ****************************************************************************/ +int +cx_cmd_push( cx_cmd_root_t *cmd_root, uint8_t d ) +{ + cx_cmd_t *cmd = cmd_root->last; + + if (!cmd) + return 0; + + if (!extend_cmd_buffer( cmd )) + return 0; + + cmd->buf[cmd->buf_pos++] = d; + + return 1; +} + + +/***************************************************************************** + * cx_cmd_dequeue( cmd_root ) + * + * Dequeues the first command. + * + * cmd_root : pointer to cx_cmd_root_t parameter struct + * + * Return value: + * NULL : Error occured + * <>NULL : All ok, pointer to dequeued cx_cmd_t + * + ****************************************************************************/ +cx_cmd_t * +cx_cmd_dequeue( cx_cmd_root_t *cmd_root ) +{ + cx_cmd_t *cmd = cmd_root->first; + + if (cmd) + { + if ((cmd_root->first = cmd->next) == NULL) + cmd_root->last = NULL; + cmd->next = NULL; + } + + return cmd; +} + + +/***************************************************************************** + * cx_cmd_free( cmd ) + * + * Frees allocated memory of specified cmd structure. + * + * cmd : pointer to cx_cmd_t + * + * Return value: + * none + * + ****************************************************************************/ +void +cx_cmd_free( cx_cmd_t *cmd ) +{ + if (cmd) + { + if (cmd->buf) + free( cmd->buf ); + free( cmd ); + } +} + + +/***************************************************************************** + * cx_cmd_queue( cmd_root, to_recv ) + * + * Allocates a new cx_cmd_t and queues it at the end of the command + * queue. The value of to_recv will be stored in the new cmd element, + * set to 0 if this command will not generate receive bytes. + * + * cmd_root : pointer to cx_cmd_root_t parameter struct + * to_recv : number of receive bytes that this command will generate + * + * Return value: + * NULL : Error occured + * <>NULL : All ok, pointer to allocated cx_cmd_t + * + ****************************************************************************/ +cx_cmd_t * +cx_cmd_queue( cx_cmd_root_t *cmd_root, uint32_t to_recv ) +{ + cx_cmd_t *cmd = (cx_cmd_t *)malloc( sizeof( cx_cmd_t ) ); + + if (cmd) + { + cmd->buf_len = 64; + if ((cmd->buf = (uint8_t *)malloc( cmd->buf_len )) == NULL) + { + free( cmd ); + cmd = NULL; + } + else + { + cmd->buf_pos = 0; + cmd->to_recv = to_recv; + cmd->next = NULL; + if (!cmd_root->first) + cmd_root->first = cmd; + if (cmd_root->last) + cmd_root->last->next = cmd; + cmd_root->last = cmd; + } + } + + return cmd; +} + + +/***************************************************************************** + * cx_cmd_init( cmd_root ) + * + * Initializes the command root structure. + * + * cmd_root : pointer to cx_cmd_root_t + * + * Return value: + * none + * + ****************************************************************************/ +void +cx_cmd_init( cx_cmd_root_t *cmd_root ) +{ + cmd_root->first = NULL; + cmd_root->last = NULL; +} + + +/***************************************************************************** + * cx_cmd_deinit( cmd_root ) + * + * Deinitialzes and frees all elements from the command root structure. + * + * cmd_root : pointer to cx_cmd_root_t + * + * Return value: + * none + * + ****************************************************************************/ +void +cx_cmd_deinit( cx_cmd_root_t *cmd_root ) +{ + cx_cmd_t *cmd; + while (cmd_root->first) + { + cmd = cx_cmd_dequeue( cmd_root ); + cx_cmd_free( cmd ); + } +} + + +/***************************************************************************** + * cx_xfer( cmd_root, out_cmd, cable, how_much ) + * + * Unrolls the queued commands and posts their payload to the usbconn driver. + * NB: usbconn_write will buffer the accumulated payload until usbconn_read + * is called. + * + * Flushing of the posted payload bytes is triggered when how_much + * requests to do so or if receive bytes are expected. + * + * cmd_root : pointer to cx_cmd_root_t struct + * out_cmd : pointer to cx_cmd_t for an optional command that is appended + * to send buffer in case commands have been scheduled that + * yield return/receive data from the device + * cable : current cable_t + * how_much : cable_flush_amount_t value specifying the flush strategy + * + * Return value: + * none + * + ****************************************************************************/ +void +cx_xfer( cx_cmd_root_t *cmd_root, const cx_cmd_t *out_cmd, + cable_t *cable, cable_flush_amount_t how_much ) +{ + cx_cmd_t *cmd = cx_cmd_dequeue( cmd_root ); + uint32_t bytes_to_recv; + + bytes_to_recv = 0; + + while (cmd) + { + /* Step 1: copy command bytes buffered for sending them later + through the usbconn driver */ + bytes_to_recv += cmd->to_recv; + /* write command data (buffered) */ + usbconn_write( cable->link.usb, cmd->buf, cmd->buf_pos, cmd->to_recv ); + cx_cmd_free( cmd ); + cmd = cx_cmd_dequeue( cmd_root ); + } + + /* it's possible for the caller to define an extra command that is + appended right before sending commands to the device in case output + data is expected */ + if (bytes_to_recv && out_cmd) + { + usbconn_write( cable->link.usb, out_cmd->buf, out_cmd->buf_pos, out_cmd->to_recv ); + bytes_to_recv += out_cmd->to_recv; + } + + if (bytes_to_recv || (how_much != TO_OUTPUT)) + { + /* Step 2: flush scheduled bytes */ + usbconn_read( cable->link.usb, NULL, 0 ); + + bytes_to_recv = 0; + } +} + + +/***************************************************************************** + * cx_xfer_recv( cable ) + * + * Extracts the byte at the current position from the receive buffer. + * + * cable : pointer to the current cable struct + * + * Return value: + * Byte value from receive buffer + * + ****************************************************************************/ +uint8_t +cx_xfer_recv( cable_t *cable ) +{ + uint8_t buf; + + if (usbconn_read( cable->link.usb, &buf, 1 ) == 1) + { + return buf; + } + else + return 0; +} + + +/* + Local Variables: + mode:C + c-default-style:gnu + indent-tabs-mode:nil + End: +*/ diff --git a/jtag/src/tap/cable/cmd_xfer.h b/jtag/src/tap/cable/cmd_xfer.h new file mode 100644 index 00000000..c10c2b2a --- /dev/null +++ b/jtag/src/tap/cable/cmd_xfer.h @@ -0,0 +1,61 @@ +/* + * $Id$ + * + * Generic command buffer handler. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger, 2008. + * + */ + +#ifndef CMD_XFER_H +#define CMD_XFER_H + +#include "sysdep.h" + +#include + +/* description of a command + the buffer can contain one or more commands if receive count + is zero for all of them */ +typedef struct cx_cmd cx_cmd_t; +struct cx_cmd { + cx_cmd_t *next; + uint32_t buf_len; + uint32_t buf_pos; + uint8_t *buf; + uint32_t to_recv; +}; + +struct cx_cmd_root { + cx_cmd_t *first; + cx_cmd_t *last; +}; +typedef struct cx_cmd_root cx_cmd_root_t; + +int cx_cmd_push( cx_cmd_root_t *cmd_root, uint8_t d); +cx_cmd_t *cx_cmd_dequeue( cx_cmd_root_t *cmd_root ); +void cx_cmd_free( cx_cmd_t *cmd ); +cx_cmd_t *cx_cmd_queue( cx_cmd_root_t *cmd_root, uint32_t to_recv ); +void cx_cmd_init( cx_cmd_root_t *cmd_root ); +void cx_cmd_deinit( cx_cmd_root_t *cmd_root ); + +void cx_xfer( cx_cmd_root_t *cmd_root, const cx_cmd_t *out_cmd, + cable_t *cable, cable_flush_amount_t how_much ); +uint8_t cx_xfer_recv( cable_t *cable ); + +#endif /* CMD_XFER_H */ diff --git a/jtag/src/tap/cable/ft2232.c b/jtag/src/tap/cable/ft2232.c index ed0e382f..fcd44923 100644 --- a/jtag/src/tap/cable/ft2232.c +++ b/jtag/src/tap/cable/ft2232.c @@ -30,22 +30,27 @@ #include "sysdep.h" #include -#include #include #include #include "generic.h" +#include "generic_usbconn.h" -/* Maximum chunk to write to parport driver. - Larger values might speed up comm, but there's an upper limit - when too many bytes are sent and the underlying libftdi or libftd2xx - don't fetch the returned data in time -> deadlock */ -#define MAXRECV_FTD2XX (63 * 64) -#define MAXRECV_FTDI ( 4 * 64) +#include "usbconn.h" +#include "usbconn/libftdx.h" + +#include "cmd_xfer.h" /* Maximum TCK frequency of FT2232 */ #define FT2232_MAX_TCK_FREQ 6000000 +/* The default driver if not specified otherwise during connect */ +#ifdef ENABLE_LOWLEVEL_FTD2XX +#define DEFAULT_DRIVER "ftd2xx-mpsse" +#else +#define DEFAULT_DRIVER "ftdi-mpsse" +#endif + /* repeat the definitions for MPSSE command processor here since we cannot rely on the existence of ftdih. even though @@ -148,1421 +153,1485 @@ #define BITMASK_SIGNALYZER_nSRST (1 << BIT_SIGNALYZER_nSRST) + typedef struct { - uint32_t mpsse_frequency; - - /* this driver issues several "Set Data Bits Low Byte" commands - here is the place where cable specific values can be stored - that are used each time this command is issued */ - uint8_t low_byte_value; - uint8_t low_byte_dir; - - /* this driver supports TRST control on high byte only - set the variables below with value/direction for active and inactive TRST line - static settings for other high byte signals must be entered here as well */ - uint8_t high_byte_value_trst_active; - uint8_t high_byte_value_trst_inactive; - uint8_t high_byte_dir; - - /* variables to save last TDO value - this acts as a cache to prevent multiple "Read Data Bits Low" transfer - over USB for ft2232_get_tdo */ - unsigned int last_tdo_valid; - unsigned int last_tdo; - - /* queue buffers */ - uint32_t send_buffer_len; - uint32_t to_send; - uint16_t *send_buffer; - uint32_t recv_buffer_len; - uint32_t to_recv; - uint32_t recv_idx; - uint8_t *recv_buffer; - uint16_t maxrecv; + uint32_t mpsse_frequency; + + /* this driver issues several "Set Data Bits Low Byte" commands + here is the place where cable specific values can be stored + that are used each time this command is issued */ + uint8_t low_byte_value; + uint8_t low_byte_dir; + + /* this driver supports TRST control on high byte only + set the variables below with value/direction for active and inactive TRST line + static settings for other high byte signals must be entered here as well */ + uint8_t high_byte_value_trst_active; + uint8_t high_byte_value_trst_inactive; + uint8_t high_byte_dir; + + /* variables to save last TDO value + this acts as a cache to prevent multiple "Read Data Bits Low" transfer + over USB for ft2232_get_tdo */ + unsigned int last_tdo_valid; + unsigned int last_tdo; + + cx_cmd_root_t cmd_root; } params_t; -static int -extend_send_buffer( params_t *params ) -{ - /* check size of send_buffer and increase it if not sufficient */ - if (params->to_send >= params->send_buffer_len) { - params->send_buffer_len *= 2; - params->send_buffer = (uint16_t *)realloc( params->send_buffer, params->send_buffer_len * sizeof(uint16_t) ); - } - - return params->send_buffer ? 1 : 0; -} - - -static void -push_recv_cmd( params_t *params, uint16_t num_recv ) -{ - extend_send_buffer( params ); - - /* set MSB to flag this as a header of a receive command */ - params->send_buffer[params->to_send++] = (1 << 15) | num_recv; - params->to_recv += num_recv; -} - - -static void -push_to_send( params_t *params, uint8_t d ) -{ - extend_send_buffer( params ); - - params->send_buffer[params->to_send++] = d; -} - - -static void -send_and_receive( cable_t *cable, cable_flush_amount_t how_much ) -{ - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - uint32_t bytes_sent, bytes_to_recv, bytes_recvd; - uint16_t *send_idx; - uint8_t *recv_idx; - - /* TODO: move down before receive routine */ - if (params->to_recv > params->recv_buffer_len) { - free( params->recv_buffer ); - params->recv_buffer = (uint8_t *)malloc( params->to_recv ); - } - - send_idx = params->send_buffer; - bytes_sent = 0; - recv_idx = params->recv_buffer; - bytes_recvd = 0; - bytes_to_recv = 0; - - while (bytes_sent < params->to_send) { - - /* Step 1: send scheduled bytes through the parport driver */ - while (bytes_sent < params->to_send) { - /* check for receive command header */ - if (*send_idx & 0x8000) { - uint16_t num_recv = *send_idx & 0x7fff; - - if (bytes_to_recv + num_recv > params->maxrecv) { - /* suspend sending since we can't handle the receive data - of this command */ - break; - } - - /* eat up entry */ - send_idx++; - bytes_sent++; - - bytes_to_recv += num_recv; - } - - parport_set_data( p, *send_idx & 0xff ); - send_idx++; - bytes_sent++; - } - - /* the SEND_IMMEDIATE command will trigger the ft2232 to send - its bytes immediately without waiting for the latency timeout */ - if (bytes_to_recv) - parport_set_data( p, SEND_IMMEDIATE ); - - if (bytes_to_recv || (how_much != TO_OUTPUT)) { - /* Step 2: flush parport */ - parport_set_control( p, 1 ); // flush - parport_set_control( p, 0 ); // noflush - - /* Step 3: receive answers */ - while (bytes_to_recv) { - *recv_idx = parport_get_data( p ); - recv_idx++; - bytes_to_recv--; - bytes_recvd++; - } - } - } - - params->recv_idx = 0; - params->to_recv = bytes_recvd; - params->to_send = 0; -} - - -static uint8_t -pop_to_recv( params_t *params ) -{ - if (params->to_recv == 0) { - printf( _("Error: Receive buffer underrun %s line %d\n"), __FILE__, __LINE__ ); - return 0; - } - - params->to_recv--; - return params->recv_buffer[params->recv_idx++]; -} +static const uint8_t imm_buf[1] = {SEND_IMMEDIATE}; +static const cx_cmd_t imm_cmd = {NULL, 1, 1, (uint8_t *)imm_buf, 0}; static void ft2232_set_frequency( cable_t *cable, uint32_t new_frequency ) { - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); - if (!new_frequency || new_frequency > FT2232_MAX_TCK_FREQ) - new_frequency = FT2232_MAX_TCK_FREQ; + if (!new_frequency || new_frequency > FT2232_MAX_TCK_FREQ) + new_frequency = FT2232_MAX_TCK_FREQ; - cable->frequency = new_frequency; + cable->frequency = new_frequency; - /* update ft2232 frequency if cable setting changed */ - if (new_frequency != params->mpsse_frequency) { - uint32_t div; + /* update ft2232 frequency if cable setting changed */ + if (new_frequency != params->mpsse_frequency) + { + uint32_t div; - div = FT2232_MAX_TCK_FREQ / new_frequency; - if (FT2232_MAX_TCK_FREQ % new_frequency) - div++; + div = FT2232_MAX_TCK_FREQ / new_frequency; + if (FT2232_MAX_TCK_FREQ % new_frequency) + div++; - if (div >= (1 << 16)) { - div = (1 << 16) - 1; - printf( _("Warning: Setting lowest supported frequency for FT2232: %d\n"), FT2232_MAX_TCK_FREQ/div ); - } + if (div >= (1 << 16)) + { + div = (1 << 16) - 1; + printf( _("Warning: Setting lowest supported frequency for FT2232: %d\n"), FT2232_MAX_TCK_FREQ/div ); + } - /* send new divisor to device */ - div -= 1; - push_to_send( params, TCK_DIVISOR ); - push_to_send( params, div & 0xff ); - push_to_send( params, (div >> 8) & 0xff ); + /* send new divisor to device */ + div -= 1; + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, TCK_DIVISOR ); + cx_cmd_push( cmd_root, div & 0xff ); + cx_cmd_push( cmd_root, (div >> 8) & 0xff ); - send_and_receive( cable, COMPLETELY ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); - params->mpsse_frequency = FT2232_MAX_TCK_FREQ / (div + 1); - } + params->mpsse_frequency = FT2232_MAX_TCK_FREQ / (div + 1); + } } static int ft2232_generic_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); - if (parport_open( p )) - return -1; + if (usbconn_open( cable->link.usb )) return -1; - /* safe default values */ - params->low_byte_value = 0; - params->low_byte_dir = 0; + /* safe default values */ + params->low_byte_value = 0; + params->low_byte_dir = 0; - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - /* Set Data Bits High Byte */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = 0; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); + /* Set Data Bits High Byte */ + params->high_byte_value_trst_active = 0; + params->high_byte_value_trst_inactive = 0; + params->high_byte_dir = 0; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - params->last_tdo_valid = 0; + params->last_tdo_valid = 0; - return 0; + return 0; } static int ft2232_jtagkey_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - if (parport_open( p )) - return -1; - - /* static low byte value and direction: - set nOE to '0' -> activate output enables */ - params->low_byte_value = 0; - params->low_byte_dir = BITMASK_JTAGKEY_nOE; - - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - /* Set Data Bits High Byte - default: - TRST_N_OUT = 1 - TRST_N_OE_N = 0 - SRST_N_OUT = 1 - SRST_N_OE_N = 0 */ - params->high_byte_value_trst_active = BITMASK_JTAGKEY_SRST_N_OUT; - params->high_byte_value_trst_inactive = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OUT; - params->high_byte_dir = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_TRST_N_OE_N | - BITMASK_JTAGKEY_SRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OE_N; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, 0 ); - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); - - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + if (usbconn_open( cable->link.usb )) return -1; + + /* static low byte value and direction: + set nOE to '0' -> activate output enables */ + params->low_byte_value = 0; + params->low_byte_dir = BITMASK_JTAGKEY_nOE; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + /* Set Data Bits High Byte + default: + TRST_N_OUT = 1 + TRST_N_OE_N = 0 + SRST_N_OUT = 1 + SRST_N_OE_N = 0 */ + params->high_byte_value_trst_active = BITMASK_JTAGKEY_SRST_N_OUT; + params->high_byte_value_trst_inactive = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OUT; + params->high_byte_dir = BITMASK_JTAGKEY_TRST_N_OUT + | BITMASK_JTAGKEY_TRST_N_OE_N + | BITMASK_JTAGKEY_SRST_N_OUT + | BITMASK_JTAGKEY_SRST_N_OE_N; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + + params->last_tdo_valid = 0; + + return 0; } static int ft2232_armusbocd_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - if (parport_open( p )) - return -1; - - /* static low byte value and direction: - set nOE to '0' -> activate output enables */ - params->low_byte_value = 0; - params->low_byte_dir = BITMASK_ARMUSBOCD_nOE; - - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - /* Set Data Bits High Byte - default: - TRST = 1 - TRST buffer enable = 0 - TSRST = 1 - RED LED on */ - params->high_byte_value_trst_active = BITMASK_ARMUSBOCD_nTSRST | - BITMASK_ARMUSBOCD_RED_LED; - params->high_byte_value_trst_inactive = BITMASK_ARMUSBOCD_nTRST | - BITMASK_ARMUSBOCD_nTSRST | - BITMASK_ARMUSBOCD_RED_LED; - params->high_byte_dir = BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTRST_nOE | - BITMASK_ARMUSBOCD_nTSRST | - BITMASK_ARMUSBOCD_RED_LED; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, 0 ); - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); - - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + if (usbconn_open( cable->link.usb )) return -1; + + /* static low byte value and direction: + set nOE to '0' -> activate output enables */ + params->low_byte_value = 0; + params->low_byte_dir = BITMASK_ARMUSBOCD_nOE; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + /* Set Data Bits High Byte + default: + TRST = 1 + TRST buffer enable = 0 + TSRST = 1 + RED LED on */ + params->high_byte_value_trst_active = BITMASK_ARMUSBOCD_nTSRST + | BITMASK_ARMUSBOCD_RED_LED; + params->high_byte_value_trst_inactive = BITMASK_ARMUSBOCD_nTRST + | BITMASK_ARMUSBOCD_nTSRST + | BITMASK_ARMUSBOCD_RED_LED; + params->high_byte_dir = BITMASK_ARMUSBOCD_nTRST + | BITMASK_ARMUSBOCD_nTRST_nOE + | BITMASK_ARMUSBOCD_nTSRST + | BITMASK_ARMUSBOCD_RED_LED; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + + params->last_tdo_valid = 0; + + return 0; } static int ft2232_bfin_ujtag_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - if (parport_open( p )) - return -1; - - /* safe default values */ - params->low_byte_value = 0; - params->low_byte_dir = 0; - - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - /* Set Data Bits High Byte */ - params->high_byte_value_trst_active = BITMASK_BFIN_UJTAG_nLED; - params->high_byte_value_trst_inactive = BITMASK_BFIN_UJTAG_nTRST; - params->high_byte_dir = BITMASK_BFIN_UJTAG_nTRST | BITMASK_BFIN_UJTAG_nLED; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, 0 ); - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); - - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + if (usbconn_open( cable->link.usb )) return -1; + + /* safe default values */ + params->low_byte_value = 0; + params->low_byte_dir = 0; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + /* Set Data Bits High Byte */ + params->high_byte_value_trst_active = BITMASK_BFIN_UJTAG_nLED; + params->high_byte_value_trst_inactive = BITMASK_BFIN_UJTAG_nTRST; + params->high_byte_dir = BITMASK_BFIN_UJTAG_nTRST | BITMASK_BFIN_UJTAG_nLED; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + + params->last_tdo_valid = 0; + + return 0; } static int ft2232_oocdlinks_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - if (parport_open( p )) - return -1; - - /* static low byte value and direction */ - params->low_byte_value = 0; - params->low_byte_dir = 0; - - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - /* Set Data Bits High Byte - default: - TRST = 1 - TRST buffer enable = 0 - SRST = 1 - SRST buffer enable = 0 */ - params->high_byte_value_trst_active = BITMASK_OOCDLINKS_nSRST; - params->high_byte_value_trst_inactive = BITMASK_OOCDLINKS_nTRST | - BITMASK_OOCDLINKS_nSRST; - params->high_byte_dir = BITMASK_OOCDLINKS_nTRST | BITMASK_OOCDLINKS_nTRST_nOE | - BITMASK_OOCDLINKS_nSRST | BITMASK_OOCDLINKS_nSRST_nOE; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, 0 ); - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); - - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + if (usbconn_open( cable->link.usb )) return -1; + + /* static low byte value and direction */ + params->low_byte_value = 0; + params->low_byte_dir = 0; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + /* Set Data Bits High Byte + default: + TRST = 1 + TRST buffer enable = 0 + SRST = 1 + SRST buffer enable = 0 */ + params->high_byte_value_trst_active = BITMASK_OOCDLINKS_nSRST; + params->high_byte_value_trst_inactive = BITMASK_OOCDLINKS_nTRST + | BITMASK_OOCDLINKS_nSRST; + params->high_byte_dir = BITMASK_OOCDLINKS_nTRST + | BITMASK_OOCDLINKS_nTRST_nOE + | BITMASK_OOCDLINKS_nSRST + | BITMASK_OOCDLINKS_nSRST_nOE; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + + params->last_tdo_valid = 0; + + return 0; } static int ft2232_turtelizer2_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - if (parport_open( p )) - return -1; - - /* static low byte value and direction: - set nJTAGOE to '0' -> activate output enables - set RST to 0 -> inactive nSRST */ - params->low_byte_value = 0; - params->low_byte_dir = BITMASK_TURTELIZER2_nJTAGOE | BITMASK_TURTELIZER2_RST; - - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - /* Set Data Bits High Byte - default: - TX1LED on - RX1LED on */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); - - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + if (usbconn_open( cable->link.usb )) return -1; + + /* static low byte value and direction: + set nJTAGOE to '0' -> activate output enables + set RST to 0 -> inactive nSRST */ + params->low_byte_value = 0; + params->low_byte_dir = BITMASK_TURTELIZER2_nJTAGOE | BITMASK_TURTELIZER2_RST; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + /* Set Data Bits High Byte + default: + TX1LED on + RX1LED on */ + params->high_byte_value_trst_active = 0; + params->high_byte_value_trst_inactive = 0; + params->high_byte_dir = BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + + params->last_tdo_valid = 0; + + return 0; } static int ft2232_usbtojtagif_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - if (parport_open( p )) - return -1; - - /* static low byte value and direction: - nTRST = 1, RST = 1, DBGRQ = 0 */ - params->low_byte_value = BITMASK_USBTOJTAGIF_nTRST | BITMASK_USBTOJTAGIF_RST; - params->low_byte_dir = BITMASK_USBTOJTAGIF_nTRST | BITMASK_USBTOJTAGIF_RST | BITMASK_USBTOJTAGIF_DBGRQ; - - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - /* Set Data Bits High Byte - default: - RxLED on - TxLED on */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); - - /* I-couplers can only work up to 3 MHz - ref. http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html */ - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ/2 ); - - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + if (usbconn_open( cable->link.usb )) return -1; + + /* static low byte value and direction: + nTRST = 1, RST = 1, DBGRQ = 0 */ + params->low_byte_value = BITMASK_USBTOJTAGIF_nTRST | BITMASK_USBTOJTAGIF_RST; + params->low_byte_dir = BITMASK_USBTOJTAGIF_nTRST | BITMASK_USBTOJTAGIF_RST | BITMASK_USBTOJTAGIF_DBGRQ; + + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + /* Set Data Bits High Byte + default: + RxLED on + TxLED on */ + params->high_byte_value_trst_active = 0; + params->high_byte_value_trst_inactive = 0; + params->high_byte_dir = BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); + + /* I-couplers can only work up to 3 MHz + ref. http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html */ + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ/2 ); + + params->last_tdo_valid = 0; + + return 0; } static int ft2232_signalyzer_init( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); - if (parport_open( p )) - return -1; + if (usbconn_open( cable->link.usb )) return -1; - /* static low byte value and direction: - nTRST = 1, RST = 1, DBGRQ = 0 */ - params->low_byte_value = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST; - params->low_byte_dir = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST; + /* static low byte value and direction: + nTRST = 1, RST = 1, DBGRQ = 0 */ + params->low_byte_value = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST; + params->low_byte_dir = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST; - /* Set Data Bits Low Byte - TCK = 0, TMS = 1, TDI = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | BITMASK_TMS ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + /* Set Data Bits Low Byte + TCK = 0, TMS = 1, TDI = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - /* Set Data Bits High Byte */ - params->high_byte_value_trst_active = 0; - params->high_byte_value_trst_inactive = 0; - params->high_byte_dir = 0; - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); + /* Set Data Bits High Byte */ + params->high_byte_value_trst_active = 0; + params->high_byte_value_trst_inactive = 0; + params->high_byte_dir = 0; + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); - ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); + ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); - params->last_tdo_valid = 0; + params->last_tdo_valid = 0; - return 0; + return 0; } static void ft2232_generic_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, 0 ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, 0 ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_jtagkey_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - disable output drivers */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_JTAGKEY_nOE ); - push_to_send( params, BITMASK_JTAGKEY_nOE ); - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_JTAGKEY_nOE ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - disable output drivers */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_TRST_N_OE_N | - BITMASK_JTAGKEY_SRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OE_N ); - push_to_send( params, BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_TRST_N_OE_N | - BITMASK_JTAGKEY_SRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OE_N ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_TRST_N_OE_N | - BITMASK_JTAGKEY_SRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OE_N ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + disable output drivers */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_JTAGKEY_nOE ); + cx_cmd_push( cmd_root, BITMASK_JTAGKEY_nOE ); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_JTAGKEY_nOE ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + disable output drivers */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + BITMASK_JTAGKEY_TRST_N_OUT + | BITMASK_JTAGKEY_TRST_N_OE_N + | BITMASK_JTAGKEY_SRST_N_OUT + | BITMASK_JTAGKEY_SRST_N_OE_N ); + cx_cmd_push( cmd_root, + BITMASK_JTAGKEY_TRST_N_OUT + | BITMASK_JTAGKEY_TRST_N_OE_N + | BITMASK_JTAGKEY_SRST_N_OUT + | BITMASK_JTAGKEY_SRST_N_OE_N ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + BITMASK_JTAGKEY_TRST_N_OUT + | BITMASK_JTAGKEY_TRST_N_OE_N + | BITMASK_JTAGKEY_SRST_N_OUT + | BITMASK_JTAGKEY_SRST_N_OE_N ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_armusbocd_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - disable output drivers */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_ARMUSBOCD_nOE ); - push_to_send( params, BITMASK_ARMUSBOCD_nOE ); - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_ARMUSBOCD_nOE ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - disable output drivers */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTRST_nOE | - BITMASK_ARMUSBOCD_nTSRST ); - push_to_send( params, BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTRST_nOE | - BITMASK_ARMUSBOCD_nTSRST | - BITMASK_ARMUSBOCD_RED_LED ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTRST_nOE | - BITMASK_ARMUSBOCD_nTSRST ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + disable output drivers */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_ARMUSBOCD_nOE ); + cx_cmd_push( cmd_root, BITMASK_ARMUSBOCD_nOE ); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_ARMUSBOCD_nOE ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + disable output drivers */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + BITMASK_ARMUSBOCD_nTRST + | BITMASK_ARMUSBOCD_nTRST_nOE + | BITMASK_ARMUSBOCD_nTSRST ); + cx_cmd_push( cmd_root, + BITMASK_ARMUSBOCD_nTRST + | BITMASK_ARMUSBOCD_nTRST_nOE + | BITMASK_ARMUSBOCD_nTSRST + | BITMASK_ARMUSBOCD_RED_LED ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + BITMASK_ARMUSBOCD_nTRST + | BITMASK_ARMUSBOCD_nTRST_nOE + | BITMASK_ARMUSBOCD_nTSRST ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_bfin_ujtag_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - disable output drivers */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, 0 ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - disable output drivers */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_BFIN_UJTAG_nTRST); - push_to_send( params, BITMASK_BFIN_UJTAG_nTRST | BITMASK_BFIN_UJTAG_nLED); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_BFIN_UJTAG_nTRST); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + disable output drivers */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + disable output drivers */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, BITMASK_BFIN_UJTAG_nTRST); + cx_cmd_push( cmd_root, BITMASK_BFIN_UJTAG_nTRST | BITMASK_BFIN_UJTAG_nLED); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, BITMASK_BFIN_UJTAG_nTRST); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_oocdlinks_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, 0 ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - disable output drivers */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_OOCDLINKS_nTRST | BITMASK_OOCDLINKS_nTRST_nOE | - BITMASK_OOCDLINKS_nSRST | BITMASK_OOCDLINKS_nSRST_nOE ); - push_to_send( params, BITMASK_OOCDLINKS_nTRST | BITMASK_OOCDLINKS_nTRST_nOE | - BITMASK_OOCDLINKS_nSRST | BITMASK_OOCDLINKS_nSRST_nOE ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_OOCDLINKS_nTRST | BITMASK_OOCDLINKS_nTRST_nOE | - BITMASK_OOCDLINKS_nSRST | BITMASK_OOCDLINKS_nSRST_nOE ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + disable output drivers */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + BITMASK_OOCDLINKS_nTRST + | BITMASK_OOCDLINKS_nTRST_nOE + | BITMASK_OOCDLINKS_nSRST + | BITMASK_OOCDLINKS_nSRST_nOE ); + cx_cmd_push( cmd_root, + BITMASK_OOCDLINKS_nTRST + | BITMASK_OOCDLINKS_nTRST_nOE + | BITMASK_OOCDLINKS_nSRST + | BITMASK_OOCDLINKS_nSRST_nOE ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + BITMASK_OOCDLINKS_nTRST + | BITMASK_OOCDLINKS_nTRST_nOE + | BITMASK_OOCDLINKS_nSRST + | BITMASK_OOCDLINKS_nSRST_nOE ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_turtelizer2_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - disable output drivers */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_TURTELIZER2_nJTAGOE ); - push_to_send( params, BITMASK_TURTELIZER2_nJTAGOE ); - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_TURTELIZER2_nJTAGOE ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - switch off LEDs */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED ); - push_to_send( params, BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, 0 ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + disable output drivers */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_TURTELIZER2_nJTAGOE ); + cx_cmd_push( cmd_root, BITMASK_TURTELIZER2_nJTAGOE ); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_TURTELIZER2_nJTAGOE ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + switch off LEDs */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED ); + cx_cmd_push( cmd_root, BITMASK_TURTELIZER2_nTX1LED | BITMASK_TURTELIZER2_nRX1LED ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_usbtojtagif_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_USBTOJTAGIF_nTRST | BITMASK_USBTOJTAGIF_RST ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - disable output drivers */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED ); - push_to_send( params, BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_USBTOJTAGIF_nTRST | BITMASK_USBTOJTAGIF_RST ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + disable output drivers */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED ); + cx_cmd_push( cmd_root, BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, BITMASK_USBTOJTAGIF_nRxLED | BITMASK_USBTOJTAGIF_nTxLED ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_signalyzer_done( cable_t *cable ) { - parport_t *p = cable->link.port; - params_t *params = (params_t *)cable->params; - - /* Set Data Bits Low Byte - set all to input */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST ); - push_to_send( params, 0 ); - - /* Set Data Bits High Byte - disable output drivers */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST ); - push_to_send( params, BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST ); - - /* Set Data Bits High Byte - set all to input */ - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, 0 ); - push_to_send( params, 0 ); - send_and_receive( cable, COMPLETELY ); - - parport_close( p ); + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + /* Set Data Bits Low Byte + set all to input */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST ); + cx_cmd_push( cmd_root, 0 ); + + /* Set Data Bits High Byte + disable output drivers */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST ); + cx_cmd_push( cmd_root, BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST ); + + /* Set Data Bits High Byte + set all to input */ + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, 0 ); + cx_cmd_push( cmd_root, 0 ); + cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); + + generic_usbconn_done( cable ); } static void ft2232_clock_schedule( cable_t *cable, int tms, int tdi, int n ) { - params_t *params = (params_t *)cable->params; - - tms = tms ? 0x7f : 0; - tdi = tdi ? 1 << 7 : 0; - - while (n > 0) { - /* Clock Data to TMS/CS Pin (no Read) */ - push_to_send( params, MPSSE_WRITE_TMS | - MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); - if (n <= 7) { - push_to_send( params, n-1 ); - n = 0; - } else { - push_to_send( params, 7-1 ); - n -= 7; - } - push_to_send( params, tdi | tms ); - } + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + tms = tms ? 0x7f : 0; + tdi = tdi ? 1 << 7 : 0; + + cx_cmd_queue( cmd_root, 0 ); + while (n > 0) + { + /* Clock Data to TMS/CS Pin (no Read) */ + cx_cmd_push( cmd_root, MPSSE_WRITE_TMS | + MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); + if (n <= 7) + { + cx_cmd_push( cmd_root, n-1 ); + n = 0; + } + else + { + cx_cmd_push( cmd_root, 7-1 ); + n -= 7; + } + cx_cmd_push( cmd_root, tdi | tms ); + } } static void ft2232_clock( cable_t *cable, int tms, int tdi, int n ) { - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; - ft2232_clock_schedule( cable, tms, tdi, n ); - send_and_receive( cable, COMPLETELY ); - params->last_tdo_valid = 0; + ft2232_clock_schedule( cable, tms, tdi, n ); + cx_xfer( &(params->cmd_root), &imm_cmd, cable, COMPLETELY ); + params->last_tdo_valid = 0; } static void ft2232_get_tdo_schedule( cable_t *cable ) { - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); - /* Read Data Bits Low Byte */ - push_recv_cmd( params, 1 ); - push_to_send( params, GET_BITS_LOW ); + /* Read Data Bits Low Byte */ + cx_cmd_queue( cmd_root, 1 ); + cx_cmd_push( cmd_root, GET_BITS_LOW ); } static int ft2232_get_tdo_finish( cable_t *cable ) { - params_t *params = (params_t *)cable->params; - int value; + params_t *params = (params_t *)cable->params; + int value; - value = ( pop_to_recv( params ) & BITMASK_TDO) ? 1 : 0; + value = ( cx_xfer_recv( cable ) & BITMASK_TDO) ? 1 : 0; - params->last_tdo = value; - params->last_tdo_valid = 1; + params->last_tdo = value; + params->last_tdo_valid = 1; - return value; + return value; } static int ft2232_get_tdo( cable_t *cable ) { - ft2232_get_tdo_schedule( cable ); - send_and_receive( cable, COMPLETELY ); - return ft2232_get_tdo_finish( cable ); + params_t *params = (params_t *)cable->params; + + ft2232_get_tdo_schedule( cable ); + cx_xfer( &(params->cmd_root), &imm_cmd, cable, COMPLETELY ); + return ft2232_get_tdo_finish( cable ); } static void ft2232_set_trst_schedule( params_t *params, int trst ) { - push_to_send( params, SET_BITS_HIGH ); - push_to_send( params, - trst == 0 ? params->high_byte_value_trst_active : params->high_byte_value_trst_inactive ); - push_to_send( params, params->high_byte_dir ); + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_HIGH ); + cx_cmd_push( cmd_root, + trst == 0 ? params->high_byte_value_trst_active : params->high_byte_value_trst_inactive ); + cx_cmd_push( cmd_root, params->high_byte_dir ); } static int ft2232_set_trst( cable_t *cable, int trst ) { - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; - ft2232_set_trst_schedule( params, trst ); - send_and_receive( cable, COMPLETELY ); - params->last_tdo_valid = 0; + ft2232_set_trst_schedule( params, trst ); + cx_xfer( &(params->cmd_root), &imm_cmd, cable, COMPLETELY ); + params->last_tdo_valid = 0; - return trst; + return trst; } static void ft2232_transfer_schedule( cable_t *cable, int len, char *in, char *out ) { - params_t *params = (params_t *)cable->params; - int in_offset = 0; - int bitwise_len; - int chunkbytes; - - /* Set Data Bits Low Byte to lower TMS for transfer - TCK = 0, TMS = 0, TDI = 0, nOE = 0 */ - push_to_send( params, SET_BITS_LOW ); - push_to_send( params, params->low_byte_value | 0 ); - push_to_send( params, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); - - - chunkbytes = len >> 3; - while (chunkbytes > 0) { - int byte_idx; - - /* reduce chunkbytes to the maximum amount we can receive in one step */ - if (out && chunkbytes > params->maxrecv) - chunkbytes = params->maxrecv; - /* restrict chunkbytes to the maximum amount that can be transferred - for one single operation */ - if (chunkbytes > (1 << 16)) - chunkbytes = 1 << 16; - - /*********************************************************************** - * Step 1: - * Determine data shifting command (bytewise). - * Either with or without read - ***********************************************************************/ - if (out) { - push_recv_cmd( params, chunkbytes ); - /* Clock Data Bytes In and Out LSB First - out on negative edge, in on positive edge */ - push_to_send( params, MPSSE_DO_READ | MPSSE_DO_WRITE | - MPSSE_LSB | MPSSE_WRITE_NEG ); - } else - /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ - push_to_send( params, MPSSE_DO_WRITE | - MPSSE_LSB | MPSSE_WRITE_NEG ); - /* set byte count */ - push_to_send( params, (chunkbytes - 1) & 0xff ); - push_to_send( params, ((chunkbytes - 1) >> 8) & 0xff ); - - - /********************************************************************* - * Step 2: - * Write TDI data in bundles of 8 bits. - *********************************************************************/ - for (byte_idx = 0; byte_idx < chunkbytes; byte_idx++) { - int bit_idx; - unsigned char b = 0; - - for (bit_idx = 1; bit_idx < 256; bit_idx <<= 1) - if (in[in_offset++]) - b |= bit_idx; - push_to_send( params, b ); - } - - /* recalc chunkbytes for next round */ - chunkbytes = (len - in_offset) >> 3; - } - - /* determine bitwise shift amount */ - bitwise_len = (len - in_offset) % 8; - if (bitwise_len > 0) { - /*********************************************************************** - * Step 3: - * Determine data shifting command (bitwise). - * Either with or without read - ***********************************************************************/ - if (out) { - push_recv_cmd( params, 1 ); - /* Clock Data Bytes In and Out LSB First - out on negative edge, in on positive edge */ - push_to_send( params, MPSSE_DO_READ | MPSSE_DO_WRITE | - MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); - } else - /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ - push_to_send( params, MPSSE_DO_WRITE | - MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); - /* determine bit count */ - push_to_send( params, bitwise_len - 1 ); - - /*********************************************************************** - * Step 4: - * Write TDI data bitwise - ***********************************************************************/ - { - int bit_idx; - unsigned char b = 0; - for (bit_idx = 1; bit_idx <= 1 << bitwise_len; bit_idx <<= 1) { - if (in[in_offset++]) - b |= bit_idx; - } - push_to_send( params, b ); - } - } - - if (out) { - /* Read Data Bits Low Byte to get current TDO, - Do this only if we'll read out data nonetheless */ - push_recv_cmd( params, 1 ); - push_to_send( params, GET_BITS_LOW ); - params->last_tdo_valid = 1; - } else - params->last_tdo_valid = 0; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + int in_offset = 0; + int bitwise_len; + int chunkbytes; + + /* Set Data Bits Low Byte to lower TMS for transfer + TCK = 0, TMS = 0, TDI = 0, nOE = 0 */ + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, SET_BITS_LOW ); + cx_cmd_push( cmd_root, params->low_byte_value | 0 ); + cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); + + + chunkbytes = len >> 3; + while (chunkbytes > 0) + { + int byte_idx; + + /* reduce chunkbytes to the maximum amount we can receive in one step */ + if (out && chunkbytes > FTDX_MAXRECV) + chunkbytes = FTDX_MAXRECV; + /* restrict chunkbytes to the maximum amount that can be transferred + for one single operation */ + if (chunkbytes > (1 << 16)) + chunkbytes = 1 << 16; + + /*********************************************************************** + * Step 1: + * Determine data shifting command (bytewise). + * Either with or without read + ***********************************************************************/ + if (out) + { + cx_cmd_queue( cmd_root, chunkbytes ); + /* Clock Data Bytes In and Out LSB First + out on negative edge, in on positive edge */ + cx_cmd_push( cmd_root, MPSSE_DO_READ | MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_WRITE_NEG ); + } + else + { + cx_cmd_queue( cmd_root, 0 ); + /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ + cx_cmd_push( cmd_root, MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_WRITE_NEG ); + } + /* set byte count */ + cx_cmd_push( cmd_root, (chunkbytes - 1) & 0xff ); + cx_cmd_push( cmd_root, ((chunkbytes - 1) >> 8) & 0xff ); + + /********************************************************************* + * Step 2: + * Write TDI data in bundles of 8 bits. + *********************************************************************/ + for (byte_idx = 0; byte_idx < chunkbytes; byte_idx++) + { + int bit_idx; + unsigned char b = 0; + + for (bit_idx = 1; bit_idx < 256; bit_idx <<= 1) + if (in[in_offset++]) + b |= bit_idx; + cx_cmd_push( cmd_root, b ); + } + + /* recalc chunkbytes for next round */ + chunkbytes = (len - in_offset) >> 3; + } + + /* determine bitwise shift amount */ + bitwise_len = (len - in_offset) % 8; + if (bitwise_len > 0) + { + /*********************************************************************** + * Step 3: + * Determine data shifting command (bitwise). + * Either with or without read + ***********************************************************************/ + if (out) + { + cx_cmd_queue( cmd_root, 1 ); + /* Clock Data Bytes In and Out LSB First + out on negative edge, in on positive edge */ + cx_cmd_push( cmd_root, MPSSE_DO_READ | MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); + } + else + { + cx_cmd_queue( cmd_root, 0 ); + /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ + cx_cmd_push( cmd_root, MPSSE_DO_WRITE | + MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG ); + } + /* determine bit count */ + cx_cmd_push( cmd_root, bitwise_len - 1 ); + + /*********************************************************************** + * Step 4: + * Write TDI data bitwise + ***********************************************************************/ + { + int bit_idx; + unsigned char b = 0; + for (bit_idx = 1; bit_idx <= 1 << bitwise_len; bit_idx <<= 1) + { + if (in[in_offset++]) + b |= bit_idx; + } + cx_cmd_push( cmd_root, b ); + } + } + + if (out) + { + /* Read Data Bits Low Byte to get current TDO, + Do this only if we'll read out data nonetheless */ + cx_cmd_queue( cmd_root, 1 ); + cx_cmd_push( cmd_root, GET_BITS_LOW ); + params->last_tdo_valid = 1; + } + else + params->last_tdo_valid = 0; } static int ft2232_transfer_finish( cable_t *cable, int len, char *out ) { - params_t *params = (params_t *)cable->params; - int bitwise_len; - int chunkbytes; - int out_offset = 0; - - chunkbytes = len >> 3; - bitwise_len = len % 8; - - if (out) { - if (chunkbytes > 0) { - uint32_t xferred; - - /********************************************************************* - * Step 5: - * Read TDO data in bundles of 8 bits if read is requested. - *********************************************************************/ - xferred = chunkbytes; - for (; xferred > 0; xferred--) { - int bit_idx; - unsigned char b; - - b = pop_to_recv( params ); - for (bit_idx = 1; bit_idx < 256; bit_idx <<= 1) - out[out_offset++] = (b & bit_idx) ? 1 : 0; - } - } - - if (bitwise_len > 0) { - /*********************************************************************** - * Step 6: - * Read TDO data bitwise if read is requested. - ***********************************************************************/ - int bit_idx; - unsigned char b; - - b = pop_to_recv( params ); - - for (bit_idx = (1 << (8 - bitwise_len)); bit_idx < 256; bit_idx <<= 1) - out[out_offset++] = (b & bit_idx) ? 1 : 0; - } - - /* gather current TDO */ - params->last_tdo = ( pop_to_recv( params ) & BITMASK_TDO) ? 1 : 0; - params->last_tdo_valid = 1; - } else - params->last_tdo_valid = 0; - - return 0; + params_t *params = (params_t *)cable->params; + int bitwise_len; + int chunkbytes; + int out_offset = 0; + + chunkbytes = len >> 3; + bitwise_len = len % 8; + + if (out) + { + if (chunkbytes > 0) + { + uint32_t xferred; + + /********************************************************************* + * Step 5: + * Read TDO data in bundles of 8 bits if read is requested. + *********************************************************************/ + xferred = chunkbytes; + for (; xferred > 0; xferred--) + { + int bit_idx; + unsigned char b; + + b = cx_xfer_recv( cable ); + for (bit_idx = 1; bit_idx < 256; bit_idx <<= 1) + out[out_offset++] = (b & bit_idx) ? 1 : 0; + } + } + + if (bitwise_len > 0) + { + /*********************************************************************** + * Step 6: + * Read TDO data bitwise if read is requested. + ***********************************************************************/ + int bit_idx; + unsigned char b; + + b = cx_xfer_recv( cable ); + + for (bit_idx = (1 << (8 - bitwise_len)); bit_idx < 256; bit_idx <<= 1) + out[out_offset++] = (b & bit_idx) ? 1 : 0; + } + + /* gather current TDO */ + params->last_tdo = ( cx_xfer_recv( cable ) & BITMASK_TDO) ? 1 : 0; + params->last_tdo_valid = 1; + } + else + params->last_tdo_valid = 0; + + return 0; } static int ft2232_transfer( cable_t *cable, int len, char *in, char *out ) { - ft2232_transfer_schedule( cable, len, in, out ); - send_and_receive( cable, COMPLETELY ); - return ft2232_transfer_finish( cable, len, out ); + params_t *params = (params_t *)cable->params; + + ft2232_transfer_schedule( cable, len, in, out ); + cx_xfer( &(params->cmd_root), &imm_cmd, cable, COMPLETELY ); + return ft2232_transfer_finish( cable, len, out ); } static void ft2232_flush( cable_t *cable, cable_flush_amount_t how_much ) { - params_t *params = (params_t *)cable->params; - - if (how_much == OPTIONALLY) return; - - while (cable->todo.num_items > 0) - { - int i, j, n; - int last_tdo_valid_schedule = params->last_tdo_valid; - int last_tdo_valid_finish = params->last_tdo_valid; - - for (j = i = cable->todo.next_item, n = 0; n < cable->todo.num_items; n++) { - - switch (cable->todo.data[i].action) { - case CABLE_CLOCK: - ft2232_clock_schedule( cable, - cable->todo.data[i].arg.clock.tms, - cable->todo.data[i].arg.clock.tdi, - cable->todo.data[i].arg.clock.n ); - last_tdo_valid_schedule = 0; - break; - - case CABLE_GET_TDO: - if (!last_tdo_valid_schedule) { - ft2232_get_tdo_schedule( cable ); - last_tdo_valid_schedule = 1; - } - break; - - case CABLE_SET_TRST: - ft2232_set_trst_schedule( params, cable->todo.data[i].arg.value.trst ); - last_tdo_valid_schedule = 0; - break; - - case CABLE_TRANSFER: - ft2232_transfer_schedule( cable, - cable->todo.data[i].arg.transfer.len, - cable->todo.data[i].arg.transfer.in, - cable->todo.data[i].arg.transfer.out ); - last_tdo_valid_schedule = params->last_tdo_valid; - break; - - default: - break; - } - - i++; - if (i >= cable->todo.max_items) - i = 0; - } - - send_and_receive( cable, how_much ); - - while (j != i) { - switch (cable->todo.data[j].action) { - case CABLE_CLOCK: - params->last_tdo_valid = last_tdo_valid_finish = 0; - break; - case CABLE_GET_TDO: - { - int tdo; - int m; - if (last_tdo_valid_finish) - tdo = params->last_tdo; - else - tdo = ft2232_get_tdo_finish( cable ); - last_tdo_valid_finish = params->last_tdo_valid; - m = cable_add_queue_item( cable, &(cable->done) ); - cable->done.data[m].action = CABLE_GET_TDO; - cable->done.data[m].arg.value.tdo = tdo; - break; - } - case CABLE_SET_TRST: - { - int m = cable_add_queue_item( cable, &(cable->done) ); - cable->done.data[m].action = CABLE_SET_TRST; - cable->done.data[m].arg.value.trst = cable->done.data[j].arg.value.trst; - params->last_tdo_valid = last_tdo_valid_finish = 0; - } - case CABLE_GET_TRST: - { - int m = cable_add_queue_item( cable, &(cable->done) ); - cable->done.data[m].action = CABLE_GET_TRST; - cable->done.data[m].arg.value.trst = 1; - break; - } - case CABLE_TRANSFER: - { - int r = ft2232_transfer_finish( cable, - cable->todo.data[j].arg.transfer.len, - cable->todo.data[j].arg.transfer.out ); - last_tdo_valid_finish = params->last_tdo_valid; - free( cable->todo.data[j].arg.transfer.in ); - if (cable->todo.data[j].arg.transfer.out) { - int m = cable_add_queue_item( cable, &(cable->done) ); - if (m < 0) - printf("out of memory!\n"); - cable->done.data[m].action = CABLE_TRANSFER; - cable->done.data[m].arg.xferred.len = cable->todo.data[j].arg.transfer.len; - cable->done.data[m].arg.xferred.res = r; - cable->done.data[m].arg.xferred.out = cable->todo.data[j].arg.transfer.out; - } - } - default: - break; - } - - j++; - if (j >= cable->todo.max_items) - j = 0; - cable->todo.num_items--; - } - - cable->todo.next_item = i; - } + params_t *params = (params_t *)cable->params; + + if (how_much == OPTIONALLY) return; + + if (cable->todo.num_items == 0) + cx_xfer( &(params->cmd_root), &imm_cmd, cable, how_much ); + + while (cable->todo.num_items > 0) + { + int i, j, n; + int last_tdo_valid_schedule = params->last_tdo_valid; + int last_tdo_valid_finish = params->last_tdo_valid; + + for (j = i = cable->todo.next_item, n = 0; n < cable->todo.num_items; n++) + { + + switch (cable->todo.data[i].action) + { + case CABLE_CLOCK: + ft2232_clock_schedule( cable, + cable->todo.data[i].arg.clock.tms, + cable->todo.data[i].arg.clock.tdi, + cable->todo.data[i].arg.clock.n ); + last_tdo_valid_schedule = 0; + break; + + case CABLE_GET_TDO: + if (!last_tdo_valid_schedule) + { + ft2232_get_tdo_schedule( cable ); + last_tdo_valid_schedule = 1; + } + break; + + case CABLE_SET_TRST: + ft2232_set_trst_schedule( params, cable->todo.data[i].arg.value.trst ); + last_tdo_valid_schedule = 0; + break; + + case CABLE_TRANSFER: + ft2232_transfer_schedule( cable, + cable->todo.data[i].arg.transfer.len, + cable->todo.data[i].arg.transfer.in, + cable->todo.data[i].arg.transfer.out ); + last_tdo_valid_schedule = params->last_tdo_valid; + break; + + default: + break; + } + + i++; + if (i >= cable->todo.max_items) + i = 0; + } + + cx_xfer( &(params->cmd_root), &imm_cmd, cable, how_much ); + + while (j != i) + { + switch (cable->todo.data[j].action) + { + case CABLE_CLOCK: + params->last_tdo_valid = last_tdo_valid_finish = 0; + break; + case CABLE_GET_TDO: + { + int tdo; + int m; + if (last_tdo_valid_finish) + tdo = params->last_tdo; + else + tdo = ft2232_get_tdo_finish( cable ); + last_tdo_valid_finish = params->last_tdo_valid; + m = cable_add_queue_item( cable, &(cable->done) ); + cable->done.data[m].action = CABLE_GET_TDO; + cable->done.data[m].arg.value.tdo = tdo; + break; + } + case CABLE_SET_TRST: + { + int m = cable_add_queue_item( cable, &(cable->done) ); + cable->done.data[m].action = CABLE_SET_TRST; + cable->done.data[m].arg.value.trst = cable->done.data[j].arg.value.trst; + params->last_tdo_valid = last_tdo_valid_finish = 0; + } + case CABLE_GET_TRST: + { + int m = cable_add_queue_item( cable, &(cable->done) ); + cable->done.data[m].action = CABLE_GET_TRST; + cable->done.data[m].arg.value.trst = 1; + break; + } + case CABLE_TRANSFER: + { + int r = ft2232_transfer_finish( cable, + cable->todo.data[j].arg.transfer.len, + cable->todo.data[j].arg.transfer.out ); + last_tdo_valid_finish = params->last_tdo_valid; + free( cable->todo.data[j].arg.transfer.in ); + if (cable->todo.data[j].arg.transfer.out) + { + int m = cable_add_queue_item( cable, &(cable->done) ); + if (m < 0) + printf("out of memory!\n"); + cable->done.data[m].action = CABLE_TRANSFER; + cable->done.data[m].arg.xferred.len = cable->todo.data[j].arg.transfer.len; + cable->done.data[m].arg.xferred.res = r; + cable->done.data[m].arg.xferred.out = cable->todo.data[j].arg.transfer.out; + } + } + default: + break; + } + + j++; + if (j >= cable->todo.max_items) + j = 0; + cable->todo.num_items--; + } + + cable->todo.next_item = i; + } } static int ft2232_connect( char *params[], cable_t *cable ) { - params_t *cable_params; - parport_t *port; - int i; - uint16_t maxrecv; - - if ( cmd_params( params ) < 3 ) { - puts( _("not enough arguments!") ); - return 1; - } - - if (strcasecmp( params[1], "ftdi-mpsse" ) == 0) { - maxrecv = MAXRECV_FTDI; - } else if (strcasecmp( params[1], "ftd2xx-mpsse" ) == 0) { - maxrecv = MAXRECV_FTD2XX; - } else { - puts( _("Wrong parport driver selected!") ); - return 1; - } - - /* search parport driver list */ - for (i = 0; parport_drivers[i]; i++) - if (strcasecmp( params[1], parport_drivers[i]->type ) == 0) - break; - if (!parport_drivers[i]) { - printf( _("Unknown port driver: %s\n"), params[1] ); - return 2; - } - - /* set up parport driver */ - port = parport_drivers[i]->connect( (const char **) ¶ms[2], - cmd_params( params ) - 2 ); - - if (port == NULL) { - printf( _("Error: Cable connection failed!\n") ); - return 3; - } + params_t *cable_params; + int result; + + cable_params = (params_t *)malloc( sizeof(params_t) ); + if (!cable_params) + { + free( cable ); + return 4; + } + + /* perform generic_usbconn_connect */ + result = generic_usbconn_connect( params, cable ); + + if (result == 0) + { + cable_params->mpsse_frequency = 0; + cable_params->last_tdo_valid = 0; + + cx_cmd_init( &(cable_params->cmd_root) ); - cable_params = (params_t *)malloc( sizeof(params_t) ); - if (!cable_params) { - free( cable ); - return 4; - } - - cable_params->mpsse_frequency = 0; - cable_params->last_tdo_valid = 0; - cable_params->send_buffer_len = 1024; - cable_params->to_send = 0; - cable_params->send_buffer = (uint16_t *)malloc( cable_params->send_buffer_len * sizeof(uint16_t) ); - cable_params->recv_buffer_len = 1024; - cable_params->to_recv = 0; - cable_params->recv_idx = 0; - cable_params->recv_buffer = (uint8_t *)malloc( cable_params->recv_buffer_len ); - cable_params->maxrecv = maxrecv; - - cable->link.port = port; - cable->params = cable_params; - cable->chain = NULL; - - return 0; + /* exchange generic cable parameters with our private parameter set */ + free( cable->params ); + cable->params = cable_params; + } + + return result; } static void ft2232_cable_free( cable_t *cable ) { - params_t *params = (params_t *)cable->params; + params_t *params = (params_t *)cable->params; + + cx_cmd_deinit( &(params->cmd_root) ); - cable->link.port->driver->parport_free( cable->link.port ); - free( params->send_buffer ); - free( params->recv_buffer ); - free( cable->params ); - free( cable ); + generic_usbconn_free( cable ); } +usbconn_cable_t usbconn_cable_ft2232_ftdi; +usbconn_cable_t usbconn_cable_armusbocd_ftdi; +usbconn_cable_t usbconn_cable_bfin_ujtag_ftdi; +usbconn_cable_t usbconn_cable_jtagkey_ftdi; +usbconn_cable_t usbconn_cable_oocdlinks_ftdi; +usbconn_cable_t usbconn_cable_turtelizer2_ftdi; +usbconn_cable_t usbconn_cable_usbtojtagif_ftdi; +usbconn_cable_t usbconn_cable_signalyzer_ftdi; + static void ft2232_usbcable_help( const char *cablename ) { - printf( _( -#ifdef HAVE_LIBFTDI - "Usage: cable %s ftdi-mpsse VID:PID\n" -#endif -#ifdef HAVE_LIBFTD2XX - "Usage: cable %s ftd2xx-mpsse VID:PID\n" -#endif - "\n" - "VID vendor ID (hex, e.g. 9FB, or empty)\n" - "PID product ID (hex, e.g. 6001, or empty)\n" - "\n" -#ifdef HAVE_LIBFTDI - "Expect suboptimal performance of ftdi-mpsse for large shifts with output capture.\n" -#endif - "\n" - ), -#ifdef HAVE_LIBFTDI - cablename -#endif -#if defined HAVE_LIBFTDI && defined HAVE_LIBFTD2XX - , -#endif -#ifdef HAVE_LIBFTD2XX - cablename -#endif - ); + usbconn_cable_t *conn; + + conn = &usbconn_cable_armusbocd_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_bfin_ujtag_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_jtagkey_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_oocdlinks_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_turtelizer2_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_usbtojtagif_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_signalyzer_ftdi; + if (strcasecmp( conn->name, cablename ) == 0) + goto found; + conn = &usbconn_cable_ft2232_ftdi; +found: + + printf( _( + "Usage: cable %s [vid=VID] [pid=PID] [desc=DESC] [driver=DRIVER]\n" + "\n" + "VID vendor ID (hex), defaults to %04X\n" + "PID product ID (hex), defaults to %04X\n" + "DESC Some string to match in description or serial no.\n" + "DRIVER usbconn driver, either ftdi-mpsse of ftd2xx-mpsse\n" + " defaults to %s if not specified\n" + "\n" + ), + cablename, + conn->vid, conn->pid, + DEFAULT_DRIVER + ); } cable_driver_t ft2232_cable_driver = { - "FT2232", - N_("Generic FTDI FT2232 Cable"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_generic_init, - ft2232_generic_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "FT2232", + N_("Generic FTDI FT2232 Cable"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_generic_init, + ft2232_generic_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_ft2232_ftdi = { + "FT2232", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0000, /* VID */ + 0x0000 /* PID */ +}; +usbconn_cable_t usbconn_cable_ft2232_ftd2xx = { + "FT2232", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0000, /* VID */ + 0x0000 /* PID */ }; cable_driver_t ft2232_armusbocd_cable_driver = { - "ARM-USB-OCD", - N_("Olimex ARM-USB-OCD (FT2232) Cable"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_armusbocd_init, - ft2232_armusbocd_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "ARM-USB-OCD", + N_("Olimex ARM-USB-OCD (FT2232) Cable"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_armusbocd_init, + ft2232_armusbocd_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_armusbocd_ftdi = { + "ARM-USB-OCD", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x15BA, /* VID */ + 0x0003 /* PID */ +}; +usbconn_cable_t usbconn_cable_armusbocd_ftd2xx = { + "ARM-USB-OCD", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x15BA, /* VID */ + 0x0003 /* PID */ }; cable_driver_t ft2232_bfin_ujtag_cable_driver = { - "BFIN-UJTAG", - N_("Analog Devices BFIN-UJTAG (FT2232) Cable (EXPERIMENTAL)"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_bfin_ujtag_init, - ft2232_bfin_ujtag_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "BFIN-UJTAG", + N_("Analog Devices BFIN-UJTAG (FT2232) Cable (EXPERIMENTAL)"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_bfin_ujtag_init, + ft2232_bfin_ujtag_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_bfin_ujtag_ftdi = { + "BFIN-UJTAG", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0456, /* VID */ + 0xF000 /* PID */ +}; +usbconn_cable_t usbconn_cable_bfin_ujtag_ftd2xx = { + "BFIN-UJTAG", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0456, /* VID */ + 0xF000 /* PID */ }; cable_driver_t ft2232_jtagkey_cable_driver = { - "JTAGkey", - N_("Amontec JTAGkey (FT2232) Cable"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_jtagkey_init, - ft2232_jtagkey_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "JTAGkey", + N_("Amontec JTAGkey (FT2232) Cable"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_jtagkey_init, + ft2232_jtagkey_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_jtagkey_ftdi = { + "JTAGkey", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0xCFF8 /* PID */ +}; +usbconn_cable_t usbconn_cable_jtagkey_ftd2xx = { + "JTAGkey", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0xCFF8 /* PID */ }; cable_driver_t ft2232_oocdlinks_cable_driver = { - "OOCDLink-s", - N_("OOCDLink-s (FT2232) Cable (EXPERIMENTAL)"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_oocdlinks_init, - ft2232_oocdlinks_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "OOCDLink-s", + N_("OOCDLink-s (FT2232) Cable (EXPERIMENTAL)"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_oocdlinks_init, + ft2232_oocdlinks_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_oocdlinks_ftdi = { + "OOCDLink-s", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0xbaf8 /* PID */ +}; +usbconn_cable_t usbconn_cable_oocdlinks_ftd2xx = { + "OOCDLink-s", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0xbaf8 /* PID */ }; cable_driver_t ft2232_turtelizer2_cable_driver = { - "Turtelizer2", - N_("Turtelizer 2 Rev. B (FT2232) Cable (EXPERIMENTAL)"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_turtelizer2_init, - ft2232_turtelizer2_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "Turtelizer2", + N_("Turtelizer 2 Rev. B (FT2232) Cable (EXPERIMENTAL)"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_turtelizer2_init, + ft2232_turtelizer2_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_turtelizer2_ftdi = { + "Turtelizer2", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0xBDC8 /* PID */ +}; +usbconn_cable_t usbconn_cable_turtelizer2_ftd2xx = { + "Turtelizer2", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0403, /* VID */ + 0xBDC8 /* PID */ }; cable_driver_t ft2232_usbtojtagif_cable_driver = { - "USB-to-JTAG-IF", - N_("USB to JTAG Interface (FT2232) Cable (EXPERIMENTAL)"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_usbtojtagif_init, - ft2232_usbtojtagif_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "USB-to-JTAG-IF", + N_("USB to JTAG Interface (FT2232) Cable (EXPERIMENTAL)"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_usbtojtagif_init, + ft2232_usbtojtagif_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_usbtojtagif_ftdi = { + "USB-to-JTAG-IF", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0000, /* VID */ + 0x0000 /* PID */ +}; +usbconn_cable_t usbconn_cable_usbtojtagif_ftd2xx = { + "USB-to-JTAG-IF", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0000, /* VID */ + 0x0000 /* PID */ }; cable_driver_t ft2232_signalyzer_cable_driver = { - "Signalyzer", - N_("Xverve DT-USB-ST Signalyzer Tool (FT2232) Cable (EXPERIMENTAL)"), - ft2232_connect, - generic_disconnect, - ft2232_cable_free, - ft2232_signalyzer_init, - ft2232_signalyzer_done, - ft2232_set_frequency, - ft2232_clock, - ft2232_get_tdo, - ft2232_transfer, - ft2232_set_trst, - generic_get_trst, - ft2232_flush, - ft2232_usbcable_help + "Signalyzer", + N_("Xverve DT-USB-ST Signalyzer Tool (FT2232) Cable (EXPERIMENTAL)"), + ft2232_connect, + generic_disconnect, + ft2232_cable_free, + ft2232_signalyzer_init, + ft2232_signalyzer_done, + ft2232_set_frequency, + ft2232_clock, + ft2232_get_tdo, + ft2232_transfer, + ft2232_set_trst, + generic_get_trst, + ft2232_flush, + ft2232_usbcable_help +}; +usbconn_cable_t usbconn_cable_signalyzer_ftdi = { + "Signalyzer", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi-mpsse", /* default usbconn driver */ + 0x0000, /* VID */ + 0x0000 /* PID */ +}; +usbconn_cable_t usbconn_cable_signalyzer_ftd2xx = { + "Signalyzer", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx-mpsse", /* default usbconn driver */ + 0x0000, /* VID */ + 0x0000 /* PID */ }; /* Local Variables: mode:C - tab-width:2 - indent-tabs-mode:t + c-default-style:gnu + indent-tabs-mode:nil End: */ diff --git a/jtag/src/tap/cable/generic_usbconn.c b/jtag/src/tap/cable/generic_usbconn.c index 8fd2b70f..c3832a4a 100644 --- a/jtag/src/tap/cable/generic_usbconn.c +++ b/jtag/src/tap/cable/generic_usbconn.c @@ -1,5 +1,5 @@ /* - * $Id: generic.c 1003 2008-02-10 10:00:30Z kawk $ + * $Id$ * * Copyright (C) 2003 ETC s.r.o. * @@ -37,18 +37,94 @@ #undef VERBOSE -#ifdef HAVE_LIBUSB +#ifdef ENABLE_CABLE_XPC extern usbconn_cable_t usbconn_cable_xpc_int; extern usbconn_cable_t usbconn_cable_xpc_ext; +#endif +#ifdef ENABLE_CABLE_JLINK extern usbconn_cable_t usbconn_cable_jlink; #endif +#ifdef ENABLE_CABLE_FT2232 +#ifdef ENABLE_LOWLEVEL_FTD2XX +extern usbconn_cable_t usbconn_cable_ft2232_ftd2xx; +extern usbconn_cable_t usbconn_cable_armusbocd_ftd2xx; +extern usbconn_cable_t usbconn_cable_bfin_ujtag_ftd2xx; +extern usbconn_cable_t usbconn_cable_jtagkey_ftd2xx; +extern usbconn_cable_t usbconn_cable_oocdlinks_ftd2xx; +extern usbconn_cable_t usbconn_cable_turtelizer2_ftd2xx; +extern usbconn_cable_t usbconn_cable_usbtojtagif_ftd2xx; +extern usbconn_cable_t usbconn_cable_signalyzer_ftd2xx; +#endif +#ifdef ENABLE_LOWLEVEL_FTDI +extern usbconn_cable_t usbconn_cable_ft2232_ftdi; +extern usbconn_cable_t usbconn_cable_armusbocd_ftdi; +extern usbconn_cable_t usbconn_cable_bfin_ujtag_ftdi; +extern usbconn_cable_t usbconn_cable_jtagkey_ftdi; +extern usbconn_cable_t usbconn_cable_oocdlinks_ftdi; +extern usbconn_cable_t usbconn_cable_turtelizer2_ftdi; +extern usbconn_cable_t usbconn_cable_usbtojtagif_ftdi; +extern usbconn_cable_t usbconn_cable_signalyzer_ftdi; +#endif +#endif +#ifdef ENABLE_CABLE_USBBLASTER +#ifdef ENABLE_LOWLEVEL_FTD2XX +extern usbconn_cable_t usbconn_cable_usbblaster_ftd2xx; +extern usbconn_cable_t usbconn_cable_cubic_cyclonium_ftd2xx; +extern usbconn_cable_t usbconn_cable_nios_eval_ftd2xx; +extern usbconn_cable_t usbconn_cable_usb_jtag_ftd2xx; +#endif +#ifdef ENABLE_LOWLEVEL_FTDI +extern usbconn_cable_t usbconn_cable_usbblaster_ftdi; +extern usbconn_cable_t usbconn_cable_cubic_cyclonium_ftdi; +extern usbconn_cable_t usbconn_cable_nios_eval_ftdi; +extern usbconn_cable_t usbconn_cable_usb_jtag_ftdi; +#endif +#endif usbconn_cable_t *usbconn_cables[] = { -#ifdef HAVE_LIBUSB +#ifdef ENABLE_CABLE_XPC &usbconn_cable_xpc_int, &usbconn_cable_xpc_ext, +#endif +#ifdef ENABLE_CABLE_JLINK &usbconn_cable_jlink, +#endif +#ifdef ENABLE_CABLE_FT2232 +#ifdef ENABLE_LOWLEVEL_FTD2XX + &usbconn_cable_ft2232_ftd2xx, + &usbconn_cable_armusbocd_ftd2xx, + &usbconn_cable_bfin_ujtag_ftd2xx, + &usbconn_cable_jtagkey_ftd2xx, + &usbconn_cable_oocdlinks_ftd2xx, + &usbconn_cable_turtelizer2_ftd2xx, + &usbconn_cable_usbtojtagif_ftd2xx, + &usbconn_cable_signalyzer_ftd2xx, +#endif +#ifdef ENABLE_LOWLEVEL_FTDI + &usbconn_cable_ft2232_ftdi, + &usbconn_cable_armusbocd_ftdi, + &usbconn_cable_bfin_ujtag_ftdi, + &usbconn_cable_jtagkey_ftdi, + &usbconn_cable_oocdlinks_ftdi, + &usbconn_cable_turtelizer2_ftdi, + &usbconn_cable_usbtojtagif_ftdi, + &usbconn_cable_signalyzer_ftdi, +#endif +#endif +#ifdef ENABLE_CABLE_USBBLASTER +#ifdef ENABLE_LOWLEVEL_FTD2XX + &usbconn_cable_usbblaster_ftd2xx, + &usbconn_cable_cubic_cyclonium_ftd2xx, + &usbconn_cable_nios_eval_ftd2xx, + &usbconn_cable_usb_jtag_ftd2xx, +#endif +#ifdef ENABLE_LOWLEVEL_FTDI + &usbconn_cable_usbblaster_ftdi, + &usbconn_cable_cubic_cyclonium_ftdi, + &usbconn_cable_nios_eval_ftdi, + &usbconn_cable_usb_jtag_ftdi, +#endif #endif NULL }; diff --git a/jtag/src/tap/cable/generic_usbconn.h b/jtag/src/tap/cable/generic_usbconn.h index 25a75b61..9f13bd9e 100644 --- a/jtag/src/tap/cable/generic_usbconn.h +++ b/jtag/src/tap/cable/generic_usbconn.h @@ -1,5 +1,5 @@ /* - * $Id: generic.h 1002 2008-02-10 09:50:59Z kawk $ + * $Id$ * * Copyright (C) 2003 ETC s.r.o. * diff --git a/jtag/src/tap/cable/usbblaster.c b/jtag/src/tap/cable/usbblaster.c index 8ee0d2cb..694c351e 100644 --- a/jtag/src/tap/cable/usbblaster.c +++ b/jtag/src/tap/cable/usbblaster.c @@ -26,13 +26,20 @@ #include "sysdep.h" #include +#include #include "cable.h" -#include "parport.h" #include "chain.h" +#include "cmd.h" #include "generic.h" -#include "generic_parport.h" +#include "generic_usbconn.h" + +#include "usbconn.h" +#include "usbconn/libftdx.h" + +#include "cmd_xfer.h" + #define TCK 0 #define TMS 1 @@ -43,26 +50,71 @@ #define TDO 0 +/* The default driver if not specified otherwise during connect */ +#ifdef ENABLE_LOWLEVEL_FTD2XX +#define DEFAULT_DRIVER "ftd2xx" +#else +#define DEFAULT_DRIVER "ftdi" +#endif + +typedef struct { + cx_cmd_root_t cmd_root; +} params_t; + +static int +usbblaster_connect( char *params[], cable_t *cable ) +{ + params_t *cable_params; + int result; + + /* perform generic_usbconn_connect */ + result = generic_usbconn_connect( params, cable ); + + if (result == 0) + { + cx_cmd_init( &(cable_params->cmd_root) ); + + /* exchange generic cable parameters with our private parameter set */ + free( cable->params ); + cable->params = cable_params; + } + + return result; +} + static int usbblaster_init( cable_t *cable ) { int i; + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); - if (parport_open( cable->link.port )) - return -1; + if (usbconn_open( cable->link.usb )) return -1; + cx_cmd_queue( cmd_root, 0 ); for(i=0;i<64;i++) - parport_set_data( cable->link.port, 0 ); + cx_cmd_push( cmd_root, 0 ); - parport_set_control( cable->link.port, 1 ); // flush - parport_set_control( cable->link.port, 0 ); // noflush + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); return 0; } +static void +usbblaster_cable_free( cable_t *cable ) +{ + params_t *params = (params_t *)cable->params; + + cx_cmd_deinit( &(params->cmd_root) ); + + generic_usbconn_free( cable ); +} + static void usbblaster_clock( cable_t *cable, int tms, int tdi, int n ) { + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); int i, m; tms = tms ? (1<link.port, 0 ); // noflush - + cx_cmd_queue( cmd_root, 0 ); while (m >= 8) { int i; int chunkbytes = (m >> 3); if(chunkbytes > 63) chunkbytes = 63; - parport_set_data( cable->link.port,(1<link.port, tdis); + cx_cmd_push( cmd_root, tdis ); } m -= (chunkbytes << 3); } + + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); } - + for (i = 0; i < m; i++) { - parport_set_data( cable->link.port, OTHERS | (0 << TCK) | tms | tdi ); - parport_set_data( cable->link.port, OTHERS | (1 << TCK) | tms | tdi ); - parport_set_control( cable->link.port, 1 ); // flush - parport_set_control( cable->link.port, 0 ); // noflush + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, OTHERS | (0 << TCK) | tms | tdi ); + cx_cmd_push( cmd_root, OTHERS | (1 << TCK) | tms | tdi ); + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); } } static int usbblaster_get_tdo( cable_t *cable ) { - parport_set_control( cable->link.port, 0 ); // noflush - parport_set_data( cable->link.port, OTHERS ); /* TCK low */ - parport_set_data( cable->link.port, OTHERS | (1 << READ) ); /* TCK low */ - parport_set_control( cable->link.port, 1 ); // flush - parport_set_control( cable->link.port, 0 ); // noflush + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + + cx_cmd_queue( cmd_root, 1 ); + cx_cmd_push( cmd_root, OTHERS ); /* TCK low */ + cx_cmd_push( cmd_root, OTHERS | (1 << READ) ); /* TCK low */ + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); #if 0 - { - char x = ( parport_get_data( cable->link.port ) & (1 << TDO)) ? 1 : 0; - printf("GetTDO %d\n", x); - return x; - } + { + char x = ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0; + printf("GetTDO %d\n", x); + return x; + } #else - return ( parport_get_data( cable->link.port ) & (1 << TDO)) ? 1 : 0; + return ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0; #endif } @@ -130,10 +185,13 @@ usbblaster_set_trst( cable_t *cable, int trst ) static int usbblaster_transfer( cable_t *cable, int len, char *in, char *out ) { + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); int in_offset = 0; int out_offset = 0; - parport_set_control( cable->link.port, 0 ); - parport_set_data( cable->link.port, OTHERS ); /* TCK low */ + + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, OTHERS ); /* TCK low */ #if 0 { @@ -151,27 +209,31 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out ) if(chunkbytes > 63) chunkbytes = 63; if(out) - parport_set_data( cable->link.port,(1<link.port,(1<link.port, b ); + cx_cmd_push( cmd_root, b ); }; if(out) { - parport_set_control( cable->link.port, 1 ); // flush - parport_set_control( cable->link.port, 0 ); + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); for(i=0; ilink.port ); + unsigned char b = cx_xfer_recv( cable ); #if 0 printf("read byte: %02X\n", b); #endif @@ -184,17 +246,18 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out ) while(len > in_offset) { char tdi = in[in_offset++] ? 1 : 0; - parport_set_data( cable->link.port, OTHERS | ((out)?(1 << READ):0) | (tdi << TDI));/* TCK low */ - parport_set_data( cable->link.port, OTHERS | (1 << TCK) | (tdi << TDI)); + + cx_cmd_queue( cmd_root, out ? 1 : 0 ); + cx_cmd_push( cmd_root, OTHERS | ((out)?(1 << READ):0) | (tdi << TDI));/* TCK low */ + cx_cmd_push( cmd_root, OTHERS | (1 << TCK) | (tdi << TDI)); } if(out) { - parport_set_control( cable->link.port, 1 ); // flush - parport_set_control( cable->link.port, 0 ); + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); while(len > out_offset) - out[out_offset++] = ( parport_get_data( cable->link.port ) & (1 << TDO)) ? 1 : 0; + out[out_offset++] = ( cx_xfer_recv( cable ) & (1 << TDO)) ? 1 : 0; #if 0 { @@ -213,6 +276,9 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out ) static void usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much ) { + params_t *params = (params_t *)cable->params; + cx_cmd_root_t *cmd_root = &(params->cmd_root); + if( how_much == OPTIONALLY ) return; while (cable->todo.num_items > 0) @@ -233,16 +299,18 @@ usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much ) // printf("clock: %d %d %d\n", tms, tdi, m); for(; m>0; m--) { - parport_set_data( cable->link.port, OTHERS | tms | tdi ); - parport_set_data( cable->link.port, OTHERS | (1 << TCK) | tms | tdi ); + cx_cmd_queue( cmd_root, 0 ); + cx_cmd_push( cmd_root, OTHERS | tms | tdi ); + cx_cmd_push( cmd_root, OTHERS | (1 << TCK) | tms | tdi ); to_send += 2; } break; } case CABLE_GET_TDO: { - parport_set_data( cable->link.port, OTHERS ); /* TCK low */ - parport_set_data( cable->link.port, OTHERS | (1 << READ) ); /* TCK low */ + cx_cmd_queue( cmd_root, 1 ); + cx_cmd_push( cmd_root, OTHERS ); /* TCK low */ + cx_cmd_push( cmd_root, OTHERS | (1 << READ) ); /* TCK low */ // printf("get_tdo\n"); to_send += 2; break; @@ -258,14 +326,13 @@ usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much ) #if 0 if(cable->todo.num_items > 0 && cable->todo.data[i].action == CABLE_TRANSFER) { - parport_set_data( cable->link.port, OTHERS ); /* TCK low */ + cx_cmd_push( cmd_root, OTHERS ); /* TCK low */ }; #endif if(to_send > 0) { - parport_set_control( cable->link.port, 1 ); // flush - parport_set_control( cable->link.port, 0 ); + cx_xfer( cmd_root, NULL, cable, COMPLETELY ); } while(j!=i) @@ -274,7 +341,7 @@ usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much ) { case CABLE_GET_TDO: { - int tdo = (parport_get_data( cable->link.port ) & (1<done) ); cable->done.data[m].action = CABLE_GET_TDO; cable->done.data[m].arg.value.tdo = tdo; @@ -334,22 +401,28 @@ void usbblaster_help( const char *cablename ) { printf( _( - "Usage: cable %s ftdi VID:PID\n" + "Usage: cable %s [vid=VID] [pid=PID] [desc=DESC] [driver=DRIVER]\n" "\n" - "VID vendor ID (hex, e.g. 9FB, or empty)\n" - "PID product ID (hex, e.g. 6001, or empty)\n" + "VID vendor ID (hex, e.g. 0abc)\n" + "PID product ID (hex, e.g. 0abc)\n" + "DESC Some string to match in description or serial no.\n" + "DRIVER usbconn driver, either ftdi of ftd2xx\n" + " defaults to %s if not specified\n" "\n" - ), cablename ); + ), + cablename, + DEFAULT_DRIVER + ); } cable_driver_t usbblaster_cable_driver = { "UsbBlaster", N_("Altera USB-Blaster Cable"), - generic_parport_connect, + usbblaster_connect, generic_disconnect, - generic_parport_free, + usbblaster_cable_free, usbblaster_init, - generic_parport_done, + generic_usbconn_done, usbblaster_set_frequency, usbblaster_clock, usbblaster_get_tdo, @@ -361,3 +434,59 @@ cable_driver_t usbblaster_cable_driver = { usbblaster_flush, usbblaster_help, }; +usbconn_cable_t usbconn_cable_usbblaster_ftdi = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi", /* default usbconn driver */ + 0x09FB, /* VID */ + 0x6001 /* PID */ +}; +usbconn_cable_t usbconn_cable_cubic_cyclonium_ftdi = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi", /* default usbconn driver */ + 0x09FB, /* VID */ + 0x6002 /* PID */ +}; +usbconn_cable_t usbconn_cable_nios_eval_ftdi = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi", /* default usbconn driver */ + 0x09FB, /* VID */ + 0x6003 /* PID */ +}; +usbconn_cable_t usbconn_cable_usb_jtag_ftdi = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi", /* default usbconn driver */ + 0x16C0, /* VID */ + 0x06AD /* PID */ +}; +usbconn_cable_t usbconn_cable_usbblaster_ftd2xx = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx", /* default usbconn driver */ + 0x09FB, /* VID */ + 0x6001 /* PID */ +}; +usbconn_cable_t usbconn_cable_cubic_cyclonium_ftd2xx = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx", /* default usbconn driver */ + 0x09FB, /* VID */ + 0x6002 /* PID */ +}; +usbconn_cable_t usbconn_cable_nios_eval_ftd2xx = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftdi", /* default usbconn driver */ + 0x09FB, /* VID */ + 0x6003 /* PID */ +}; +usbconn_cable_t usbconn_cable_usb_jtag_ftd2xx = { + "UsbBlaster", /* cable name */ + NULL, /* string pattern, not used */ + "ftd2xx", /* default usbconn driver */ + 0x16C0, /* VID */ + 0x06AD /* PID */ +}; diff --git a/jtag/src/tap/parport.c b/jtag/src/tap/parport.c index 36b34112..f3df75d5 100644 --- a/jtag/src/tap/parport.c +++ b/jtag/src/tap/parport.c @@ -28,34 +28,20 @@ extern parport_driver_t direct_parport_driver; extern parport_driver_t ppdev_parport_driver; -extern parport_driver_t ftd2xx_parport_driver; -extern parport_driver_t ftd2xx_mpsse_parport_driver; -extern parport_driver_t ftdi_parport_driver; -extern parport_driver_t ftdi_mpsse_parport_driver; extern parport_driver_t ppi_parport_driver; parport_driver_t *parport_drivers[] = { -#ifdef ENABLE_PARPORT_DIRECT +#ifdef ENABLE_LOWLEVEL_DIRECT &direct_parport_driver, -#endif /* ENABLE_PARPORT_DIRECT */ +#endif /* ENABLE_LOWLEVEL_DIRECT */ -#ifdef ENABLE_PARPORT_PPDEV +#ifdef ENABLE_LOWLEVEL_PPDEV &ppdev_parport_driver, -#endif /* ENABLE_PARPORT_PPDEV */ +#endif /* ENABLE_LOWLEVEL_PPDEV */ -#ifdef ENABLE_PARPORT_FTD2XX - &ftd2xx_parport_driver, - &ftd2xx_mpsse_parport_driver, -#endif /* ENABLE_PARPORT_FTD2XX */ - -#ifdef ENABLE_PARPORT_FTDI - &ftdi_parport_driver, - &ftdi_mpsse_parport_driver, -#endif /* ENABLE_PARPORT_FTDI */ - -#ifdef ENABLE_PARPORT_PPI +#ifdef ENABLE_LOWLEVEL_PPI &ppi_parport_driver, -#endif /* ENABLE_PARPORT_PPI */ +#endif /* ENABLE_LOWLEVEL_PPI */ NULL /* last must be NULL */ }; diff --git a/jtag/src/tap/parport/ftd2xx.c b/jtag/src/tap/parport/ftd2xx.c deleted file mode 100644 index 722b073e..00000000 --- a/jtag/src/tap/parport/ftd2xx.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * $Id$ - * - * libftd2xx Driver - * - * Based on libftdi driver - * Copyright (C) 2006 K. Waschk - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by Kolja Waschk, 2006. - * Structure taken from ppdev.c, written by Marcel Telka, 2003. - * Ported to libftd2xx by A. Laeuger, 2007. - * - */ - -#include "sysdep.h" - -#include -#include -#if __CYGWIN__ || __MINGW32__ -#include -#endif -#ifdef HAVE_STROPTS_H -#include -#endif - -#include -#include - -#include - -#include "parport.h" -#include "cable.h" - -parport_driver_t ftd2xx_parport_driver; -parport_driver_t ftd2xx_mpsse_parport_driver; - -typedef struct port_node_t port_node_t; - -struct port_node_t { - parport_t *port; - port_node_t *next; -}; - -static port_node_t *ports = NULL; /* devices */ - -#define OUTBUF_LEN_STD 64 -#define OUTBUF_LEN_MPSSE 4096 - -typedef struct { - char *serial; - unsigned int vendor_id; - unsigned int product_id; - char autoflush; - FT_HANDLE fc; - int outcount; - unsigned char *outbuf; - int outbuf_len; -} ftd2xx_params_t; - -static int ftd2xx_set_data ( parport_t *parport, uint8_t data ); -static int ftd2xx_set_control ( parport_t *parport, uint8_t data ); -static int ftd2xx_flush_output ( ftd2xx_params_t *p ); - -static parport_t * -ftd2xx_parport_alloc( const char *vidpid, parport_driver_t * parport_driver, size_t outbuf_len ) -{ - ftd2xx_params_t *params = malloc( sizeof *params ); - parport_t *parport = malloc( sizeof *parport ); - port_node_t *node = malloc( sizeof *node ); - unsigned char *outbuf = malloc( outbuf_len ); - - if (!node || !parport || !params || !outbuf) { - free( node ); - free( parport ); - free( params ); - return NULL; - } - - params->outbuf = outbuf; - params->outbuf_len = outbuf_len; - params->outcount = 0; - params->autoflush = 0; - params->product_id = 0; - params->vendor_id = 0; - params->serial = NULL; - - { - char *f = strchr(vidpid, ':'); - char *l = strrchr(vidpid, ':'); - if(f) - { - params->vendor_id = strtoul(vidpid, NULL, 16); - params->product_id = strtoul(f+1, NULL, 16); - if(l!=f) params->serial = strdup(l+1); - }; - }; - - parport->params = params; - parport->driver = parport_driver; - parport->cable = NULL; - - node->port = parport; - node->next = ports; - - ports = node; - - return parport; -} - -static void -ftd2xx_parport_free( parport_t *port ) -{ - port_node_t **prev; - - for (prev = &ports; *prev; prev = &((*prev)->next)) - if ((*prev)->port == port) - break; - - if (*prev) { - port_node_t *pn = *prev; - *prev = pn->next; - free( pn ); - } - - free( ((ftd2xx_params_t *) port->params)->serial ); - free( ((ftd2xx_params_t *) port->params)->outbuf ); - free( port->params ); - free( port ); -} - - -int -ftd2xx_pre_connect( const char **par, int parnum ) -{ - port_node_t *pn; - - if (parnum != 1) { - printf( _("Syntax error!\n") ); - return 0; - } - - for (pn = ports; pn; pn = pn->next) - if (strcmp( pn->port->params, par[0] ) == 0) { - printf( _("Disconnecting %s from FTDI device %s\n"), _(pn->port->cable->driver->description), par[0] ); - pn->port->cable->driver->disconnect( pn->port->cable ); - break; - } - -#if TODO - printf( _("Initializing %s on FTDI device %s\n"), _(cable_drivers[i]->description), par[0] ); -#else - printf( _("Initializing on FTDI device %s\n"), par[0] ); -#endif - - return 1; -} - - -parport_t * -ftd2xx_std_connect( const char **par, int parnum ) -{ - parport_t *parport; - - if (!ftd2xx_pre_connect(par, parnum)) - return NULL; - - parport = ftd2xx_parport_alloc( par[0], &ftd2xx_parport_driver, OUTBUF_LEN_STD ); - if (!parport) { - printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); - return NULL; - } - - return parport; -} - - -parport_t * -ftd2xx_mpsse_connect( const char **par, int parnum ) -{ - parport_t *parport; - - if (!ftd2xx_pre_connect(par, parnum)) - return NULL; - - parport = ftd2xx_parport_alloc( par[0], &ftd2xx_mpsse_parport_driver, OUTBUF_LEN_MPSSE ); - if (!parport) { - printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); - return NULL; - } - - return parport; -} - - -static int -ftd2xx_generic_open( parport_t *parport ) -{ - ftd2xx_params_t *p = parport->params; - FT_STATUS status; - -#if !__CYGWIN__ && !__MINGW32__ - /* Add non-standard Vid/Pid to the linux driver */ - if ((status = FT_SetVIDPID(p->vendor_id, p->product_id)) != FT_OK) - fprintf( stderr, "Warning: couldn't add %4.4x:%4.4x", p->vendor_id, p->product_id ); -#endif - - if ((status = FT_Open(0, &(p->fc))) != FT_OK) { - fprintf( stderr, "Error: unable to open FTDI device: %li\n", status); - /* mark ftd2xx layer as not initialized */ - p->fc = NULL; - return -1; - } - - return 0; -} - - -static int -ftd2xx_std_open( parport_t *parport ) -{ - int r; - ftd2xx_params_t *p = parport->params; - FT_HANDLE fc; - FT_STATUS status; - - r = ftd2xx_generic_open(parport); - if (r < 0) - return r; - - fc = p->fc; - - if ((status = FT_SetBitMode( fc, 0x00, 0x00 )) != FT_OK) { - fprintf(stderr, "Can't disable bitmode: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_SetLatencyTimer(fc, 2)) != FT_OK) { - fprintf(stderr, "Can't set latency timer: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_SetBaudRate(fc, 3E6)) != FT_OK) { - fprintf(stderr, "Can't set baudrate: %li\n", status); - FT_Close(fc); - return -1; - } - - return 0; -} - - -static int -ftd2xx_mpsse_open( parport_t *parport ) -{ - int r; - ftd2xx_params_t *p = parport->params; - FT_HANDLE fc; - FT_STATUS status; - - r = ftd2xx_generic_open(parport); - if (r < 0) - return r; - - fc = p->fc; - - /* This sequence might seem weird and containing superfluous stuff. - However, it's built after the description of JTAG_InitDevice - Ref. FTCJTAGPG10.pdf - Intermittent problems will occur when certain steps are skipped. */ - if ((status = FT_ResetDevice(fc)) != FT_OK) { - fprintf(stderr, "Can't reset device: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_Purge(fc, FT_PURGE_RX)) != FT_OK) { - fprintf(stderr, "Can't purge buffers: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_SetChars(fc, 0, 0, 0, 0)) != FT_OK) { - fprintf(stderr, "Can't set special characters: %li\n", status); - FT_Close(fc); - return -1; - } - /* set a reasonable latency timer value - if this value is too low then the chip will send intermediate result data - in short packets (suboptimal performance) */ - if ((status = FT_SetLatencyTimer(fc, 16)) != FT_OK) { - fprintf(stderr, "Can't set target latency timer: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_SetBitMode( fc, 0x00, 0x00 )) != FT_OK) { - fprintf(stderr, "Can't disable bitmode: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_SetBitMode( fc, 0x0b, 0x02 /*BITMODE_MPSSE*/ )) != FT_OK) { - fprintf(stderr, "Can't set bitmode: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_ResetDevice(fc)) != FT_OK) { - fprintf(stderr, "Can't reset device: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_Purge(fc, FT_PURGE_RX)) != FT_OK) { - fprintf(stderr, "Can't purge buffers: %li\n", status); - FT_Close(fc); - return -1; - } - /* set TCK Divisor */ - ftd2xx_set_data(parport, 0x86); - ftd2xx_set_data(parport, 0x00); - ftd2xx_set_data(parport, 0x00); - ftd2xx_set_control(parport, 1); - ftd2xx_set_control(parport, 0); - /* switch off loopback */ - ftd2xx_set_data(parport, 0x85); - ftd2xx_set_control(parport, 1); - ftd2xx_set_control(parport, 0); - if ((status = FT_ResetDevice(fc)) != FT_OK) { - fprintf(stderr, "Can't reset device: %li\n", status); - FT_Close(fc); - return -1; - } - if ((status = FT_Purge(fc, FT_PURGE_RX)) != FT_OK) { - fprintf(stderr, "Can't purge buffers: %li\n", status); - FT_Close(fc); - return -1; - } - - return 0; -} - - -static int -ftd2xx_flush_output ( ftd2xx_params_t *p ) -{ - DWORD xferred; - FT_STATUS status; - - if ((status = FT_Write( p->fc, p->outbuf, (DWORD)(p->outcount), &xferred )) != FT_OK) - fprintf( stderr, "Error: FT_Write() failed in %i\n", __LINE__ ); - - if(xferred > 0 && xferred < p->outcount) - { - int offset = xferred; - int remaining = p->outcount - xferred; - - while(remaining) - { - printf("W\n"); - if(xferred < 0) return xferred; - if ((status = FT_Write( p->fc, p->outbuf + offset, (DWORD)remaining, &xferred)) != FT_OK) - fprintf( stderr, "Error: FT_Write() failed in %i\n", __LINE__ ); - if(xferred < 0) - { - memmove(p->outbuf, p->outbuf + offset, remaining); - p->outcount = remaining; - return 0; - } - offset += xferred; - remaining -= xferred; - } - }; - p->outcount = 0; - - return 0; -} - -static int -ftd2xx_close( parport_t *parport ) -{ - ftd2xx_params_t *p = parport->params; - - if (p->fc) { - if(p->outcount > 0) ftd2xx_flush_output( p ); - p->outcount = 0; - - FT_SetBitMode( p->fc, 0x00, 0x00 ); - FT_Close(p->fc); - } - - return 0; -} - -static int -ftd2xx_set_data( parport_t *parport, uint8_t data ) -{ - ftd2xx_params_t *p = parport->params; - DWORD xferred; - FT_STATUS status; - - if (p->fc) { - if(p->autoflush) - { - if ((status = FT_Write( p->fc, &data, 1 , &xferred)) != FT_OK) - fprintf( stderr, "Error: FT_Write() failed in %i\n", __LINE__ ); - if (xferred != 1) - printf("w\n"); - } - else - { - p->outbuf[p->outcount++] = data; - - if(p->outcount >= p->outbuf_len) - return ftd2xx_flush_output( p ); - } - } - - return 0; -} - -static int -ftd2xx_get_data( parport_t *parport ) -{ - DWORD xferred = 0; - FT_STATUS status; - unsigned char d; - ftd2xx_params_t *p = parport->params; - - if (p->fc) { - while (xferred == 0) { - if ((status = FT_Read( p->fc, &d, 1, &xferred )) != FT_OK) - printf( "Error: FT_Read() failed in %i\n", __LINE__ ); - } - return d; - } else - return 0; -} - -static int -ftd2xx_get_status( parport_t *parport ) -{ - return 0; -} - -static int -ftd2xx_set_control( parport_t *parport, uint8_t data ) -{ - ftd2xx_params_t *p = parport->params; - - if (p->fc) { - p->autoflush = data; - if(p->autoflush) ftd2xx_flush_output( p ); - } - - return 0; -} - -parport_driver_t ftd2xx_parport_driver = { - "ftd2xx", - ftd2xx_std_connect, - ftd2xx_parport_free, - ftd2xx_std_open, - ftd2xx_close, - ftd2xx_set_data, - ftd2xx_get_data, - ftd2xx_get_status, - ftd2xx_set_control -}; - -parport_driver_t ftd2xx_mpsse_parport_driver = { - "ftd2xx-mpsse", - ftd2xx_mpsse_connect, - ftd2xx_parport_free, - ftd2xx_mpsse_open, - ftd2xx_close, - ftd2xx_set_data, - ftd2xx_get_data, - ftd2xx_get_status, - ftd2xx_set_control -}; diff --git a/jtag/src/tap/parport/ftdi.c b/jtag/src/tap/parport/ftdi.c deleted file mode 100644 index cff1cdcd..00000000 --- a/jtag/src/tap/parport/ftdi.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * $Id$ - * - * libftdi Driver - * Copyright (C) 2006 K. Waschk - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by Kolja Waschk, 2006. - * Structure taken from ppdev.c, written by Marcel Telka, 2003. - * - */ - -#include "sysdep.h" - -#ifdef HAVE_LIBFTDI - -#include -#ifdef HAVE_STROPTS_H -#include -#endif -#include - -#include -#include - -#include - -#include "parport.h" -#include "cable.h" - -parport_driver_t ftdi_parport_driver; -parport_driver_t ftdi_mpsse_parport_driver; - -typedef struct port_node_t port_node_t; - -struct port_node_t { - parport_t *port; - port_node_t *next; -}; - -static port_node_t *ports = NULL; /* devices */ - -#define OUTBUF_LEN_STD 64 -#define OUTBUF_LEN_MPSSE 4096 - -typedef struct { - char *serial; - unsigned int vendor_id; - unsigned int product_id; - char autoflush; - struct ftdi_context *fc; - int outcount; - unsigned char *outbuf; - int outbuf_len; -} ftdi_params_t; - -static int ftdi_set_data ( parport_t *parport, uint8_t data ); -static int ftdi_set_control ( parport_t *parport, uint8_t data ); -static int ftdi_flush_output ( ftdi_params_t *p ); - -static parport_t * -ftdi_parport_alloc( const char *vidpid, parport_driver_t * parport_driver, size_t outbuf_len ) -{ - ftdi_params_t *params = malloc( sizeof *params ); - parport_t *parport = malloc( sizeof *parport ); - port_node_t *node = malloc( sizeof *node ); - struct ftdi_context *fc = malloc( sizeof(struct ftdi_context) ); - unsigned char *outbuf = malloc( outbuf_len ); - - if (!node || !parport || !params || !fc || !outbuf) { - free( node ); - free( parport ); - free( params ); - free( fc ); - return NULL; - } - - ftdi_init(fc); - params->outbuf = outbuf; - params->outbuf_len = outbuf_len; - params->outcount = 0; - params->autoflush = 0; - params->product_id = 0; - params->vendor_id = 0; - params->serial = NULL; - params->fc = fc; - - { - char *f = strchr(vidpid, ':'); - char *l = strrchr(vidpid, ':'); - if(f) - { - params->vendor_id = strtoul(vidpid, NULL, 16); - params->product_id = strtoul(f+1, NULL, 16); - if(l!=f) params->serial = strdup(l+1); - }; - }; - - parport->params = params; - parport->driver = parport_driver; - parport->cable = NULL; - - node->port = parport; - node->next = ports; - - ports = node; - - return parport; -} - -static void -ftdi_parport_free( parport_t *port ) -{ - port_node_t **prev; - - for (prev = &ports; *prev; prev = &((*prev)->next)) - if ((*prev)->port == port) - break; - - if (*prev) { - port_node_t *pn = *prev; - *prev = pn->next; - free( pn ); - } - - free( ((ftdi_params_t *) port->params)->serial ); - free( ((ftdi_params_t *) port->params)->outbuf ); - free( ((ftdi_params_t *) port->params)->fc ); - free( port->params ); - free( port ); -} - - -int -ftdi_pre_connect( const char **par, int parnum ) -{ - port_node_t *pn; - - if (parnum != 1) { - printf( _("Syntax error!\n") ); - return 0; - } - - for (pn = ports; pn; pn = pn->next) - if (strcmp( pn->port->params, par[0] ) == 0) { - printf( _("Disconnecting %s from FTDI device %s\n"), _(pn->port->cable->driver->description), par[0] ); - pn->port->cable->driver->disconnect( pn->port->cable ); - break; - } - -#if TODO - printf( _("Initializing %s on FTDI device %s\n"), _(cable_drivers[i]->description), par[0] ); -#else - printf( _("Initializing on FTDI device %s\n"), par[0] ); -#endif - - return 1; -} - - -parport_t * -ftdi_std_connect( const char **par, int parnum ) -{ - parport_t *parport; - - if(!ftdi_pre_connect(par, parnum)) - return NULL; - - parport = ftdi_parport_alloc( par[0], &ftdi_parport_driver, OUTBUF_LEN_STD ); - if (!parport) { - printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); - return NULL; - } - - return parport; -} - - -parport_t * -ftdi_mpsse_connect( const char **par, int parnum ) -{ - parport_t *parport; - - if(!ftdi_pre_connect(par, parnum)) - return NULL; - - parport = ftdi_parport_alloc( par[0], &ftdi_mpsse_parport_driver, OUTBUF_LEN_MPSSE ); - if (!parport) { - printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); - return NULL; - } - - return parport; -} - - -static int -ftdi_generic_open( parport_t *parport ) -{ - int r; - ftdi_params_t *p = parport->params; - struct ftdi_context *fc = p->fc; - - /* Try to be intelligent about IDs */ - - if(p->vendor_id) - r = ftdi_usb_open_desc(fc, p->vendor_id, p->product_id, NULL, p->serial); /* USB-Blaster */ - else - { - r = ftdi_usb_open_desc(fc, 0x09FB, 0x6001, NULL, p->serial); /* USB-Blaster */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x09FB, 0x6002, NULL, p->serial); /* Cubic Cyclonium */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x09FB, 0x6003, NULL, p->serial); /* NIOS II Evaluation board */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x16C0, 0x06AD, NULL, p->serial); /* http://www.ixo.de/info/usb_jtag/ */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x0403, 0xCFF8, NULL, p->serial); /* Amontec JTAGkey http://www.amontec.com/jtagkey.shtml */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x15BA, 0x0003, NULL, p->serial); /* Olimex ARM-USB-OCD */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x0403, 0xBDC8, NULL, p->serial); /* Turtelizer 2 */ - if(r<0) r = ftdi_usb_open_desc(fc, 0x0456, 0xF000, NULL, p->serial); /* Analog Devices BFIN-UJTAG */ - }; - - if(r<0) - { - fprintf (stderr, "Can't open ftdi device: %s\n", - ftdi_get_error_string (fc)); - ftdi_deinit(fc); - /* mark ftdi layer as not initialized */ - p->fc = NULL; - return -1; - }; - - return 0; -} - - -static int -ftdi_std_open( parport_t *parport ) -{ - int r; - ftdi_params_t *p = parport->params; - struct ftdi_context *fc = p->fc; - - r = ftdi_generic_open(parport); - if (r < 0) - return r; - - (void)ftdi_disable_bitbang(fc); - - if(ftdi_set_latency_timer(fc, 2)<0) - { - fprintf (stderr, "Can't set minimum latency: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - }; - -#if 1 - /* libftdi 0.6 doesn't allow high baudrates, so we send the control - message outselves */ - - if (usb_control_msg(fc->usb_dev, 0x40, 3, 1, 0, NULL, 0, fc->usb_write_timeout) != 0) - { - fprintf (stderr, "Can't set max baud rate.\n"); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - }; -#else - if(ftdi_set_baudrate(fc, 48000000)<0) - { - fprintf (stderr, "Can't set max baud rate: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - }; -#endif - - return 0; -} - - -#undef LIBFTDI_UNIMPLEMENTED - -static int -seq_purge( struct ftdi_context *fc, int purge_rx, int purge_tx ) -{ - int result = 0; - unsigned char buf; - -#ifndef LIBFTDI_UNIMPLEMENTED - result = ftdi_usb_purge_buffers( fc ); - if (result == 0) - result = ftdi_read_data( fc, &buf, 1 ); -#else /* not yet available */ - { - int rx_loop; - - if (purge_rx) - for (rx_loop = 0; (rx_loop < 6) && (result == 0); rx_loop++) - result = ftdi_usb_purge_rx_buffer( fc ); - - if (purge_tx) - if (result == 0) - result = ftdi_usb_purge_tx_buffer( fc ); - if (result == 0) - ftdi_read_data( fc, &buf, 1 ); - } -#endif - - return result; -} - - -static int -seq_reset( struct ftdi_context *fc ) -{ - int result = 0; - -#ifdef LIBFTDI_UNIMPLEMENTED /* not yet available */ - { - unsigned short status; - if ((result = ftdi_poll_status( fc, &status )) < 0) - return result; - } -#endif - if ((result = ftdi_usb_reset( fc)) < 0) - return result; - - return seq_purge( fc, 1, 1 ); -} - - -static int -ftdi_mpsse_open( parport_t *parport ) -{ - int r; - ftdi_params_t *p = parport->params; - struct ftdi_context *fc = p->fc; - - r = ftdi_generic_open(parport); - if (r < 0) - return r; - - /* This sequence might seem weird and containing superfluous stuff. - However, it's built after the description of JTAG_InitDevice - Ref. FTCJTAGPG10.pdf - Intermittent problems will occur when certain steps are skipped. */ - if (seq_reset(fc) < 0) - { - fprintf (stderr, "Can't reset USB: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - if (seq_purge(fc, 1, 0) < 0) - { - fprintf (stderr, "Can't purge USB RX buffer: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } -#ifdef LIBFTDI_UNIMPLEMENTED /* not yet available */ - if (ftdi_set_chars(fc, 0, 0, 0, 0) < 0) - { - fprintf (stderr, "Can't set special characters: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } -#endif - /* set a reasonable latency timer value - if this value is too low then the chip will send intermediate result data - in short packets (suboptimal performance) */ - if(ftdi_set_latency_timer(fc, 16) < 0) - { - fprintf (stderr, "Can't set target latency: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - - if (ftdi_disable_bitbang(fc) < 0) - { - fprintf (stderr, "Can't reset bitmode: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - if (ftdi_set_bitmode(fc, 0x0b, BITMODE_MPSSE) < 0) - { - fprintf (stderr, "Can't set mpsse mode: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - - if (ftdi_usb_reset(fc) < 0) - { - fprintf (stderr, "Can't reset USB: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - if (seq_purge(fc, 1, 0) < 0) - { - fprintf (stderr, "Can't purge USB RX buffer: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - /* set TCK Divisor */ - ftdi_set_data(parport, TCK_DIVISOR); - ftdi_set_data(parport, 0x00); - ftdi_set_data(parport, 0x00); - ftdi_set_control(parport, 1); - ftdi_set_control(parport, 0); - /* switch off loopback */ - ftdi_set_data(parport, LOOPBACK_END); - ftdi_set_control(parport, 1); - ftdi_set_control(parport, 0); - if (ftdi_usb_reset(fc) < 0) - { - fprintf (stderr, "Can't reset USB: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - if (seq_purge(fc, 1, 0) < 0) - { - fprintf (stderr, "Can't purge USB RX buffer: %s\n", - ftdi_get_error_string (fc)); - ftdi_usb_close(fc); - ftdi_deinit(fc); - return -1; - } - - return 0; -} - - -static int -ftdi_flush_output ( ftdi_params_t *p ) -{ - int xferred; - //int i; - //unsigned char * q; - - // printf("ftdi_flush_output, length %d", p->outcount); - // for (i=0, q=p->outbuf; ioutcount; i++, q++) - // printf(" %01x", *q); - // printf("\n"); - xferred = ftdi_write_data(p->fc, p->outbuf, p->outcount); - if (xferred < 0) - printf( _("Error from ftdi_write_data(): %d\n"), xferred); - - if(xferred > 0 && xferred < p->outcount) - { - int offset = xferred; - int remaining = p->outcount - xferred; - - while(remaining) - { - printf("W\n"); - if(xferred < 0) return xferred; - xferred = ftdi_write_data(p->fc, p->outbuf + offset, remaining); - if(xferred < 0) - { - memmove(p->outbuf, p->outbuf + offset, remaining); - p->outcount = remaining; - return 0; - } - offset += xferred; - remaining -= xferred; - } - }; - p->outcount = 0; - - return 0; -} - -static int -ftdi_close( parport_t *parport ) -{ - ftdi_params_t *p = parport->params; - - if (p->fc) { - if(p->outcount > 0) ftdi_flush_output( p ); - p->outcount = 0; - - ftdi_disable_bitbang(p->fc); - ftdi_usb_close(p->fc); - ftdi_deinit(p->fc); - } - - return 0; -} - -static int -ftdi_set_data( parport_t *parport, uint8_t data ) -{ - ftdi_params_t *p = parport->params; - - if (p->fc) { - if(p->autoflush) - { - if(ftdi_write_data(p->fc, &data, 1) != 1) printf("w\n"); - } - else - { - p->outbuf[p->outcount++] = data; - - if(p->outcount >= p->outbuf_len) - return ftdi_flush_output( p ); - } - } - - return 0; -} - -static int -ftdi_get_data( parport_t *parport ) -{ - unsigned char d; - ftdi_params_t *p = parport->params; - int res = 0; - - if (p->fc) { - while(ftdi_read_data( p->fc, &d, 1) == 0); - res = d; - } else - res = 0; - // printf("ftdi_get_data %01x\n", d); - return res; -} - -static int -ftdi_get_status( parport_t *parport ) -{ - return 0; -} - -static int -ftdi_set_control( parport_t *parport, uint8_t data ) -{ - ftdi_params_t *p = parport->params; - - if (p->fc) { - p->autoflush = data; - if(p->autoflush) ftdi_flush_output( p ); - } - - return 0; -} - -parport_driver_t ftdi_parport_driver = { - "ftdi", - ftdi_std_connect, - ftdi_parport_free, - ftdi_std_open, - ftdi_close, - ftdi_set_data, - ftdi_get_data, - ftdi_get_status, - ftdi_set_control -}; - -parport_driver_t ftdi_mpsse_parport_driver = { - "ftdi-mpsse", - ftdi_mpsse_connect, - ftdi_parport_free, - ftdi_mpsse_open, - ftdi_close, - ftdi_set_data, - ftdi_get_data, - ftdi_get_status, - ftdi_set_control -}; - -#endif /* HAVE_LIBFTDI */ diff --git a/jtag/src/tap/usbconn.c b/jtag/src/tap/usbconn.c index b629cfcf..29b726fb 100644 --- a/jtag/src/tap/usbconn.c +++ b/jtag/src/tap/usbconn.c @@ -1,5 +1,5 @@ /* - * $Id: usbconn.c 851 2007-12-15 22:53:24Z kawk $ + * $Id$ * * Copyright (C) 2008 K. Waschk * @@ -31,11 +31,27 @@ #ifdef HAVE_LIBUSB extern usbconn_driver_t usbconn_libusb_driver; #endif /* HAVE_LIBUSB */ +#ifdef ENABLE_LOWLEVEL_FTD2XX +extern usbconn_driver_t usbconn_ftd2xx_driver; +extern usbconn_driver_t usbconn_ftd2xx_mpsse_driver; +#endif /* ENABLE_LOWLEVEL_FTD2XX */ +#ifdef ENABLE_LOWLEVEL_FTDI +extern usbconn_driver_t usbconn_ftdi_driver; +extern usbconn_driver_t usbconn_ftdi_mpsse_driver; +#endif /* ENABLE_LOWLEVEL_FTDI */ usbconn_driver_t *usbconn_drivers[] = { #ifdef HAVE_LIBUSB &usbconn_libusb_driver, #endif /* HAVE_LIBUSB */ +#ifdef ENABLE_LOWLEVEL_FTD2XX + &usbconn_ftd2xx_driver, + &usbconn_ftd2xx_mpsse_driver, +#endif /* ENABLE_LOWLEVEL_FTD2XX */ +#ifdef ENABLE_LOWLEVEL_FTDI + &usbconn_ftdi_driver, + &usbconn_ftdi_mpsse_driver, +#endif /* ENABLE_LOWLEVEL_FTDI */ NULL /* last must be NULL */ }; @@ -50,3 +66,21 @@ usbconn_close( usbconn_t *conn ) { return conn->driver->close( conn ); } + +int +usbconn_read( usbconn_t *conn, uint8_t *buf, int len ) +{ + if (conn->driver->read) + return conn->driver->read( conn, buf, len ); + else + return 0; +} + +int +usbconn_write( usbconn_t *conn, uint8_t *buf, int len, int recv ) +{ + if (conn->driver->write) + return conn->driver->write( conn, buf, len, recv ); + else + return 0; +} diff --git a/jtag/src/tap/usbconn/libftd2xx.c b/jtag/src/tap/usbconn/libftd2xx.c new file mode 100644 index 00000000..27d21e61 --- /dev/null +++ b/jtag/src/tap/usbconn/libftd2xx.c @@ -0,0 +1,482 @@ +/* + * $Id$ + * + * Link driver for accessing FTDI devices via libftd2xx + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger, 2008 + * + */ + +#include "sysdep.h" + +#include +#if __CYGWIN__ || __MINGW32__ +#include +#endif +#include +#include +#ifdef HAVE_STROPTS_H +#include +#endif +#include +#include +#include + +#include + +#include "cable.h" +#include "usbconn.h" +#include "usbconn/libftdx.h" + + +typedef struct { + /* USB device information */ + unsigned int vid; + unsigned int pid; + FT_HANDLE fc; + char *serial; + /* send and receive buffer handling */ + uint32_t send_buf_len; + uint32_t send_buffered; + uint8_t *send_buf; + uint32_t recv_buf_len; + uint32_t to_recv; + uint32_t recv_write_idx; + uint32_t recv_read_idx; + uint8_t *recv_buf; +} ftd2xx_param_t; + +usbconn_driver_t usbconn_ftd2xx_driver; +usbconn_driver_t usbconn_ftd2xx_mpsse_driver; + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_flush( ftd2xx_param_t *p ) +{ + FT_STATUS status; + DWORD xferred; + DWORD recvd = 0; + + if (!p->fc) + return -1; + + if (p->send_buffered == 0) + return 0; + + if ((status = FT_Write( p->fc, p->send_buf, p->send_buffered, &xferred )) != FT_OK) + perror( _("usbconn_ftd2xx_flush(): FT_Write() failed.\n") ); + + if (xferred < p->send_buffered) + { + perror( _("usbconn_ftd2xx_flush(): Written fewer bytes than requested.\n") ); + return -1; + } + + p->send_buffered = 0; + + /* now read all scheduled receive bytes */ + if (p->to_recv) + { + if (p->recv_write_idx + p->to_recv > p->recv_buf_len) + { + /* extend receive buffer */ + p->recv_buf_len = p->recv_write_idx + p->to_recv; + if (p->recv_buf) + p->recv_buf = (uint8_t *)realloc( p->recv_buf, p->recv_buf_len ); + } + + if (!p->recv_buf) + { + perror( _("usbconn_ftd2xx_flush(): Receive buffer does not exist.\n") ); + return -1; + } + + while (recvd == 0) + if ((status = FT_Read( p->fc, &(p->recv_buf[p->recv_write_idx]), + p->to_recv, &recvd )) != FT_OK) + printf( _("usbconn_ftd2xx_flush(): Error from FT_Read(): %d\n"), (int)status ); + + if (recvd < p->to_recv) + printf( _("usbconn_ftd2xx_flush(): Received less bytes than requested.\n") ); + + p->to_recv -= recvd; + p->recv_write_idx += recvd; + } + + return status != FT_OK ? -1 : xferred; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_read( usbconn_t *conn, uint8_t *buf, int len ) +{ + ftd2xx_param_t *p = conn->params; + int cpy_len; + FT_STATUS status = FT_OK; + DWORD recvd = 0; + + if (!p->fc) + return -1; + + /* flush send buffer to get all scheduled receive bytes */ + if (usbconn_ftd2xx_flush( p ) < 0) + return -1; + + if (len == 0) + return 0; + + /* check for number of remaining bytes in receive buffer */ + cpy_len = p->recv_write_idx - p->recv_read_idx; + if (cpy_len > len) + cpy_len = len; + len -= cpy_len; + + if (cpy_len > 0) + { + /* get data from the receive buffer */ + memcpy( buf, &(p->recv_buf[p->recv_read_idx]), cpy_len ); + p->recv_read_idx += cpy_len; + if (p->recv_read_idx == p->recv_write_idx) + p->recv_read_idx = p->recv_write_idx = 0; + } + + if (len > 0) + { + /* need to get more data directly from the device */ + while (recvd == 0) + if ((status = FT_Read( p->fc, &(buf[cpy_len]), len, &recvd )) != FT_OK) + printf( _("usbconn_ftd2xx_read(): Error from FT_Read(): %d\n"), (int)status ); + } + + return status != FT_OK ? -1 : cpy_len + len; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_write( usbconn_t *conn, uint8_t *buf, int len, int recv ) +{ + ftd2xx_param_t *p = conn->params; + int xferred = 0; + + if (!p->fc) + return -1; + + /* this write function will try to buffer write data + buffering will be ceased and a flush triggered in two cases. */ + + /* Case A: max number of scheduled receive bytes will be exceeded + with this write + Case B: max number of scheduled send bytes has been reached */ + if ((p->to_recv + recv > FTD2XX_MAXRECV) + || ((p->send_buffered > FTDX_MAXSEND) && (p->to_recv == 0))) + xferred = usbconn_ftd2xx_flush( p ); + + if (xferred < 0) + return -1; + + /* now buffer this write */ + if (p->send_buffered + len > p->send_buf_len) + { + p->send_buf_len = p->send_buffered + len; + if (p->send_buf) + p->send_buf = (uint8_t *)realloc( p->send_buf, p->send_buf_len); + } + + if (p->send_buf) + { + memcpy( &(p->send_buf[p->send_buffered]), buf, len ); + p->send_buffered += len; + p->to_recv += recv; + + if (recv < 0) + { + /* immediate write requested, so flush the buffered data */ + xferred = usbconn_ftd2xx_flush( p ); + } + + return xferred < 0 ? -1 : len; + } + else + { + perror( _("usbconn_ftd2xx_write(): Send buffer does not exist.\n") ); + return -1; + } +} + +/* ---------------------------------------------------------------------- */ + +usbconn_t * +usbconn_ftd2xx_connect( const char **param, int paramc, usbconn_cable_t *template ) +{ + usbconn_t *c = malloc( sizeof( usbconn_t ) ); + ftd2xx_param_t *p = malloc( sizeof( ftd2xx_param_t ) ); + + if (p) + { + p->send_buf_len = FTDX_MAXSEND; + p->send_buffered = 0; + p->send_buf = (uint8_t *)malloc( p->send_buf_len ); + p->recv_buf_len = FTD2XX_MAXRECV; + p->to_recv = 0; + p->recv_write_idx = 0; + p->recv_read_idx = 0; + p->recv_buf = (uint8_t *)malloc( p->recv_buf_len ); + } + + if (!p || !c || !p->send_buf || !p->recv_buf) + { + printf( _("Out of memory\n") ); + if (p->send_buf) + free( p->send_buf ); + if (p->recv_buf) + free( p->recv_buf ); + if (p) + free( p ); + if (c) + free( c ); + return NULL; + } + + p->fc = NULL; + p->pid = template->pid; + p->vid = template->vid; + p->serial = NULL; + + c->params = p; + c->driver = &usbconn_ftd2xx_driver; + c->cable = NULL; + + printf( _("Connected to libftd2xx driver.\n") ); + + return c; +} + + +usbconn_t * +usbconn_ftd2xx_mpsse_connect( const char **param, int paramc, usbconn_cable_t *template ) +{ + usbconn_t *conn = usbconn_ftd2xx_connect( param, paramc, template ); + + if (conn) + conn->driver = &usbconn_ftd2xx_mpsse_driver; + + return conn; +} + + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_common_open( usbconn_t *conn ) +{ + ftd2xx_param_t *p = conn->params; + FT_STATUS status; + +#if !__CYGWIN__ && !__MINGW32__ + /* Add non-standard Vid/Pid to the linux driver */ + if ((status = FT_SetVIDPID( p->vid, p->pid )) != FT_OK) + fprintf( stderr, "Warning: couldn't add %4.4x:%4.4x", p->vid, p->pid ); +#endif + + if ((status = FT_Open( 0, &(p->fc) )) != FT_OK) + { + perror( "Unable to open FTDO device.\n" ); + /* mark ftd2xx layer as not initialized */ + p->fc = NULL; + return -1; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_open( usbconn_t *conn ) +{ + ftd2xx_param_t *p = conn->params; + FT_HANDLE fc; + FT_STATUS status; + + if (usbconn_ftd2xx_common_open( conn ) < 0) + return -1; + + fc = p->fc; + + if ((status = FT_SetBitMode( fc, 0x00, 0x00 )) != FT_OK) + perror( _("Can't disable bitmode.\n") ); + + if (status == FT_OK) if ((status = FT_SetLatencyTimer(fc, 2)) != FT_OK) + perror( _("Can't set latency timer.\n") ); + + if (status == FT_OK) if ((status = FT_SetBaudRate(fc, 3E6)) != FT_OK) + perror( _("Can't set baudrate.\n") ); + + if (status != FT_OK) + { + FT_Close( fc ); + /* mark ftdi layer as not initialized */ + p->fc = NULL; + } + + return status != FT_OK ? -1 : 0; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_mpsse_open( usbconn_t *conn ) +{ + ftd2xx_param_t *p = conn->params; + FT_HANDLE fc; + FT_STATUS status; + + if (usbconn_ftd2xx_common_open( conn ) < 0) + return -1; + + fc = p->fc; + + /* This sequence might seem weird and containing superfluous stuff. + However, it's built after the description of JTAG_InitDevice + Ref. FTCJTAGPG10.pdf + Intermittent problems will occur when certain steps are skipped. */ + if ((status = FT_ResetDevice( fc )) != FT_OK) + perror( _("Can't reset device.\n") ); + if (status == FT_OK) if ((status = FT_Purge( fc, FT_PURGE_RX )) != FT_OK) + perror( _("Can't purge RX buffer.\n") ); + + if (status == FT_OK) if ((status = FT_SetChars( fc, 0, 0, 0, 0 )) != FT_OK) + perror( _("Can't set special characters.\n") ); + + /* set a reasonable latency timer value + if this value is too low then the chip will send intermediate result data + in short packets (suboptimal performance) */ + if (status == FT_OK) if ((status = FT_SetLatencyTimer( fc, 16 )) != FT_OK) + perror( _("Can't set target latency timer.\n") ); + + if (status == FT_OK) if ((status = FT_SetBitMode( fc, 0x00, 0x00 )) != FT_OK) + perror( _("Can't disable bitmode.\n") ); + if (status == FT_OK) if ((status = FT_SetBitMode( fc, 0x0b, 0x02 /* BITMODE_MPSSE */ )) != FT_OK) + perror( _("Can't set MPSSE bitmode.\n") ); + + if (status == FT_OK) if ((status = FT_ResetDevice( fc )) != FT_OK) + perror( _("Can't reset device.\n") ); + if (status == FT_OK) if ((status = FT_Purge( fc, FT_PURGE_RX )) != FT_OK) + perror( _("Can't purge RX buffer.\n") ); + + /* set TCK Divisor */ + if (status == FT_OK) + { + uint8_t buf[3] = {0x86, 0x00, 0x00}; + if (usbconn_ftd2xx_write( conn, buf, 3, 0 ) < 0) + status = FT_OTHER_ERROR; + } + /* switch off loopback */ + if (status == FT_OK) + { + uint8_t buf[1] = {0x85}; + if (usbconn_ftd2xx_write( conn, buf, 1, 0 ) < 0) + status = FT_OTHER_ERROR; + } + if (status == FT_OK) + if (usbconn_ftd2xx_read( conn, NULL, 0 ) < 0) + status = FT_OTHER_ERROR; + + if (status == FT_OK) if ((status = FT_ResetDevice( fc )) != FT_OK) + perror( _("Can't reset device.\n") ); + if (status == FT_OK) if ((status = FT_Purge( fc, FT_PURGE_RX )) != FT_OK) + perror( _("Can't purge RX buffer.\n") ); + + if (status != FT_OK) + { + FT_Close( fc ); + /* mark ftdi layer as not initialized */ + p->fc = NULL; + } + + return status != FT_OK ? -1 : 0; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftd2xx_close( usbconn_t *conn ) +{ + ftd2xx_param_t *p = conn->params; + + if (p->fc) + { + FT_SetBitMode( p->fc, 0x00, 0x00 ); + FT_Close( p->fc ); + p->fc = NULL; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static void +usbconn_ftd2xx_free( usbconn_t *conn ) +{ + ftd2xx_param_t *p = conn->params; + + if (p->send_buf) + free( p->send_buf ); + if (p->recv_buf) + free( p->recv_buf ); + if (p->serial) + free( p->serial ); + + free( conn->params ); + free( conn ); +} + +/* ---------------------------------------------------------------------- */ + +usbconn_driver_t usbconn_ftd2xx_driver = { + "ftd2xx", + usbconn_ftd2xx_connect, + usbconn_ftd2xx_free, + usbconn_ftd2xx_open, + usbconn_ftd2xx_close, + usbconn_ftd2xx_read, + usbconn_ftd2xx_write +}; + +usbconn_driver_t usbconn_ftd2xx_mpsse_driver = { + "ftd2xx-mpsse", + usbconn_ftd2xx_mpsse_connect, + usbconn_ftd2xx_free, + usbconn_ftd2xx_mpsse_open, + usbconn_ftd2xx_close, + usbconn_ftd2xx_read, + usbconn_ftd2xx_write +}; + + +/* + Local Variables: + mode:C + c-default-style:gnu + indent-tabs-mode:nil + End: +*/ diff --git a/jtag/src/tap/usbconn/libftdi.c b/jtag/src/tap/usbconn/libftdi.c new file mode 100644 index 00000000..0893e6a7 --- /dev/null +++ b/jtag/src/tap/usbconn/libftdi.c @@ -0,0 +1,542 @@ +/* + * $Id$ + * + * Link driver for accessing FTDI devices via libftdi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by Arnim Laeuger, 2008 + * + */ + +#include "sysdep.h" + +#include +#if __CYGWIN__ || __MINGW32__ +#include +#endif +#include +#include +#ifdef HAVE_STROPTS_H +#include +#endif +#include +#include +#include + +#include + +#include "cable.h" +#include "usbconn.h" +#include "usbconn/libftdx.h" + +typedef struct { + /* USB device information */ + unsigned int vid; + unsigned int pid; + struct ftdi_context *fc; + char *serial; + /* send and receive buffer handling */ + uint32_t send_buf_len; + uint32_t send_buffered; + uint8_t *send_buf; + uint32_t recv_buf_len; + uint32_t to_recv; + uint32_t recv_write_idx; + uint32_t recv_read_idx; + uint8_t *recv_buf; +} ftdi_param_t; + +usbconn_driver_t usbconn_ftdi_driver; +usbconn_driver_t usbconn_ftdi_mpsse_driver; + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftdi_flush( ftdi_param_t *p ) +{ + int xferred; + int recvd = 0; + + if (!p->fc) + return -1; + + if (p->send_buffered == 0) + return 0; + + if ((xferred = ftdi_write_data( p->fc, p->send_buf, p->send_buffered )) < 0) + perror( ftdi_get_error_string( p->fc ) ); + + if (xferred < p->send_buffered) + { + perror( _("usbconn_ftdi_flush(): Written fewer bytes than requested.\n") ); + return -1; + } + + p->send_buffered = 0; + + /* now read all scheduled receive bytes */ + if (p->to_recv) + { + if (p->recv_write_idx + p->to_recv > p->recv_buf_len) + { + /* extend receive buffer */ + p->recv_buf_len = p->recv_write_idx + p->to_recv; + if (p->recv_buf) + p->recv_buf = (uint8_t *)realloc( p->recv_buf, p->recv_buf_len ); + } + + if (!p->recv_buf) + { + perror( _("usbconn_ftdi_flush(): Receive buffer does not exist.\n") ); + return -1; + } + + while (recvd == 0) + if ((recvd = ftdi_read_data( p->fc, &(p->recv_buf[p->recv_write_idx]), + p->to_recv )) < 0) + printf( _("usbconn_ftdi_flush(): Error from ftdi_read_data(): %s\n"), + ftdi_get_error_string( p->fc ) ); + + if (recvd < p->to_recv) + printf( _("usbconn_ftdi_flush(): Received less bytes than requested.\n") ); + + p->to_recv -= recvd; + p->recv_write_idx += recvd; + } + + return xferred < 0 ? -1 : xferred; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len ) +{ + ftdi_param_t *p = conn->params; + int cpy_len; + int recvd = 0; + + if (!p->fc) + return -1; + + /* flush send buffer to get all scheduled receive bytes */ + if (usbconn_ftdi_flush( p ) < 0) + return -1; + + if (len == 0) + return 0; + + /* check for number of remaining bytes in receive buffer */ + cpy_len = p->recv_write_idx - p->recv_read_idx; + if (cpy_len > len) + cpy_len = len; + len -= cpy_len; + + if (cpy_len > 0) + { + /* get data from the receive buffer */ + memcpy( buf, &(p->recv_buf[p->recv_read_idx]), cpy_len ); + p->recv_read_idx += cpy_len; + if (p->recv_read_idx == p->recv_write_idx) + p->recv_read_idx = p->recv_write_idx = 0; + } + + if (len > 0) + { + /* need to get more data directly from the device */ + while (recvd == 0) + if ((recvd = ftdi_read_data( p->fc, &(buf[cpy_len]), len )) < 0) + printf( _("usbconn_ftdi_read(): Error from ftdi_read_data(): %s\n"), + ftdi_get_error_string( p->fc ) ); + } + + return recvd < 0 ? -1 : cpy_len + len; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv ) +{ + ftdi_param_t *p = conn->params; + int xferred = 0; + + if (!p->fc) + return -1; + + /* this write function will try to buffer write data + buffering will be ceased and a flush triggered in two cases. */ + + /* Case A: max number of scheduled receive bytes will be exceeded + with this write + Case B: max number of scheduled send bytes has been reached */ + if ((p->to_recv + recv > FTDI_MAXRECV) + || ((p->send_buffered > FTDX_MAXSEND) && (p->to_recv == 0))) + xferred = usbconn_ftdi_flush( p ); + + if (xferred < 0) + return -1; + + /* now buffer this write */ + if (p->send_buffered + len > p->send_buf_len) + { + p->send_buf_len = p->send_buffered + len; + if (p->send_buf) + p->send_buf = (uint8_t *)realloc( p->send_buf, p->send_buf_len); + } + + if (p->send_buf) + { + memcpy( &(p->send_buf[p->send_buffered]), buf, len ); + p->send_buffered += len; + p->to_recv += recv; + + if (recv < 0) + { + /* immediate write requested, so flush the buffered data */ + xferred = usbconn_ftdi_flush( p ); + } + + return xferred < 0 ? -1 : len; + } + else + { + perror( _("usbconn_ftdi_write(): Send buffer does not exist.\n") ); + return -1; + } +} + +/* ---------------------------------------------------------------------- */ + +usbconn_t * +usbconn_ftdi_connect( const char **param, int paramc, usbconn_cable_t *template ) +{ + usbconn_t *c = malloc( sizeof( usbconn_t ) ); + ftdi_param_t *p = malloc( sizeof( ftdi_param_t ) ); + struct ftdi_context *fc = malloc( sizeof( struct ftdi_context ) ); + + if (p) + { + p->send_buf_len = FTDX_MAXSEND; + p->send_buffered = 0; + p->send_buf = (uint8_t *)malloc( p->send_buf_len ); + p->recv_buf_len = FTDI_MAXRECV; + p->to_recv = 0; + p->recv_write_idx = 0; + p->recv_read_idx = 0; + p->recv_buf = (uint8_t *)malloc( p->recv_buf_len ); + } + + if (!p || !c || !fc || !p->send_buf || !p->recv_buf) + { + printf( _("Out of memory\n") ); + if (p->send_buf) + free( p->send_buf ); + if (p->recv_buf) + free( p->recv_buf ); + if (p) + free( p ); + if (c) + free( c ); + if (fc) + free( fc ); + return NULL; + } + + ftdi_init( fc ); + p->fc = fc; + p->pid = template->pid; + p->vid = template->vid; + p->serial = NULL; + + c->params = p; + c->driver = &usbconn_ftdi_driver; + c->cable = NULL; + + printf( _("Connected to libftdi driver.\n") ); + + return c; +} + + +usbconn_t * +usbconn_ftdi_mpsse_connect( const char **param, int paramc, usbconn_cable_t *template ) +{ + usbconn_t *conn = usbconn_ftdi_connect( param, paramc, template ); + + if (conn) + conn->driver = &usbconn_ftdi_mpsse_driver; + + return conn; +} + + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftdi_common_open( usbconn_t *conn ) +{ + ftdi_param_t *p = conn->params; + struct ftdi_context *fc = p->fc; + + if (ftdi_usb_open_desc( fc, p->vid, p->pid, NULL, p->serial ) < 0) + { + perror( ftdi_get_error_string( fc ) ); + ftdi_deinit( fc ); + /* mark ftdi layer as not initialized */ + p->fc = NULL; + + /* TODO: disconnect? */ + return -1; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftdi_open( usbconn_t *conn ) +{ + ftdi_param_t *p = conn->params; + struct ftdi_context *fc = p->fc; + int r; + + if (usbconn_ftdi_common_open( conn ) < 0) + return -1; + + if ((r = ftdi_disable_bitbang( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + + if (r >= 0) if ((r = ftdi_set_latency_timer( fc, 2 )) < 0) + perror( ftdi_get_error_string( fc ) ); + +#if 1 + /* libftdi 0.6 doesn't allow high baudrates, so we send the control + message outselves */ + if (r >= 0) if (usb_control_msg( fc->usb_dev, 0x40, 3, 1, 0, NULL, 0, fc->usb_write_timeout ) != 0) + { + perror( "Can't set max baud rate.\n" ); + r = -1; + } +#else + if (r >= 0) if ((r = ftdi_set_baudrate( fc, 48000000 )) < 0) + perror( ftdi_get_error_string( fc ) ); +#endif + + if (r < 0) + { + ftdi_usb_close( fc ); + ftdi_deinit( fc ); + /* mark ftdi layer as not initialized */ + p->fc = NULL; + } + + return r < 0 ? -1 : 0; +} + +/* ---------------------------------------------------------------------- */ + +#undef LIBFTDI_UNIMPLEMENTED + +static int +seq_purge( struct ftdi_context *fc, int purge_rx, int purge_tx ) +{ + int r; + unsigned char buf; + +#ifndef LIBFTDI_UNIMPLEMENTED + if ((r = ftdi_usb_purge_buffers( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + if (r >= 0) if ((r = ftdi_read_data( fc, &buf, 1 )) < 0) + perror( ftdi_get_error_string( fc ) ); +#else /* not yet available */ + { + int rx_loop; + + if (purge_rx) + for (rx_loop = 0; (rx_loop < 6) && (r >= 0); rx_loop++) + if ((r = ftdi_usb_purge_rx_buffer( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + + if (purge_tx) + if (r >= 0) if ((r = ftdi_usb_purge_tx_buffer( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + if (r >= 0) if ((r = ftdi_read_data( fc, &buf, 1 )) < 0) + perror( ftdi_get_error_string( fc ) ); + } +#endif + + return r < 0 ? -1 : 0; +} + +static int +seq_reset( struct ftdi_context *fc ) +{ + int r; + +#ifdef LIBFTDI_UNIMPLEMENTED /* not yet available */ + { + unsigned short status; + if ((r = ftdi_poll_status( fc, &status )) < 0) + perror( ftdi_get_error_string( fc ) ); + } +#endif + if ((r = ftdi_usb_reset( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + + if (r >= 0) r = seq_purge( fc, 1, 1 ); + return r < 0 ? -1 : 0; +} + +static int +usbconn_ftdi_mpsse_open( usbconn_t *conn ) +{ + ftdi_param_t *p = conn->params; + struct ftdi_context *fc = p->fc; + int r; + + if (usbconn_ftdi_common_open( conn ) < 0) + return -1; + + /* This sequence might seem weird and containing superfluous stuff. + However, it's built after the description of JTAG_InitDevice + Ref. FTCJTAGPG10.pdf + Intermittent problems will occur when certain steps are skipped. */ + r = seq_reset( fc ); + if (r >= 0) r = seq_purge( fc, 1, 0 ); + +#ifdef LIBFTDI_UNIMPLEMENTED + if (r >= 0) if ((r = ftdi_set_event_char( fc, 0, 0 )) < 0) + perror( ftdi_get_error_string( fc ) ); + if (r >= 0) if ((r = ftdi_set_error_char( fc, 0, 0 )) < 0) + perror( ftdi_get_error_string( fc ) ); +#endif + + /* set a reasonable latency timer value + if this value is too low then the chip will send intermediate result data + in short packets (suboptimal performance) */ + if (r >= 0) if ((r = ftdi_set_latency_timer( fc, 16 )) < 0) + perror( ftdi_get_error_string( fc ) ); + + if (r >= 0) if ((r = ftdi_disable_bitbang( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + + if (r >= 0) if ((r = ftdi_set_bitmode( fc, 0x0b, BITMODE_MPSSE )) < 0) + perror( ftdi_get_error_string( fc ) ); + + if (r >= 0) if ((r = ftdi_usb_reset( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + if (r >= 0) r = seq_purge( fc, 1, 0 ); + + /* set TCK Divisor */ + if (r >= 0) + { + uint8_t buf[3] = {TCK_DIVISOR, 0x00, 0x00}; + r = usbconn_ftdi_write( conn, buf, 3, 0 ); + } + /* switch off loopback */ + if (r >= 0) + { + uint8_t buf[1] = {LOOPBACK_END}; + r = usbconn_ftdi_write( conn, buf, 1, 0 ); + } + if (r >= 0) r = usbconn_ftdi_read( conn, NULL, 0 ); + + if (r >= 0) if ((r = ftdi_usb_reset( fc )) < 0) + perror( ftdi_get_error_string( fc ) ); + if (r >= 0) r = seq_purge( fc, 1, 0 ); + + if (r < 0) + { + ftdi_usb_close( fc ); + ftdi_deinit( fc ); + /* mark ftdi layer as not initialized */ + p->fc = NULL; + } + + return r < 0 ? -1 : 0; +} + +/* ---------------------------------------------------------------------- */ + +static int +usbconn_ftdi_close( usbconn_t *conn ) +{ + ftdi_param_t *p = conn->params; + + if (p->fc) + { + ftdi_disable_bitbang( p->fc ); + ftdi_usb_close( p->fc ); + ftdi_deinit( p->fc ); + p->fc = NULL; + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static void +usbconn_ftdi_free( usbconn_t *conn ) +{ + ftdi_param_t *p = conn->params; + + if (p->send_buf) + free( p->send_buf ); + if (p->recv_buf) + free( p->recv_buf ); + if (p->fc) + free( p->fc ); + if (p->serial) + free( p->serial ); + + free( conn->params ); + free( conn ); +} + +/* ---------------------------------------------------------------------- */ + +usbconn_driver_t usbconn_ftdi_driver = { + "ftdi", + usbconn_ftdi_connect, + usbconn_ftdi_free, + usbconn_ftdi_open, + usbconn_ftdi_close, + usbconn_ftdi_read, + usbconn_ftdi_write +}; + +usbconn_driver_t usbconn_ftdi_mpsse_driver = { + "ftdi-mpsse", + usbconn_ftdi_mpsse_connect, + usbconn_ftdi_free, + usbconn_ftdi_mpsse_open, + usbconn_ftdi_close, + usbconn_ftdi_read, + usbconn_ftdi_write +}; + + +/* + Local Variables: + mode:C + c-default-style:gnu + indent-tabs-mode:nil + End: +*/ diff --git a/jtag/src/tap/usbconn/libusb.c b/jtag/src/tap/usbconn/libusb.c index 09ff8f45..e50c166a 100644 --- a/jtag/src/tap/usbconn/libusb.c +++ b/jtag/src/tap/usbconn/libusb.c @@ -1,5 +1,5 @@ /* - * $Id: ftdi.c,v 1.7 2003/08/19 09:05:25 telka Exp $ + * $Id$ * * Link driver for accessing USB devices via libusb * @@ -148,8 +148,10 @@ usbconn_libusb_connect( const char **param, int paramc, usbconn_cable_t *templat if(libusb_params == NULL || libusb_conn == NULL) { printf(_("Out of memory\n")); - free(libusb_params); - free(libusb_conn); + if (libusb_params) + free(libusb_params); + if (libusb_conn) + free(libusb_conn); return NULL; }; @@ -235,7 +237,9 @@ usbconn_driver_t usbconn_libusb_driver = { usbconn_libusb_connect, usbconn_libusb_free, usbconn_libusb_open, - usbconn_libusb_close + usbconn_libusb_close, + NULL, + NULL }; #endif /* HAVE_LIBUSB */