Merged from jtag_kawk#978: New functions to queue "deferred" JTAG activity.

New code in cable drivers to flush the activity queue, both generic (for
parport-based and new drivers) and optimized implementations for FT2232-based
cables (by Arnim Laeuger) and USB-Blaster (by me) (#1832990)



git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@979 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Kolja Waschk 17 years ago
parent d24460151a
commit 03aeb3783e

@ -1,3 +1,20 @@
2008-02-01 Kolja Waschk <kawk>
* include/cable.h, include/chain.h, src/tap/chain.c, src/tap/tap.c,
src/tap/cable/wiggler.c, src/tap/cable/arcom.c, src/tap/cable/mpcbdm.c,
src/tap/cable/usbblaster.c, src/tap/cable/generic.c,
src/tap/cable/vision_ep9307.c, src/tap/cable/ea253.c,
src/tap/cable/triton.c, src/tap/cable/jim.c, src/tap/cable/byteblaster.c,
src/tap/cable/ei012.c, src/tap/cable/generic.h, src/tap/cable/ft2232.c,
src/tap/cable/wiggler2.c, src/tap/cable/keithkoep.c,
src/tap/cable/lattice.c, src/tap/cable/dlc5.c, src/tap/cable/xpc.c,
src/tap/cable.c: New functions to queue "deferred" JTAG activity.
New code in cable drivers to flush the activity queue, both generic
(for parport-based and new drivers) and optimized implementations
for FT2232-based cables (by Arnim Laeuger) and USB-Blaster (by me).
Result is a vast speed improvement at least for FT2232; this
implements [ 1832990 ] Speed improvements for USB cables
2008-01-30 Arnim Laeuger <arniml@users.sourceforge.net>
* src/tap/tap.c (tap_reset): set instructions of all parts to BYPASS, fix
@ -8,7 +25,7 @@
* include/jim.h, src/jim/tap.c, intel_28f800b3.c, Makefile.am,
some_cpu.c: Code skeleton and alloc/free calls for actual parts
connected to JIM's some_cpu
connected to JIM's some_cpu
2008-01-24 Kolja Waschk <kawk>
@ -171,9 +188,9 @@
2007-12-29 Arnim Laeuger <arniml@users.sourceforge.net>
* data/altera/PARTS: ep2c8 added
'[ 1859032 ] jtag support for Altera EP2C8' (Hartley Sweeten)
'[ 1859032 ] jtag support for Altera EP2C8' (Hartley Sweeten)
* data/Makefile.am (nobase_dist_pkgdata_DATA): ep2c8 files added
'[ 1859032 ] jtag support for Altera EP2C8' (Hartley Sweeten)
'[ 1859032 ] jtag support for Altera EP2C8' (Hartley Sweeten)
2007-12-27 Arnim Laeuger <arniml@users.sourceforge.net>
@ -183,7 +200,7 @@
2007-12-26 Kolja Waschk <kawk>
* tap/cable/vision_ep9307.c, tap/cable.c, tap/Makefile.am, configure.ac:
Integrated first modern (single-file w/o parport) cable driver
Integrated first modern (single-file w/o parport) cable driver
(1858709: EP9307 target specific cable driver, from Hartley Sweeten)
2007-12-23 Kolja Waschk <kawk>

@ -48,28 +48,89 @@ struct cable_driver_t {
int (*transfer)( cable_t *, int, char *, char * );
int (*set_trst)( cable_t *, int );
int (*get_trst)( cable_t * );
void (*flush)( cable_t * );
void (*help)( const char * );
};
typedef struct cable_queue_t cable_queue_t;
struct cable_queue_t {
enum {
CABLE_CLOCK,
CABLE_GET_TDO,
CABLE_TRANSFER,
CABLE_SET_TRST,
CABLE_GET_TRST
} action;
union {
struct {
int tms;
int tdi;
int n;
} clock;
struct {
int tdo;
int trst;
int val;
} value;
struct {
int len;
char *in;
char *out;
} transfer;
struct {
int len;
int res;
char *out;
} xferred;
} arg;
};
typedef struct cable_queue_info_t cable_queue_info_t;
struct cable_queue_info_t {
cable_queue_t *data;
int max_items;
int num_items;
int next_item;
int next_free;
};
struct cable_t {
cable_driver_t *driver;
parport_t *port;
void *params;
chain_t *chain;
cable_queue_info_t todo;
cable_queue_info_t done;
uint32_t delay;
uint32_t frequency;
};
void cable_free( cable_t *cable );
int cable_init( cable_t *cable );
void cable_done( cable_t *cable );
void cable_flush( cable_t *cable );
void cable_clock( cable_t *cable, int tms, int tdi, int n );
int cable_defer_clock( cable_t *cable, int tms, int tdi, int n );
int cable_get_tdo( cable_t *cable );
int cable_get_tdo_late( cable_t *cable );
int cable_defer_get_tdo( cable_t *cable );
int cable_set_trst( cable_t *cable, int trst );
int cable_defer_set_trst( cable_t *cable, int trst );
int cable_get_trst( cable_t *cable );
int cable_get_trst_late( cable_t *cable );
int cable_defer_get_trst( cable_t *cable );
int cable_transfer( cable_t *cable, int len, char *in, char *out );
int cable_transfer_late( cable_t *cable, char *out );
int cable_defer_transfer( cable_t *cable, int len, char *in, char *out );
void cable_set_frequency( cable_t *cable, uint32_t frequency );
uint32_t cable_get_frequency( cable_t *cable );
void cable_wait( void );
void cable_wait( cable_t *cable );
void cable_purge_queue( cable_queue_info_t *q, int io );
int cable_add_queue_item( cable_t *cable, cable_queue_info_t *q );
int cable_get_queue_item( cable_t *cable, cable_queue_info_t *q );
extern cable_driver_t *cable_drivers[];

@ -46,6 +46,7 @@ chain_t *chain_alloc( void );
void chain_free( chain_t *chain );
void chain_disconnect( chain_t *chain );
void chain_clock( chain_t *chain, int tms, int tdi, int n );
void chain_defer_clock( chain_t *chain, int tms, int tdi, int n );
int chain_set_trst( chain_t *chain, int trst );
int chain_get_trst( chain_t *chain );
void chain_shift_instructions( chain_t *chain );

@ -30,6 +30,7 @@
#include <stdint.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "fclock.h"
#include "jtag.h"
@ -106,51 +107,314 @@ cable_free( cable_t *cable )
int
cable_init( cable_t *cable )
{
cable->delay = 0;
cable->frequency = 0;
cable->todo.max_items = 128;
cable->todo.num_items = 0;
cable->todo.next_item = 0;
cable->todo.next_free = 0;
cable->todo.data = malloc(cable->todo.max_items*sizeof(cable_queue_t));
cable->done.max_items = 128;
cable->done.num_items = 0;
cable->done.next_item = 0;
cable->done.next_free = 0;
cable->done.data = malloc(cable->done.max_items*sizeof(cable_queue_t));
if(cable->todo.data == NULL || cable->done.data == NULL)
{
printf(_("Failed to allocate memory for cable activity queue.\n"));
if(cable->todo.data != NULL) free(cable->todo.data);
if(cable->done.data != NULL) free(cable->done.data);
return 1;
};
return cable->driver->init( cable );
}
void
cable_flush ( cable_t *cable )
{
cable->driver->flush( cable );
}
void
cable_done( cable_t *cable )
{
cable_flush( cable );
if( cable->todo.data != NULL)
{
free( cable->todo.data );
free( cable->done.data );
}
return cable->driver->done( cable );
}
int
cable_add_queue_item( cable_t *cable, cable_queue_info_t *q )
{
int i,j;
if( q->num_items >= q->max_items ) /* queue full? */
{
/* TODO: try to alloc more space for queue */
// printf("add_queue_item to %p: %d\n", q, -1);
return -1; /* report failure */
}
i = q->next_free;
j = i+1;
if( j >= q->max_items ) j = 0;
q->next_free = j;
q->num_items ++;
// printf("add_queue_item to %p: %d\n", q, i);
return i;
}
int
cable_get_queue_item( cable_t *cable, cable_queue_info_t *q )
{
if(q->num_items > 0)
{
int i = q->next_item;
int j = i+1;
if( j >= q->max_items ) j = 0;
q->next_item = j;
q->num_items --;
// printf("get_queue_item from %p: %d\n", q, i);
return i;
}
// printf("get_queue_item from %p: %d\n", q, -1);
return -1;
}
void
cable_purge_queue( cable_queue_info_t *q, int io )
{
while(q->num_items > 0)
{
int i = q->next_item;
if(q->data[i].action == CABLE_TRANSFER)
{
if(io == 0) /* todo queue */
{
if(q->data[i].arg.transfer.in != NULL) free(q->data[i].arg.transfer.in);
if(q->data[i].arg.transfer.out != NULL) free(q->data[i].arg.transfer.out);
}
else /* done queue */
{
if(q->data[i].arg.xferred.out != NULL) free(q->data[i].arg.xferred.out);
}
}
i++;
if(i >= q->max_items) i = 0;
q->num_items--;
};
q->num_items = 0;
q->next_item = 0;
q->next_free = 0;
}
void
cable_clock( cable_t *cable, int tms, int tdi, int n )
{
cable_flush( cable );
cable->driver->clock( cable, tms, tdi, n );
}
int
cable_defer_clock ( cable_t *cable, int tms, int tdi, int n )
{
int i = cable_add_queue_item( cable, &(cable->todo) );
if( i < 0 ) return 1; /* report failure */
cable->todo.data[i].action = CABLE_CLOCK;
cable->todo.data[i].arg.clock.tms = tms;
cable->todo.data[i].arg.clock.tdi = tdi;
cable->todo.data[i].arg.clock.n = n;
return 0; /* success */
}
int
cable_get_tdo( cable_t *cable )
{
cable_flush( cable );
return cable->driver->get_tdo( cable );
}
int
cable_get_tdo_late( cable_t *cable )
{
int i;
cable_flush( cable );
i = cable_get_queue_item( cable, &(cable->done) );
if( i >= 0 )
{
if(cable->done.data[i].action != CABLE_GET_TDO)
{
printf(_("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"),
cable->done.data[i].action, &(cable->done), i);
cable_purge_queue( &(cable->done), 1 );
}
else
{
return cable->done.data[i].arg.value.tdo;
}
};
return cable->driver->get_tdo( cable );
}
int
cable_defer_get_tdo( cable_t *cable )
{
int i = cable_add_queue_item( cable, &(cable->todo) );
if( i < 0 ) return 1; /* report failure */
cable->todo.data[i].action = CABLE_GET_TDO;
return 0; /* success */
}
int
cable_set_trst( cable_t *cable, int trst )
{
cable_flush( cable );
return cable->driver->set_trst( cable, trst );
}
int
cable_defer_set_trst( cable_t *cable, int trst )
{
int i = cable_add_queue_item( cable, &(cable->todo) );
if( i < 0 ) return 1; /* report failure */
cable->todo.data[i].action = CABLE_SET_TRST;
cable->todo.data[i].arg.value.trst = trst;
return 0; /* success */
}
int
cable_get_trst( cable_t *cable )
{
cable_flush( cable );
return cable->driver->get_trst( cable );
}
int
cable_get_trst_late( cable_t *cable )
{
int i;
cable_flush( cable );
i = cable_get_queue_item( cable, &(cable->done) );
if( i >= 0 )
{
if(cable->done.data[i].action != CABLE_GET_TRST)
{
printf(_("Internal error: Got wrong type of result from queue (%d? %p.%d)\n"),
cable->done.data[i].action, &(cable->done), i);
cable_purge_queue( &(cable->done), 1 );
}
else
{
return cable->done.data[i].arg.value.trst;
}
};
return cable->driver->get_trst( cable );
}
static uint32_t delay = 0;
static uint32_t frequency = 0;
int
cable_defer_get_trst( cable_t *cable )
{
int i = cable_add_queue_item( cable, &(cable->todo) );
if( i < 0 ) return 1; /* report failure */
cable->todo.data[i].action = CABLE_GET_TRST;
return 0; /* success */
}
int
cable_transfer( cable_t *cable, int len, char *in, char *out )
{
cable_flush( cable );
return cable->driver->transfer( cable, len, in, out );
}
int
cable_transfer_late( cable_t *cable, char *out )
{
int i;
cable_flush( cable );
i = cable_get_queue_item( cable, &(cable->done) );
if( i >= 0 && cable->done.data[i].action == CABLE_TRANSFER)
{
#if 0
printf("Got queue item (%p.%d) len=%d out=%p\n",
&(cable->done), i,
cable->done.data[i].arg.xferred.len,
cable->done.data[i].arg.xferred.out);
#endif
if(out) memcpy(out,
cable->done.data[i].arg.xferred.out,
cable->done.data[i].arg.xferred.len);
free(cable->done.data[i].arg.xferred.out);
return cable->done.data[i].arg.xferred.res;
};
if(cable->done.data[i].action != CABLE_TRANSFER)
{
printf(_("Internal error: Got wrong type of result from queue (#%d %p.%d)\n"),
cable->done.data[i].action, &(cable->done), i);
cable_purge_queue( &(cable->done), 1 );
}
else
{
printf(_("Internal error: Wanted transfer result but none was queued\n"));
}
return 0;
}
int
cable_defer_transfer( cable_t *cable, int len, char *in, char *out )
{
char *dbuf;
int i = cable_add_queue_item( cable, &(cable->todo) );
if( i < 0 ) return 1; /* report failure */
cable->todo.data[i].action = CABLE_TRANSFER;
cable->todo.data[i].arg.transfer.len = len;
dbuf = malloc(len);
if(dbuf == NULL) return 1; /* report failure */
if(in) memcpy(dbuf, in, len);
cable->todo.data[i].arg.transfer.in = dbuf;
if(out)
{
dbuf = malloc(len);
if(dbuf == NULL)
{
free(cable->todo.data[i].arg.transfer.in);
return 1; /* report failure */
}
cable->todo.data[i].arg.transfer.out = dbuf;
}
else
{
cable->todo.data[i].arg.transfer.out = NULL;
}
return 0; /* success */
}
void
cable_set_frequency( cable_t *cable, uint32_t new_frequency )
{
if (new_frequency == 0) {
delay = 0;
frequency = 0;
cable->delay = 0;
cable-> frequency = 0;
} else {
const double tolerance = 0.1;
uint32_t loops;
uint32_t delay = cable->delay;
uint32_t frequency = cable->frequency;
printf("requested frequency %u, now calibrating delay loop\n", new_frequency);
@ -201,29 +465,23 @@ cable_set_frequency( cable_t *cable, uint32_t new_frequency )
}
}
frequency = new_frequency;
cable->delay = delay;
cable->frequency = frequency;
}
}
uint32_t
cable_get_frequency( cable_t *cable )
{
return frequency;
}
int
cable_transfer( cable_t *cable, int len, char *in, char *out )
{
int r;
r=cable->driver->transfer( cable, len, in, out );
return r;
return cable->frequency;
}
void
cable_wait( void )
cable_wait( cable_t *cable )
{
int i;
volatile int j;
uint32_t delay = cable->delay;
if (delay == 0)
return;

@ -76,9 +76,9 @@ arcom_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -86,7 +86,7 @@ static int
arcom_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -112,5 +112,6 @@ cable_driver_t arcom_cable_driver = {
generic_transfer,
arcom_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -105,9 +105,9 @@ byteblaster_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -115,7 +115,7 @@ static int
byteblaster_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, 0 << TCK );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -138,5 +138,6 @@ cable_driver_t byteblaster_cable_driver = {
generic_transfer,
byteblaster_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -76,9 +76,9 @@ dlc5_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -86,7 +86,7 @@ static int
dlc5_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (1 << PROG) | (0 << TCK) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -109,5 +109,6 @@ cable_driver_t dlc5_cable_driver = {
generic_transfer,
dlc5_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -76,9 +76,9 @@ ea253_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -86,7 +86,7 @@ static int
ea253_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -112,5 +112,6 @@ cable_driver_t ea253_cable_driver = {
generic_transfer,
ea253_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -78,9 +78,9 @@ ei012_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -88,7 +88,7 @@ static int
ei012_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -114,5 +114,6 @@ cable_driver_t ei012_cable_driver = {
generic_transfer,
ei012_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -24,6 +24,8 @@
*
*/
#include <stdlib.h>
#include "sysdep.h"
#include "cable.h"
@ -93,11 +95,13 @@
#define BITMASK_ARMUSBOCD_nOE (1 << BIT_ARMUSBOCD_nOE)
#ifdef LAST_TDO_CACHE
/* global 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 */
static unsigned int last_tdo_valid;
static unsigned int last_tdo;
#endif
static uint32_t mpsse_frequency;
@ -166,7 +170,9 @@ ft2232_generic_init( cable_t *cable )
mpsse_frequency = FT2232_MAX_TCK_FREQ;
#ifdef LAST_TDO_CACHE
last_tdo_valid = 0;
#endif
return 0;
}
@ -201,7 +207,9 @@ ft2232_jtagkey_init( cable_t *cable )
mpsse_frequency = FT2232_MAX_TCK_FREQ;
#ifdef LAST_TDO_CACHE
last_tdo_valid = 0;
#endif
return 0;
}
@ -236,7 +244,9 @@ ft2232_armusbocd_init( cable_t *cable )
mpsse_frequency = FT2232_MAX_TCK_FREQ;
#ifdef LAST_TDO_CACHE
last_tdo_valid = 0;
#endif
return 0;
}
@ -304,7 +314,7 @@ ft2232_armusbocd_done( cable_t *cable )
}
static void
ft2232_clock( cable_t *cable, int tms, int tdi, int n )
ft2232_clock_defer( cable_t *cable, int defer, int tms, int tdi, int n )
{
parport_t *p = cable->port;
@ -327,29 +337,56 @@ ft2232_clock( cable_t *cable, int tms, int tdi, int n )
}
parport_set_data( p, tdi | tms );
}
parport_set_control( p, 1 ); // flush
parport_set_control( p, 0 ); // noflush
if (!defer) {
parport_set_control( p, 1 ); // flush
parport_set_control( p, 0 ); // noflush
last_tdo_valid = 0;
#ifdef LAST_TDO_CACHE
last_tdo_valid = 0;
#endif
}
}
static void
ft2232_clock( cable_t *cable, int tms, int tdi, int n )
{
ft2232_clock_defer( cable, 0, tms, tdi, n );
}
static void
ft2232_get_tdo_schedule( cable_t *cable )
{
parport_t *p = cable->port;
/* Read Data Bits Low Byte */
parport_set_data( p, GET_BITS_LOW );
}
static int
ft2232_get_tdo( cable_t *cable )
ft2232_get_tdo_finish( cable_t *cable )
{
parport_t *p = cable->port;
int value;
if (!last_tdo_valid) {
/* Read Data Bits Low Byte */
parport_set_data( p, GET_BITS_LOW );
parport_set_control( p, 1 ); // flush
parport_set_control( p, 0 ); // noflush
last_tdo = ( parport_get_data( p ) & BITMASK_TDO) ? 1 : 0;
value = ( parport_get_data( p ) & BITMASK_TDO) ? 1 : 0;
#ifdef LAST_TDO_CACHE
last_tdo_valid = 1;
last_tdo = value;
last_tdo_valid = 1;
#endif
}
return last_tdo;
return value;
}
static int
ft2232_get_tdo( cable_t *cable )
{
parport_t *p = cable->port;
ft2232_get_tdo_schedule( cable );
parport_set_control( p, 1 ); // flush
parport_set_control( p, 0 ); // noflush
return ft2232_get_tdo_finish( cable );
}
static int
@ -369,10 +406,11 @@ ft2232_transfer( cable_t *cable, int len, char *in, char *out )
/* check for new frequency setting */
update_frequency( cable );
#ifdef LAST_TDO_CACHE
/* invalidate TDO cache */
last_tdo_valid = 0;
#endif
/* Set Data Bits Low Byte to lower TMS for transfer
TCK = 0, TMS = 0, TDI = 0, nOE = 0 */
parport_set_data( p, SET_BITS_LOW );
parport_set_data( p, 0 );
parport_set_data( p, BITMASK_TCK | BITMASK_TDI | BITMASK_TMS | BITMASK_ARMUSBOCD_nOE );
while (len - in_offset > 0) {
int byte_idx;
@ -466,6 +504,11 @@ ft2232_transfer( cable_t *cable, int len, char *in, char *out )
parport_set_control( p, 1 ); // flush
parport_set_control( p, 0 ); // noflush
#ifdef LAST_TDO_CACHE
/* invalidate TDO cache */
last_tdo_valid = 0;
#endif
if (out) {
if (chunkbytes > 0) {
@ -527,6 +570,155 @@ ft2232_transfer( cable_t *cable, int len, char *in, char *out )
return 0;
}
#undef FLUSH_PUTS
static void
ft2232_flush( cable_t *cable )
{
#ifdef FLUSH_PUTS
puts("flush()");
#endif
while (cable->todo.num_items > 0)
{
int i, j, n, to_send = 0, to_rec = 0;
#ifdef LAST_TDO_CACHE
int last_tdo_valid_schedule = last_tdo_valid;
int last_tdo_valid_finish = last_tdo_valid;
#endif
for(j=i=cable->todo.next_item, n=0; to_send < 64 && n<cable->todo.num_items; n++)
{
if(cable->todo.data[i].action == CABLE_TRANSFER) {
#ifdef FLUSH_PUTS
puts("transfer");
#endif
break;
}
switch(cable->todo.data[i].action) {
case CABLE_CLOCK:
#ifdef FLUSH_PUTS
puts("clock");
#endif
ft2232_clock_defer( cable, 1,
cable->todo.data[i].arg.clock.tms,
cable->todo.data[i].arg.clock.tdi,
cable->todo.data[i].arg.clock.n );
to_send += 3;
#ifdef LAST_TDO_CACHE
last_tdo_valid_schedule = 0;
#endif
break;
case CABLE_GET_TDO:
#ifdef LAST_TDO_CACHE
if (!last_tdo_valid_schedule) {
#else
{
#endif
ft2232_get_tdo_schedule( cable );
#ifdef FLUSH_PUTS
puts("get_tdo");
#endif
to_send += 1;
to_rec += 1;
#ifdef LAST_TDO_CACHE
last_tdo_valid_schedule = 1;
#endif
}
break;
default:
break;
}
i++;
if (i >= cable->todo.max_items) i=0;
}
if(to_rec > 0)
{
#ifdef FLUSH_PUTS
puts("flush");
#endif
parport_set_control( cable->port, 1 ); // flush
parport_set_control( cable->port, 0 );
}
while(j!=i)
{
switch(cable->todo.data[j].action)
{
case CABLE_CLOCK:
#ifdef LAST_TDO_CACHE
last_tdo_valid_finish = 0;
#endif
break;
case CABLE_GET_TDO:
{
int tdo;
int m;
#ifdef LAST_TDO_CACHE
if (last_tdo_valid_finish) {
tdo = last_tdo;
#ifdef FLUSH_PUTS
puts("tdo cached");
#endif
} else
tdo = ft2232_get_tdo_finish( cable );
last_tdo_valid_finish = 1;
#else
tdo = ft2232_get_tdo_finish( cable );
#endif
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_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;
}
default:
break;
};
j++;
if (j >= cable->todo.max_items) j=0;
cable->todo.num_items --;
};
while(cable->todo.num_items > 0 && cable->todo.data[i].action == CABLE_TRANSFER)
{
int r = ft2232_transfer( cable,
cable->todo.data[i].arg.transfer.len,
cable->todo.data[i].arg.transfer.in,
cable->todo.data[i].arg.transfer.out);
free(cable->todo.data[i].arg.transfer.in);
if(cable->todo.data[i].arg.transfer.out != NULL)
{
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[i].arg.transfer.len;
cable->done.data[m].arg.xferred.res = r;
cable->done.data[m].arg.xferred.out = cable->todo.data[i].arg.transfer.out;
};
i++;
if (i >= cable->todo.max_items) i=0;
cable->todo.num_items --;
};
cable->todo.next_item = i;
}
}
void
ft2232_usbcable_help( const char *cablename )
{
@ -552,6 +744,7 @@ cable_driver_t ft2232_cable_driver = {
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_flush,
ft2232_usbcable_help
};
@ -568,6 +761,8 @@ cable_driver_t ft2232_armusbocd_cable_driver = {
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
// generic_flush_using_transfer,
ft2232_flush,
ft2232_usbcable_help
};
@ -584,6 +779,7 @@ cable_driver_t ft2232_jtagkey_cable_driver = {
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_flush,
ft2232_usbcable_help
};

@ -36,6 +36,17 @@
#include <cmd.h>
#undef VERBOSE
#ifdef VERBOSE
void
print_vector(int len, char *vec)
{
int i;
for(i=0;i<len;i++) printf("%c",vec[i]?'1':'0');
}
#endif
int
generic_connect( char *params[], cable_t *cable )
{
@ -107,12 +118,12 @@ generic_transfer( cable_t *cable, int len, char *in, char *out )
if(out)
for(i=0; i<len; i++) {
out[i] = cable_get_tdo( cable );
cable_clock( cable, 0, in[i], 1 );
out[i] = cable->driver->get_tdo( cable );
cable->driver->clock( cable, 0, in[i], 1 );
}
else
for(i=0; i<len; i++) {
cable_clock( cable, 0, in[i], 1 );
cable->driver->clock( cable, 0, in[i], 1 );
}
return i;
@ -124,6 +135,265 @@ generic_get_trst( cable_t *cable )
return PARAM_TRST(cable);
}
int
do_one_queued_action( cable_t *cable )
{
int i;
#ifdef VERBOSE
printf("do_one_queued\n");
#endif
if ( (i = cable_get_queue_item( cable, &(cable->todo) )) >= 0 )
{
int j;
if( cable->done.num_items >= cable->done.max_items )
{
if( cable->todo.data[i].action == CABLE_GET_TDO
|| cable->todo.data[i].action == CABLE_GET_TRST
|| cable->todo.data[i].action == CABLE_TRANSFER )
{
printf(_("No space in cable activity results queue.\n"));
cable_purge_queue( &(cable->done), 1 );
}
};
switch(cable->todo.data[i].action)
{
case CABLE_CLOCK:
cable->driver->clock( cable,
cable->todo.data[i].arg.clock.tms,
cable->todo.data[i].arg.clock.tdi,
cable->todo.data[i].arg.clock.n );
break;
case CABLE_SET_TRST:
cable_set_trst( cable,
cable->todo.data[i].arg.value.trst );
break;
case CABLE_TRANSFER:
{
int r = cable->driver->transfer( cable,
cable->todo.data[i].arg.transfer.len,
cable->todo.data[i].arg.transfer.in,
cable->todo.data[i].arg.transfer.out);
free(cable->todo.data[i].arg.transfer.in);
if(cable->todo.data[i].arg.transfer.out != NULL)
{
j = cable_add_queue_item( cable, &(cable->done) );
#ifdef VERBOSE
printf("add result from transfer to %p.%d (out=%p)\n", &(cable->done), j, cable->todo.data[i].arg.transfer.out);
#endif
cable->done.data[j].action = CABLE_TRANSFER;
cable->done.data[j].arg.xferred.len = cable->todo.data[i].arg.transfer.len;
cable->done.data[j].arg.xferred.res = r;
cable->done.data[j].arg.xferred.out = cable->todo.data[i].arg.transfer.out;
};
break;
};
case CABLE_GET_TDO:
j = cable_add_queue_item( cable, &(cable->done) );
#ifdef VERBOSE
printf("add result from get_tdo to %p.%d\n", &(cable->done), j);
#endif
cable->done.data[j].action = CABLE_GET_TDO;
cable->done.data[j].arg.value.tdo =
cable->driver->get_tdo( cable );
break;
case CABLE_GET_TRST:
j = cable_add_queue_item( cable, &(cable->done) );
#ifdef VERBOSE
printf("add result from get_trst to %p.%d\n", &(cable->done), j);
#endif
cable->done.data[j].action = CABLE_GET_TRST;
cable->done.data[j].arg.value.trst =
cable->driver->get_trst( cable );
break;
};
#ifdef VERBOSE
printf("do_one_queued done\n");
#endif
return 1;
}
#ifdef VERBOSE
printf("do_one_queued abort\n");
#endif
return 0;
}
void
generic_flush_one_by_one( cable_t *cable )
{
while( do_one_queued_action( cable ) );
}
void
generic_flush_using_transfer( cable_t *cable )
{
int i, j, n;
char *in, *out;
if(cable->todo.num_items == 0) return;
do
{
int r, bits = 0, tdo;
#ifdef VERBOSE
printf("flush(%d)\n", cable->todo.num_items);
#endif
/* Combine as much as possible into transfer() */
/* Step 1: Count clocks. Can do only clock(TMS=0), get_tdo, transfer */
for(i = cable->todo.next_item, n=0; n < cable->todo.num_items; n++)
{
if(cable->todo.data[i].action != CABLE_CLOCK
&& cable->todo.data[i].action != CABLE_TRANSFER
&& cable->todo.data[i].action != CABLE_GET_TDO)
{
#ifdef VERBOSE
printf("cutoff at n=%d because action unsuitable for transfer\n", n);
#endif
break;
}
if(cable->todo.data[i].action == CABLE_CLOCK
&& cable->todo.data[i].arg.clock.tms != 0)
{
#ifdef VERBOSE
printf("cutoff at n=%d because clock.tms=1 is unsuitable for transfer\n", n);
#endif
break;
}
if(cable->todo.data[i].action == CABLE_CLOCK)
{
int k = cable->todo.data[i].arg.clock.n;
#ifdef VERBOSE
printf("%d clock(s)\n", k);
#endif
bits += k;
}
else if(cable->todo.data[i].action == CABLE_TRANSFER)
{
int k = cable->todo.data[i].arg.transfer.len;
#ifdef VERBOSE
printf("%d transfer\n", k);
#endif
bits += k;
}
i++;
if(i >= cable->todo.max_items) i = 0;
};
#ifdef VERBOSE
printf("%d combined into one (%d bits)\n", n, bits);
#endif
if(bits == 0 || n <= 1)
{
do_one_queued_action( cable );
}
else
{
/* Step 2: Combine into single transfer. */
in = malloc(bits);
out = malloc(bits);
if(in == NULL || out == NULL)
{
if(in != NULL) free(in);
if(out != NULL) free(out);
generic_flush_one_by_one( cable );
break;
};
for(j=0, bits=0, i=cable->todo.next_item; j<n; j++)
{
if(cable->todo.data[i].action == CABLE_CLOCK)
{
int k;
for(k=0;k<cable->todo.data[i].arg.clock.n;k++)
in[bits++] = cable->todo.data[i].arg.clock.tdi;
}
else if(cable->todo.data[i].action == CABLE_TRANSFER)
{
int len = cable->todo.data[i].arg.transfer.len;
if(len>0)
{
memcpy(in+bits, cable->todo.data[i].arg.transfer.in, len);
bits += len;
};
};
i++;
if(i >= cable->todo.max_items) i = 0;
};
/* Step 3: Do the transfer */
r = cable->driver->transfer( cable, bits, in, out );
#ifdef VERBOSE
printf("in: "); print_vector(bits,in); printf("\n");
if(out) { printf("out: "); print_vector(bits,out); printf("\n"); };
#endif
/* Step 4: Pick results from transfer */
for(j=0, bits=0, i=cable->todo.next_item; j<n; j++)
{
if(cable->todo.data[i].action == CABLE_CLOCK)
{
int k;
for(k=0;k<cable->todo.data[i].arg.clock.n;k++)
tdo = out[bits++];
}
else if(cable->todo.data[i].action == CABLE_GET_TDO)
{
int c = cable_add_queue_item( cable, &(cable->done) );
#ifdef VERBOSE
printf("add result from transfer to %p.%d\n", &(cable->done), c);
#endif
cable->done.data[c].action = CABLE_GET_TDO;
cable->done.data[c].arg.value.tdo = tdo;
}
else if(cable->todo.data[i].action == CABLE_TRANSFER)
{
char *p = cable->todo.data[i].arg.transfer.out;
int len = cable->todo.data[i].arg.transfer.len;
free(cable->todo.data[i].arg.transfer.in);
if(p != NULL)
{
int c = cable_add_queue_item( cable, &(cable->done) );
#ifdef VERBOSE
printf("add result from transfer to %p.%d\n", &(cable->done), c);
#endif
cable->done.data[c].action = CABLE_TRANSFER;
cable->done.data[c].arg.xferred.len = len;
cable->done.data[c].arg.xferred.res = r;
cable->done.data[c].arg.xferred.out = p;
if(len > 0) memcpy(p, out+bits, len);
}
if(len>0) bits += len;
if(bits>0) tdo = out[bits-1];
};
i++;
if(i >= cable->todo.max_items) i = 0;
}
cable->todo.next_item = i;
cable->todo.num_items -= n;
free(in);
free(out);
}
}
while(cable->todo.num_items > 0);
}
void
generic_lptcable_help( const char *cablename )
{

@ -42,6 +42,8 @@ void generic_cable_free( cable_t *cable );
void generic_done( cable_t *cable );
int generic_transfer( cable_t *cable, int len, char *in, char *out );
int generic_get_trst( cable_t *cable );
void generic_flush_one_by_one( cable_t *cable );
void generic_flush_using_transfer( cable_t *cable );
void generic_lptcable_help( const char *name );
#endif /* GENERIC_H */

@ -171,6 +171,7 @@ cable_driver_t jim_cable_driver = {
generic_transfer,
jim_cable_set_trst,
jim_cable_get_trst,
generic_flush_using_transfer,
jim_cable_help
};

@ -85,9 +85,9 @@ keithkoep_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -95,7 +95,7 @@ static int
keithkoep_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, 0 << TCK );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -121,5 +121,6 @@ cable_driver_t keithkoep_cable_driver = {
generic_transfer,
keithkoep_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -71,9 +71,9 @@ lattice_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) );
cable_wait();
cable_wait( cable );
}
}
@ -81,7 +81,7 @@ static int
lattice_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (0 << TCK) | (1 << TRST) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -104,5 +104,6 @@ cable_driver_t lattice_cable_driver = {
generic_transfer,
lattice_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -82,9 +82,9 @@ mpcbdm_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -92,7 +92,7 @@ static int
mpcbdm_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, 0 << TCK );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -118,5 +118,6 @@ cable_driver_t mpcbdm_cable_driver = {
generic_transfer,
mpcbdm_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -87,9 +87,9 @@ triton_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -97,7 +97,7 @@ static int
triton_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -123,5 +123,6 @@ cable_driver_t triton_cable_driver = {
generic_transfer,
triton_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -25,6 +25,8 @@
#include "sysdep.h"
#include <stdlib.h>
#include "cable.h"
#include "parport.h"
#include "chain.h"
@ -62,12 +64,14 @@ usbblaster_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
tms = tms ? (1<<TMS) : 0;
tdi = tdi ? (1<<TDI) : 0;
// printf("clock: %d %d %d\n", tms, tdi, n);
for (i = 0; i < n; i++) {
parport_set_data( cable->port, OTHERS | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->port, OTHERS | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->port, OTHERS | (0 << TCK) | tms | tdi );
parport_set_data( cable->port, OTHERS | (1 << TCK) | tms | tdi );
parport_set_control( cable->port, 1 ); // flush
parport_set_control( cable->port, 0 ); // noflush
}
@ -106,6 +110,15 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out )
parport_set_control( cable->port, 0 );
parport_set_data( cable->port, OTHERS ); /* TCK low */
#if 0
{
int o;
printf("%d in: ", len);
for(o=0;o<len;o++) printf("%c", in[o]?'1':'0');
printf("\n");
}
#endif
while(len - in_offset >= 8)
{
int i;
@ -158,11 +171,134 @@ usbblaster_transfer( cable_t *cable, int len, char *in, char *out )
while(len > out_offset)
out[out_offset++] = ( parport_get_data( cable->port ) & (1 << TDO)) ? 1 : 0;
#if 0
{
int o;
printf("%d out: ", len);
for(o=0;o<len;o++) printf("%c", out[o]?'1':'0');
printf("\n");
}
#endif
}
return 0;
}
static void
usbblaster_flush( cable_t *cable )
{
while (cable->todo.num_items > 0)
{
int i, j, n, to_send = 0;
for(j=i=cable->todo.next_item, n=0; to_send < 64 && n<cable->todo.num_items; n++)
{
if(cable->todo.data[i].action == CABLE_TRANSFER) break;
switch(cable->todo.data[i].action)
{
case CABLE_CLOCK:
{
int tms = cable->todo.data[i].arg.clock.tms ? (1<<TMS) : 0;
int tdi = cable->todo.data[i].arg.clock.tdi ? (1<<TDI) : 0;
int m = cable->todo.data[i].arg.clock.n;
// printf("clock: %d %d %d\n", tms, tdi, m);
for(; m>0; m--)
{
parport_set_data( cable->port, OTHERS | tms | tdi );
parport_set_data( cable->port, OTHERS | (1 << TCK) | tms | tdi );
to_send += 2;
}
break;
}
case CABLE_GET_TDO:
{
parport_set_data( cable->port, OTHERS ); /* TCK low */
parport_set_data( cable->port, OTHERS | (1 << READ) ); /* TCK low */
// printf("get_tdo\n");
to_send += 2;
break;
}
default:
break;
};
i++;
if (i >= cable->todo.max_items) i=0;
};
#if 0
if(cable->todo.num_items > 0 && cable->todo.data[i].action == CABLE_TRANSFER)
{
parport_set_data( cable->port, OTHERS ); /* TCK low */
};
#endif
if(to_send > 0)
{
parport_set_control( cable->port, 1 ); // flush
parport_set_control( cable->port, 0 );
}
while(j!=i)
{
switch(cable->todo.data[j].action)
{
case CABLE_GET_TDO:
{
int tdo = (parport_get_data( cable->port ) & (1<<TDO)) ? 1 : 0;
int 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_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;
}
default:
break;
};
j++;
if (j >= cable->todo.max_items) j=0;
cable->todo.num_items --;
};
while(cable->todo.num_items > 0 && cable->todo.data[i].action == CABLE_TRANSFER)
{
int r = usbblaster_transfer( cable,
cable->todo.data[i].arg.transfer.len,
cable->todo.data[i].arg.transfer.in,
cable->todo.data[i].arg.transfer.out);
free(cable->todo.data[i].arg.transfer.in);
if(cable->todo.data[i].arg.transfer.out != NULL)
{
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[i].arg.transfer.len;
cable->done.data[m].arg.xferred.res = r;
cable->done.data[m].arg.xferred.out = cable->todo.data[i].arg.transfer.out;
};
i++;
if (i >= cable->todo.max_items) i=0;
cable->todo.num_items --;
};
cable->todo.next_item = i;
}
}
void
usbblaster_help( const char *cablename )
{
@ -188,5 +324,8 @@ cable_driver_t usbblaster_cable_driver = {
usbblaster_transfer,
usbblaster_set_trst,
generic_get_trst,
// generic_flush_one_by_one,
// generic_flush_using_transfer,
usbblaster_flush,
usbblaster_help,
};

@ -319,5 +319,6 @@ cable_driver_t ep9307_cable_driver = {
generic_transfer,
ep9307_set_trst,
ep9307_get_trst,
generic_flush_one_by_one,
ep9307_help
};

@ -245,13 +245,13 @@ wiggler_clock( cable_t *cable, int tms, int tdi, int n )
(tms ? PRM_TMS_ACT(cable) : PRM_TMS_INACT(cable)) |
(tdi ? PRM_TDI_ACT(cable) : PRM_TDI_INACT(cable)) |
PRM_UNUSED_BITS(cable) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, PRM_TRST_LVL(cable) |
PRM_TCK_ACT(cable) |
(tms ? PRM_TMS_ACT(cable) : PRM_TMS_INACT(cable)) |
(tdi ? PRM_TDI_ACT(cable) : PRM_TDI_INACT(cable)) |
PRM_UNUSED_BITS(cable) );
cable_wait();
cable_wait( cable );
}
}
@ -261,7 +261,7 @@ wiggler_get_tdo( cable_t *cable )
parport_set_data( cable->port, PRM_TRST_LVL(cable) |
PRM_TCK_INACT(cable) |
PRM_UNUSED_BITS(cable) );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) & (PRM_TDO_ACT(cable) | PRM_TDO_INACT(cable))) ^
PRM_TDO_ACT(cable) ? 0 : 1;
}
@ -329,6 +329,7 @@ cable_driver_t wiggler_cable_driver = {
generic_transfer,
wiggler_set_trst,
wiggler_get_trst,
generic_flush_one_by_one,
wiggler_help
};
@ -345,6 +346,7 @@ cable_driver_t igloo_cable_driver = {
generic_transfer,
wiggler_set_trst,
wiggler_get_trst,
generic_flush_one_by_one,
wiggler_help
};

@ -92,9 +92,9 @@ wiggler2_clock( cable_t *cable, int tms, int tdi, int n )
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS );
cable_wait();
cable_wait( cable );
}
}
@ -102,7 +102,7 @@ static int
wiggler2_get_tdo( cable_t *cable )
{
parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | UNUSED_BITS );
cable_wait();
cable_wait( cable );
return (parport_get_status( cable->port ) >> TDO) & 1;
}
@ -128,5 +128,6 @@ cable_driver_t wiggler2_cable_driver = {
generic_transfer,
wiggler2_set_trst,
generic_get_trst,
generic_flush_one_by_one,
generic_lptcable_help
};

@ -73,12 +73,12 @@ xpc_clock( cable_t *cable, int tms, int tdi, int n )
tdi = tdi ? 1 : 0;
parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
for (i = 0; i < n; i++) {
parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait();
cable_wait( cable );
}
}
@ -119,6 +119,7 @@ cable_driver_t xpc_int_cable_driver = {
generic_transfer,
xpc_set_trst,
generic_get_trst,
generic_flush_using_transfer,
xpcu_usbcable_help
};
@ -135,6 +136,7 @@ cable_driver_t xpc_ext_cable_driver = {
generic_transfer,
xpc_set_trst,
generic_get_trst,
generic_flush_using_transfer,
xpcu_usbcable_help
};

@ -83,6 +83,20 @@ chain_clock( chain_t *chain, int tms, int tdi, int n )
tap_state_clock( chain, tms );
}
void
chain_defer_clock( chain_t *chain, int tms, int tdi, int n )
{
int i;
if (!chain || !chain->cable)
return;
cable_defer_clock( chain->cable, tms, tdi, n );
for (i = 0; i < n; i++)
tap_state_clock( chain, tms );
}
int
chain_set_trst( chain_t *chain, int trst )
{

@ -36,9 +36,8 @@ tap_reset( chain_t *chain )
{
tap_state_reset( chain );
chain_clock( chain, 1, 0, 5 ); /* Test-Logic-Reset */
chain_clock( chain, 0, 0, 1 ); /* Run-Test/Idle */
chain_defer_clock( chain, 1, 0, 5 ); /* Test-Logic-Reset */
chain_defer_clock( chain, 0, 0, 1 ); /* Run-Test/Idle */
parts_set_instruction( chain->parts, "BYPASS" );
}
@ -46,33 +45,43 @@ tap_reset( chain_t *chain )
void
tap_shift_register( chain_t *chain, const tap_register *in, tap_register *out, int exit )
{
int i;
int i,j;
if (!(tap_state( chain ) & TAPSTAT_SHIFT))
printf( _("%s: Invalid state: %2X\n"), "tap_shift_register", tap_state( chain ) );
/* Capture-DR, Capture-IR, Shift-DR, Shift-IR, Exit2-DR or Exit2-IR state */
if (tap_state( chain ) & TAPSTAT_CAPTURE)
chain_clock( chain, 0, 0, 1 ); /* save last TDO bit :-) */
chain_defer_clock( chain, 0, 0, 1 ); /* save last TDO bit :-) */
i = in->len;
if(exit) i--;
if(out && out->len < i) i = out->len;
if(out)
cable_transfer( chain->cable, i, in->data, out->data );
cable_defer_transfer( chain->cable, i, in->data, out->data );
else
cable_transfer( chain->cable, i, in->data, NULL );
cable_defer_transfer( chain->cable, i, in->data, NULL );
j = i;
for (; i < in->len; i++) {
if (out && (i < out->len))
out->data[i] = cable_get_tdo( chain->cable );
chain_clock( chain, (exit != EXITMODE_SHIFT && ((i + 1) == in->len)) ? 1 : 0, in->data[i], 1 ); /* Shift (& Exit1) */
if (out != NULL && (i < out->len))
out->data[i] = cable_defer_get_tdo( chain->cable );
chain_defer_clock( chain, (exit != EXITMODE_SHIFT && ((i + 1) == in->len)) ? 1 : 0, in->data[i], 1 ); /* Shift (& Exit1) */
}
/* Shift-DR, Shift-IR, Exit1-DR or Exit1-IR state */
if (exit == EXITMODE_IDLE) {
chain_clock( chain, 1, 0, 1 ); /* Update-DR or Update-IR */
chain_clock( chain, 0, 0, 1 ); /* Run-Test/Idle */
chain_defer_clock( chain, 1, 0, 1 ); /* Update-DR or Update-IR */
chain_defer_clock( chain, 0, 0, 1 ); /* Run-Test/Idle */
}
if(out != NULL)
{
/* Asking for the result of the cable transfer actually flushes the queue */
(void)cable_transfer_late( chain->cable, out->data );
for (; j < in->len && j < out->len; j++)
out->data[j] = cable_get_tdo_late( chain->cable );
}
}
@ -83,8 +92,8 @@ tap_capture_dr( chain_t *chain )
printf( _("%s: Invalid state: %2X\n"), "tap_capture_dr", tap_state( chain ) );
/* Run-Test/Idle or Update-DR or Update-IR state */
chain_clock( chain, 1, 0, 1 ); /* Select-DR-Scan */
chain_clock( chain, 0, 0, 1 ); /* Capture-DR */
chain_defer_clock( chain, 1, 0, 1 ); /* Select-DR-Scan */
chain_defer_clock( chain, 0, 0, 1 ); /* Capture-DR */
}
void
@ -94,6 +103,6 @@ tap_capture_ir( chain_t *chain )
printf( _("%s: Invalid state: %2X\n"), "tap_capture_ir", tap_state( chain ) );
/* Run-Test/Idle or Update-DR or Update-IR state */
chain_clock( chain, 1, 0, 2 ); /* Select-DR-Scan, then Select-IR-Scan */
chain_clock( chain, 0, 0, 1 ); /* Capture-IR */
chain_defer_clock( chain, 1, 0, 2 ); /* Select-DR-Scan, then Select-IR-Scan */
chain_defer_clock( chain, 0, 0, 1 ); /* Capture-IR */
}

Loading…
Cancel
Save