[2187351] Direct JTAG signal access, get/set_trst extension integrated from getset_pod branch

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1419 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Kolja Waschk 16 years ago
parent 8fb546d493
commit dde7398208

@ -1,3 +1,25 @@
2009-01-19 Kolja Waschk <kawk>
* doc/UrJTAG.txt,
include/cable.h, include/chain.h, include/pod.h, include/Makefile.am,
src/cmd/cmd.c, src/cmd/pod.c, src/cmd/Makefile.am, src/tap/cable.c,
src/tap/chain.c, src/tap/cable/wiggler.c, src/tap/cable/arcom.c,
src/tap/cable/mpcbdm.c, src/tap/cable/ts7800.c,
src/tap/cable/usbblaster.c, src/tap/cable/jlink.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/ei012.c,
src/tap/cable/byteblaster.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/svf/svf.c:
[ 2187351 ] Direct JTAG signal access, get/set_trst extension;
Integrated changes from getset_pod branch, substituting the
get/set_trst cable functions with more mighty get/set_signal
functions. Finally, this gives low level access to cable signals
as Sebastian Hesselbarth suggested and implemented first (thanks).
Arnim implemented it for the FTDI cable drivers, while I worked
on the parport cable drivers and new "pod" command.
2009-01-16 Arnim Laeuger <arniml@users.sourceforge.net>
* src/cmd/parse.c: flush_chain() between commands read from file

@ -816,6 +816,7 @@ of the TAP controller(s) and registers in the chain:
*dr*:: display or set active data register for a part
*instruction*:: change active instruction for a part or declare new instruction
*get*:: get external signal value
*pod*:: low level direct access to POD signals like TRST; use with care
*scan*:: detect changes on input pins of current part
*set*:: set external signal value
*shift*:: shift data/instruction registers through JTAG chain

@ -50,6 +50,7 @@ noinst_HEADERS = \
fclock.h \
jim.h \
jim/some_cpu.h \
pod.h \
svf.h \
usbconn.h \
usbconn/libftdx.h \

@ -33,6 +33,7 @@ typedef struct cable_t cable_t;
#include "usbconn.h"
#include "parport.h"
#include "chain.h"
#include "pod.h"
typedef struct cable_driver_t cable_driver_t;
@ -56,8 +57,8 @@ struct cable_driver_t {
void (*clock)( cable_t *, int, int, int );
int (*get_tdo)( cable_t * );
int (*transfer)( cable_t *, int, char *, char * );
int (*set_trst)( cable_t *, int );
int (*get_trst)( cable_t * );
int (*set_signal)( cable_t *, int, int );
int (*get_signal)( cable_t *, pod_sigsel_t );
void (*flush)( cable_t *, cable_flush_amount_t );
void (*help)( const char * );
};
@ -69,8 +70,8 @@ struct cable_queue_t {
CABLE_CLOCK,
CABLE_GET_TDO,
CABLE_TRANSFER,
CABLE_SET_TRST,
CABLE_GET_TRST
CABLE_SET_SIGNAL,
CABLE_GET_SIGNAL
} action;
union {
struct {
@ -79,8 +80,8 @@ struct cable_queue_t {
int n;
} clock;
struct {
int tdo;
int trst;
pod_sigsel_t sig;
int mask;
int val;
} value;
struct {
@ -129,11 +130,11 @@ void cable_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_set_signal( cable_t *cable, int mask, int val );
int cable_defer_set_signal( cable_t *cable, int mask, int val );
int cable_get_signal( cable_t *cable, pod_sigsel_t sig );
int cable_get_signal_late( cable_t *cable, pod_sigsel_t sig );
int cable_defer_get_signal( cable_t *cable, pod_sigsel_t sig );
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 );

@ -26,6 +26,7 @@
#define CHAIN_H
#include "part.h"
#include "pod.h"
typedef struct chain_t chain_t;
@ -58,6 +59,8 @@ void chain_shift_instructions_mode( chain_t *chain, int capture_output, int capt
void chain_shift_data_registers( chain_t *chain, int capture_output );
void chain_shift_data_registers_mode( chain_t *chain, int capture_output, int capture, int exit );
void chain_flush( chain_t *chain );
int chain_set_pod_signal( chain_t *chain, int mask, int val );
int chain_get_pod_signal( chain_t *chain, pod_sigsel_t sig );
typedef struct {
chain_t **chains;

@ -0,0 +1,41 @@
/*
* $Id$
*
* Pod signal names
* Copyright (C) 2008 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.
*
*/
#ifndef POD_H
#define POD_H
typedef enum
{
CS_NONE = 0, // no/invalid signal
CS_TDI = (1<<0), // out: JTAG/SPI data in
CS_TCK = (1<<1), // out: JTAG/SPI clock
CS_TMS = (1<<2), // out: JTAG test mode select/SPI slave select
CS_TRST = (1<<3), // out: JTAG TAP reset
CS_RESET = (1<<4), // out: system reset
CS_SCK = (1<<5), // out: I2C clock (not yet used)
CS_SDA = (1<<6), // inout: I2C data (not yet used)
CS_SS = (1<<7), // out: SPI slave select (not yet used)
}
pod_sigsel_t;
#endif /* POD_H */

@ -55,6 +55,7 @@ libcmd_a_SOURCES = \
endian.c \
parse.c \
peekpoke.c \
pod.c \
readmem.c \
writemem.c \
flashmem.c \

@ -61,6 +61,7 @@ extern cmd_t cmd_set;
extern cmd_t cmd_endian;
extern cmd_t cmd_peek;
extern cmd_t cmd_poke;
extern cmd_t cmd_pod;
extern cmd_t cmd_readmem;
extern cmd_t cmd_writemem;
extern cmd_t cmd_detectflash;
@ -106,6 +107,7 @@ const cmd_t *cmds[] = {
&cmd_endian,
&cmd_peek,
&cmd_poke,
&cmd_pod,
&cmd_readmem,
&cmd_writemem,
&cmd_detectflash,

@ -0,0 +1,91 @@
/*
* $Id$
*
* Copyright (C) 2008 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, 2008
* based on idea and code by Sebastian Hesselbarth, 2008
* and code by Marcel Telka <marcel@telka.sk>, 2003.
*
*/
#include "sysdep.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jtag.h"
#include <cable.h>
#include "cmd.h"
static int
cmd_pod_run( chain_t *chain, char *params[] )
{
int i,j;
int mask = 0;
int val = 0;
if ((i = cmd_params( params )) < 2)
return -1;
if (!cmd_test_cable( chain ))
return -1;
for (j=1; j<i; j++)
{
char *eq = strrchr(params[j], '=');
if (!eq)
return -1;
pod_sigsel_t it = CS_NONE;
int n = strlen(params[j]);
if (n > 4 && (strncasecmp(params[j], "tck", 3) == 0)) it = CS_TCK;
else if (n > 4 && (strncasecmp(params[j], "tms", 3) == 0)) it = CS_TMS;
else if (n > 4 && (strncasecmp(params[j], "tdi", 3) == 0)) it = CS_TDI;
else if (n > 5 && (strncasecmp(params[j], "trst", 3) == 0)) it = CS_TRST;
else if (n > 6 && (strncasecmp(params[j], "reset", 3) == 0)) it = CS_RESET;
if (it == CS_NONE)
return -1;
mask |= it;
if (atoi(eq+1) != 0) val |= it;
}
chain_set_pod_signal( chain, mask, val );
return 1;
}
static void
cmd_pod_help( void )
{
printf( _(
"Usage: %s SIGNAL=# [SIGNAL=# ...]\n"
"Set state of POD signal(s) to 0 or 1.\n"
"\n"
"SIGNAL e.g. TCK,TMS or TDI\n"
"# 0 or 1\n"
), "pod" );
}
cmd_t cmd_pod = {
"pod",
N_("Set state of POD signal(s)"),
cmd_pod_help,
cmd_pod_run
};

@ -978,7 +978,7 @@ svf_trst(chain_t *chain, parser_priv_t *priv, int trst_mode)
printf( _("Warning %s: unimplemented mode '%s' for TRST\n"), "svf",
unimplemented_mode);
else
cable_set_trst(chain->cable, trst_cable);
cable_set_signal(chain->cable, CS_TRST, trst_cable ? CS_TRST : 0);
return(1);
}

@ -406,7 +406,7 @@ cable_get_tdo_late( cable_t *cable )
}
else
{
return cable->done.data[i].arg.value.tdo;
return cable->done.data[i].arg.value.val;
}
};
return cable->driver->get_tdo( cable );
@ -423,58 +423,66 @@ cable_defer_get_tdo( cable_t *cable )
}
int
cable_set_trst( cable_t *cable, int trst )
cable_set_signal( cable_t *cable, int mask, int val )
{
cable_flush( cable, COMPLETELY );
return cable->driver->set_trst( cable, trst );
return cable->driver->set_signal( cable, mask, val );
}
int
cable_defer_set_trst( cable_t *cable, int trst )
cable_defer_set_signal( cable_t *cable, int mask, int val )
{
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;
cable->todo.data[i].action = CABLE_SET_SIGNAL;
cable->todo.data[i].arg.value.mask = mask;
cable->todo.data[i].arg.value.val = val;
cable_flush( cable, OPTIONALLY );
return 0; /* success */
}
int
cable_get_trst( cable_t *cable )
cable_get_signal( cable_t *cable, pod_sigsel_t sig )
{
cable_flush( cable, COMPLETELY );
return cable->driver->get_trst( cable );
return cable->driver->get_signal( cable, sig );
}
int
cable_get_trst_late( cable_t *cable )
cable_get_signal_late( cable_t *cable, pod_sigsel_t sig )
{
int i;
cable_flush( cable, TO_OUTPUT );
i = cable_get_queue_item( cable, &(cable->done) );
if( i >= 0 )
{
if(cable->done.data[i].action != CABLE_GET_TRST)
if(cable->done.data[i].action != CABLE_GET_SIGNAL)
{
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 if(cable->done.data[i].arg.value.sig != sig)
{
printf(_("Internal error: Got wrong signal's value 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->done.data[i].arg.value.val;
}
};
return cable->driver->get_trst( cable );
return cable->driver->get_signal( cable, sig );
}
int
cable_defer_get_trst( cable_t *cable )
cable_defer_get_signal( cable_t *cable, pod_sigsel_t sig )
{
int i = cable_add_queue_item( cable, &(cable->todo) );
if( i < 0 ) return 1; /* report failure */
cable->todo.data[i].action = CABLE_GET_TRST;
cable->todo.data[i].action = CABLE_GET_SIGNAL;
cable->todo.data[i].arg.value.sig = sig;
cable_flush( cable, OPTIONALLY );
return 0; /* success */
}

@ -60,9 +60,9 @@ arcom_init( cable_t *cable )
if ((data = parport_get_data( cable->link.port )) < 0) {
if (parport_set_data( cable->link.port, 1 << TRST ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
} else
PARAM_TRST(cable) = (data >> TRST) & 1;
PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0;
return 0;
}
@ -71,33 +71,57 @@ static void
arcom_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
for (i = 0; i < n; i++) {
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
arcom_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) );
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
arcom_set_trst( cable_t *cable, int trst )
arcom_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (prev_sigs & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
data |= (sigs & CS_TRST) ? (1 << TRST) : 0;
parport_set_data( cable->link.port, data );
PARAM_SIGNALS(cable) = sigs;
}
parport_set_data( cable->link.port, PARAM_TRST(cable) << TRST );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t arcom_cable_driver = {
@ -112,8 +136,8 @@ cable_driver_t arcom_cable_driver = {
arcom_clock,
arcom_get_tdo,
generic_transfer,
arcom_set_trst,
generic_get_trst,
arcom_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -75,8 +75,8 @@ byteblaster_init( cable_t *cable )
if (parport_open( cable->link.port ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
/* check if a ByteBlaster or ByteBlasterMV is connected */
parport_set_data( cable->link.port, 1 << BB_CHECK);
if ( !( ( parport_get_status( cable->link.port ) >> BB_PRESENT ) & 1 ) )
@ -110,20 +110,43 @@ byteblaster_clock( cable_t *cable, int tms, int tdi, int n )
parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
byteblaster_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, 0 << TCK );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
byteblaster_set_trst( cable_t *cable, int trst )
byteblaster_set_signal( cable_t *cable, int mask, int val )
{
return 1;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (prev_sigs & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
parport_set_data( cable->link.port, data );
PARAM_SIGNALS(cable) = sigs;
}
return prev_sigs;
}
cable_driver_t byteblaster_cable_driver = {
@ -138,8 +161,8 @@ cable_driver_t byteblaster_cable_driver = {
byteblaster_clock,
byteblaster_get_tdo,
generic_transfer,
byteblaster_set_trst,
generic_get_trst,
byteblaster_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -62,7 +62,7 @@ dlc5_init( cable_t *cable )
if (parport_open( cable->link.port ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
return 0;
}
@ -81,20 +81,43 @@ dlc5_clock( cable_t *cable, int tms, int tdi, int n )
parport_set_data( cable->link.port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
dlc5_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (1 << PROG) | (0 << TCK) );
parport_set_data( cable->link.port, (1 << PROG) | ( 0 << TCK ) );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
dlc5_set_trst( cable_t *cable, int trst )
dlc5_set_signal( cable_t *cable, int mask, int val )
{
return 1;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (prev_sigs & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
parport_set_data( cable->link.port, ( 1 << PROG ) | data );
PARAM_SIGNALS(cable) = sigs;
}
return prev_sigs;
}
cable_driver_t dlc5_cable_driver = {
@ -109,8 +132,8 @@ cable_driver_t dlc5_cable_driver = {
dlc5_clock,
dlc5_get_tdo,
generic_transfer,
dlc5_set_trst,
generic_get_trst,
dlc5_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -60,9 +60,9 @@ ea253_init( cable_t *cable )
if ((data = parport_get_data( cable->link.port )) < 0) {
if (parport_set_data( cable->link.port, 1 << TRST ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
} else
PARAM_TRST(cable) = (data >> TRST) & 1;
PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0;
return 0;
}
@ -71,33 +71,57 @@ static void
ea253_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
for (i = 0; i < n; i++) {
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
ea253_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) );
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
ea253_set_trst( cable_t *cable, int trst )
ea253_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (prev_sigs & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
data |= (sigs & CS_TRST) ? (1 << TRST) : 0;
parport_set_data( cable->link.port, data );
PARAM_SIGNALS(cable) = sigs;
}
parport_set_data( cable->link.port, PARAM_TRST(cable) << TRST );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t ea253_cable_driver = {
@ -112,8 +136,8 @@ cable_driver_t ea253_cable_driver = {
ea253_clock,
ea253_get_tdo,
generic_transfer,
ea253_set_trst,
generic_get_trst,
ea253_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -62,9 +62,9 @@ ei012_init( cable_t *cable )
if ((data = parport_get_data( cable->link.port )) < 0) {
if (parport_set_data( cable->link.port, 1 << TRST ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
} else
PARAM_TRST(cable) = (data >> TRST) & 1;
PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0;
return 0;
}
@ -73,33 +73,57 @@ static void
ei012_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
for (i = 0; i < n; i++) {
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
ei012_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) );
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
ei012_set_trst( cable_t *cable, int trst )
ei012_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (prev_sigs & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
data |= (sigs & CS_TRST) ? (1 << TRST) : 0;
parport_set_data( cable->link.port, data );
PARAM_SIGNALS(cable) = sigs;
}
parport_set_data( cable->link.port, PARAM_TRST(cable) << TRST );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t ei012_cable_driver = {
@ -114,8 +138,8 @@ cable_driver_t ei012_cable_driver = {
ei012_clock,
ei012_get_tdo,
generic_transfer,
ei012_set_trst,
generic_get_trst,
ei012_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -53,8 +53,8 @@
/* repeat the definitions for MPSSE command processor here
since we cannot rely on the existence of ftdih. even though
they're defined there */
since we cannot rely on the existence of ftdi.h even though
they're defined there */
/* Shifting commands IN MPSSE Mode*/
#define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/
@ -109,7 +109,7 @@
#define BIT_ARMUSBOCD_RED_LED 3
#define BITMASK_ARMUSBOCD_nOE (1 << BIT_ARMUSBOCD_nOE)
#define BITMASK_ARMUSBOCD_nTRST (1 << BIT_ARMUSBOCD_nTRST)
#define BITMASK_ARMUSBOCD_nTSRST (1 << BIT_ARMUSBOCD_nTRST)
#define BITMASK_ARMUSBOCD_nTSRST (1 << BIT_ARMUSBOCD_nTSRST)
#define BITMASK_ARMUSBOCD_nTRST_nOE (1 << BIT_ARMUSBOCD_nTRST_nOE)
#define BITMASK_ARMUSBOCD_RED_LED (1 << BIT_ARMUSBOCD_RED_LED)
/* bit and bitmask definitions for Blackfin gnICE */
@ -173,18 +173,27 @@ typedef struct {
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;
/* this driver issues several "Set Data Bits High Byte" commands
here is the place where cable specific values can be stored
that are used each time this command is issued */
uint8_t high_byte_value;
uint8_t high_byte_dir;
/* the following variables store the bit position of TRST and RESET (SRST)
for XOR'ing with the default values of low_byte_value and high_byte_value
allowed values:
< 0 : feature not used
< 8 : applies to low byte
< 12 : applies to high byte */
int bit_trst;
int bit_reset;
/* 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;
int signals;
cx_cmd_root_t cmd_root;
} params_t;
@ -253,16 +262,20 @@ ft2232_generic_init( cable_t *cable )
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;
params->high_byte_value = 0;
params->high_byte_value = 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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = -1; /* not used */
params->bit_reset = -1; /* not used */
params->last_tdo_valid = 0;
params->signals = 0;
return 0;
}
@ -293,22 +306,25 @@ ft2232_jtagkey_init( cable_t *cable )
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
params->high_byte_value = 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, params->high_byte_value );
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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = BIT_JTAGKEY_TRST_N_OUT + 8; /* member of HIGH byte */
params->bit_reset = BIT_JTAGKEY_SRST_N_OUT + 8; /* member of HIGH byte */
params->last_tdo_valid = 0;
params->signals = CS_TRST | CS_RESET;
return 0;
}
@ -340,25 +356,27 @@ ft2232_armusbocd_init( cable_t *cable )
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
params->high_byte_value = BITMASK_ARMUSBOCD_nTRST
| BITMASK_ARMUSBOCD_nTSRST
| BITMASK_ARMUSBOCD_RED_LED;
params->high_byte_dir = BITMASK_ARMUSBOCD_nTRST
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, params->high_byte_value );
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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = BIT_ARMUSBOCD_nTRST + 8; /* member of HIGH byte */
params->bit_reset = BIT_ARMUSBOCD_nTSRST + 8; /* member of HIGH byte */
params->last_tdo_valid = 0;
params->signals = CS_TRST | CS_RESET;
return 0;
}
@ -384,19 +402,22 @@ ft2232_gnice_init( cable_t *cable )
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_GNICE_nLED;
params->high_byte_value_trst_inactive = BITMASK_GNICE_nTRST;
params->high_byte_dir = BITMASK_GNICE_nTRST | BITMASK_GNICE_nLED;
params->high_byte_value = BITMASK_GNICE_nTRST;
params->high_byte_dir = BITMASK_GNICE_nTRST | BITMASK_GNICE_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, params->high_byte_value );
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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = BIT_GNICE_nTRST + 8; /* member of HIGH byte */
params->bit_reset = -1; /* not used */
params->last_tdo_valid = 0;
params->signals = CS_TRST;
return 0;
}
@ -427,23 +448,26 @@ ft2232_oocdlinks_init( cable_t *cable )
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
params->high_byte_value = BITMASK_OOCDLINKS_nTRST
| BITMASK_OOCDLINKS_nSRST;
params->high_byte_dir = BITMASK_OOCDLINKS_nTRST
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, params->high_byte_value );
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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = BIT_OOCDLINKS_nTRST + 8; /* member of HIGH byte */
params->bit_reset = BIT_OOCDLINKS_nSRST + 8; /* member of HIGH byte */
params->last_tdo_valid = 0;
params->signals = CS_TRST | CS_RESET;
return 0;
}
@ -474,16 +498,19 @@ ft2232_turtelizer2_init( cable_t *cable )
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;
params->high_byte_value = 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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = -1; /* not used */
params->bit_reset = BIT_TURTELIZER2_RST; /* member of LOW byte */
params->last_tdo_valid = 0;
params->signals = CS_RESET;
return 0;
}
@ -513,18 +540,22 @@ ft2232_usbtojtagif_init( cable_t *cable )
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;
params->high_byte_value = 0;
params->high_byte_value = 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_value );
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->bit_trst = BIT_USBTOJTAGIF_nTRST; /* member of LOW byte */
params->bit_reset = BIT_USBTOJTAGIF_RST; /* member of LOW byte */
params->last_tdo_valid = 0;
params->signals = CS_TRST | CS_RESET;
return 0;
}
@ -539,7 +570,7 @@ ft2232_signalyzer_init( cable_t *cable )
if (usbconn_open( cable->link.usb )) return -1;
/* static low byte value and direction:
nTRST = 1, RST = 1, DBGRQ = 0 */
nTRST = 1, nSRST = 1 */
params->low_byte_value = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST;
params->low_byte_dir = BITMASK_SIGNALYZER_nTRST | BITMASK_SIGNALYZER_nSRST;
@ -551,16 +582,19 @@ ft2232_signalyzer_init( cable_t *cable )
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;
params->high_byte_value = 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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = BIT_SIGNALYZER_nTRST; /* member of LOW byte */
params->bit_reset = BIT_SIGNALYZER_nSRST; /* member of LOW byte */
params->last_tdo_valid = 0;
params->signals = CS_TRST | CS_RESET;
return 0;
}
@ -575,8 +609,8 @@ ft2232_flyswatter_init( cable_t *cable )
if (usbconn_open( cable->link.usb )) return -1;
/* static low byte value and direction:
nTRST = 1, set nOE1 and nOE2 to '0' -> activate output enables */
params->low_byte_value = BITMASK_FLYSWATTER_nTRST;
nTRST = 1, nSRST = 1, set nOE1 and nOE2 to '0' -> activate output enables */
params->low_byte_value = BITMASK_FLYSWATTER_nTRST | BIT_FLYSWATTER_nSRST;
params->low_byte_dir = BITMASK_FLYSWATTER_nOE1 | BITMASK_FLYSWATTER_nOE2 |
BITMASK_FLYSWATTER_nTRST | BITMASK_FLYSWATTER_nSRST;
@ -589,16 +623,19 @@ ft2232_flyswatter_init( cable_t *cable )
/* Set Data Bits High Byte */
/* Turn LED2 on */
params->high_byte_value_trst_active = 0;
params->high_byte_value_trst_inactive = 0;
params->high_byte_dir = BITMASK_FLYSWATTER_nLED2;
params->high_byte_value = 0;
params->high_byte_dir = BITMASK_FLYSWATTER_nLED2;
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_value );
cx_cmd_push( cmd_root, params->high_byte_dir );
ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ );
params->bit_trst = BIT_FLYSWATTER_nTRST; /* member of LOW byte */
params->bit_reset = BIT_FLYSWATTER_nSRST; /* member of LOW byte */
params->last_tdo_valid = 0;
params->signals = CS_TRST | CS_RESET;
return 0;
}
@ -954,6 +991,11 @@ ft2232_clock_schedule( cable_t *cable, int tms, int tdi, int n )
}
cx_cmd_push( cmd_root, tdi | tms );
}
params->signals &= ~(CS_TMS | CS_TDI | CS_TCK);
if (tms) params->signals |= CS_TMS;
if (tdi) params->signals |= CS_TDI;
// if (tck) params->signals |= CS_TCK;
}
@ -1007,27 +1049,84 @@ ft2232_get_tdo( cable_t *cable )
static void
ft2232_set_trst_schedule( params_t *params, int trst )
ft2232_set_signal_schedule( params_t *params, int mask, int val,
int set_low, int set_high )
{
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 );
/* filter for supported signals */
mask &= CS_TCK | CS_TDI | CS_TMS | CS_TRST | CS_RESET;
if (mask != 0)
{
int sigs = (params->signals & ~mask) | (val & mask);
uint8_t low_or = 0;
uint8_t low_xor = 0;
uint8_t high_xor = 0;
/* prepare low and high byte */
if (sigs & CS_TCK) low_or |= BITMASK_TCK;
if (sigs & CS_TDI) low_or |= BITMASK_TDI;
if (sigs & CS_TMS) low_or |= BITMASK_TMS;
/* TRST and RESET (SRST) are XOR'ed to the default value since
the right value depends on the external circuitry (inverter or not) */
if ((sigs & CS_TRST) == 0)
if (params->bit_trst >= 0)
{
if (params->bit_trst < 8)
{
low_xor |= 1 << params->bit_trst;
}
else
{
high_xor |= 1 << (params->bit_trst - 8);
}
}
if ((sigs & CS_RESET) == 0)
if (params->bit_reset >= 0)
{
if (params->bit_reset < 8)
{
low_xor |= 1 << params->bit_reset;
}
else
{
high_xor |= 1 << (params->bit_reset - 8);
}
}
if (set_low)
{
cx_cmd_queue( cmd_root, 0 );
cx_cmd_push( cmd_root, SET_BITS_LOW );
cx_cmd_push( cmd_root, (params->low_byte_value | low_or) ^ low_xor );
cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS );
}
if (set_high)
{
cx_cmd_queue( cmd_root, 0 );
cx_cmd_push( cmd_root, SET_BITS_HIGH );
cx_cmd_push( cmd_root, params->high_byte_value ^ high_xor );
cx_cmd_push( cmd_root, params->high_byte_dir );
}
params->signals = sigs;
}
}
static int
ft2232_set_trst( cable_t *cable, int trst )
ft2232_set_signal( cable_t *cable, int mask, int val )
{
params_t *params = (params_t *)cable->params;
ft2232_set_trst_schedule( params, trst );
int prev_sigs = params->signals;
ft2232_set_signal_schedule( params, mask, val, 1, 1 );
cx_xfer( &(params->cmd_root), &imm_cmd, cable, COMPLETELY );
params->last_tdo_valid = 0;
return trst;
return prev_sigs;
}
@ -1040,13 +1139,9 @@ ft2232_transfer_schedule( cable_t *cable, int len, char *in, char *out )
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 );
/* lower TMS for transfer
also lower TCK to ensure correct clocking */
ft2232_set_signal_schedule( params, CS_TCK | CS_TMS, 0, 1, 0 );
chunkbytes = len >> 3;
while (chunkbytes > 0)
@ -1247,6 +1342,7 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much )
while (cable->todo.num_items > 0)
{
int i, j, n;
int post_signals = params->signals;
int last_tdo_valid_schedule = params->last_tdo_valid;
int last_tdo_valid_finish = params->last_tdo_valid;
@ -1271,8 +1367,10 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much )
}
break;
case CABLE_SET_TRST:
ft2232_set_trst_schedule( params, cable->todo.data[i].arg.value.trst );
case CABLE_SET_SIGNAL:
ft2232_set_signal_schedule( params,
cable->todo.data[i].arg.value.mask,
cable->todo.data[i].arg.value.val, 1, 1 );
last_tdo_valid_schedule = 0;
break;
@ -1300,8 +1398,13 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much )
switch (cable->todo.data[j].action)
{
case CABLE_CLOCK:
params->last_tdo_valid = last_tdo_valid_finish = 0;
break;
{
post_signals &= ~(CS_TCK | CS_TDI | CS_TMS);
post_signals |= (cable->todo.data[j].arg.clock.tms ? CS_TMS : 0);
post_signals |= (cable->todo.data[j].arg.clock.tdi ? CS_TDI : 0);
params->last_tdo_valid = last_tdo_valid_finish = 0;
break;
}
case CABLE_GET_TDO:
{
int tdo;
@ -1313,21 +1416,24 @@ ft2232_flush( cable_t *cable, cable_flush_amount_t how_much )
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;
cable->done.data[m].arg.value.val = tdo;
break;
}
case CABLE_SET_TRST:
case CABLE_SET_SIGNAL:
{
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;
cable->done.data[m].action = CABLE_SET_SIGNAL;
cable->done.data[m].arg.value.mask = cable->todo.data[j].arg.value.mask;
cable->done.data[m].arg.value.val = post_signals;
int mask = cable->todo.data[j].arg.value.mask & ~(CS_TCK | CS_TDI | CS_TMS | CS_TRST | CS_RESET);
post_signals = (post_signals & ~mask) | (cable->todo.data[j].arg.value.val & mask);
}
case CABLE_GET_TRST:
case CABLE_GET_SIGNAL:
{
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;
cable->done.data[m].action = CABLE_GET_SIGNAL;
cable->done.data[m].arg.value.sig = cable->todo.data[j].arg.value.sig;
cable->done.data[m].arg.value.val = (post_signals & cable->todo.data[j].arg.value.sig) ? 1 : 0;
break;
}
case CABLE_TRANSFER:
@ -1480,8 +1586,8 @@ cable_driver_t ft2232_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1512,8 +1618,8 @@ cable_driver_t ft2232_armusbocd_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1558,8 +1664,8 @@ cable_driver_t ft2232_gnice_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1590,8 +1696,8 @@ cable_driver_t ft2232_jtagkey_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1622,8 +1728,8 @@ cable_driver_t ft2232_oocdlinks_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1654,8 +1760,8 @@ cable_driver_t ft2232_turtelizer2_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1686,8 +1792,8 @@ cable_driver_t ft2232_usbtojtagif_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1718,8 +1824,8 @@ cable_driver_t ft2232_signalyzer_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};
@ -1750,8 +1856,8 @@ cable_driver_t ft2232_flyswatter_cable_driver = {
ft2232_clock,
ft2232_get_tdo,
ft2232_transfer,
ft2232_set_trst,
generic_get_trst,
ft2232_set_signal,
generic_get_signal,
ft2232_flush,
ft2232_usbcable_help
};

@ -83,9 +83,9 @@ generic_transfer( cable_t *cable, int len, char *in, char *out )
}
int
generic_get_trst( cable_t *cable )
generic_get_signal( cable_t *cable, pod_sigsel_t sig )
{
return PARAM_TRST(cable);
return (((PARAM_SIGNALS(cable)) & sig) != 0) ? 1:0;
}
int
@ -104,7 +104,7 @@ do_one_queued_action( cable_t *cable )
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_GET_SIGNAL
|| cable->todo.data[i].action == CABLE_TRANSFER )
{
printf(_("No space in cable activity results queue.\n"));
@ -120,9 +120,10 @@ do_one_queued_action( cable_t *cable )
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 );
case CABLE_SET_SIGNAL:
cable_set_signal( cable,
cable->todo.data[i].arg.value.sig,
cable->todo.data[i].arg.value.val );
break;
case CABLE_TRANSFER:
{
@ -151,17 +152,20 @@ do_one_queued_action( cable_t *cable )
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->done.data[j].arg.value.val =
cable->driver->get_tdo( cable );
break;
case CABLE_GET_TRST:
case CABLE_GET_SIGNAL:
j = cable_add_queue_item( cable, &(cable->done) );
#ifdef VERBOSE
printf("add result from get_trst to %p.%d\n", &(cable->done), j);
printf("add result from get_signal 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 );
cable->done.data[j].action = CABLE_GET_SIGNAL;
cable->done.data[j].arg.value.sig =
cable->todo.data[i].arg.value.sig;
cable->done.data[j].arg.value.val =
cable->driver->get_signal( cable,
cable->todo.data[i].arg.value.sig );
break;
};
#ifdef VERBOSE
@ -316,7 +320,7 @@ generic_flush_using_transfer( cable_t *cable, cable_flush_amount_t how_much )
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;
cable->done.data[c].arg.value.val = tdo;
}
else if(cable->todo.data[i].action == CABLE_TRANSFER)
{

@ -29,17 +29,15 @@
#include "parport.h"
typedef struct {
int trst;
int sreset;
int signals;
} generic_params_t;
#define PARAM_TRST(cable) ((generic_params_t *) cable->params)->trst
#define PARAM_SRESET(cable) ((generic_params_t *) cable->params)->sreset
#define PARAM_SIGNALS(cable) ((generic_params_t *) cable->params)->signals
void generic_disconnect( cable_t *cable );
void generic_set_frequency( cable_t *cable, uint32_t new_freq );
int generic_transfer( cable_t *cable, int len, char *in, char *out );
int generic_get_trst( cable_t *cable );
int generic_get_signal( cable_t *cable, pod_sigsel_t sig );
void generic_flush_one_by_one( cable_t *cable, cable_flush_amount_t hm );
void generic_flush_using_transfer( cable_t *cable, cable_flush_amount_t hm );

@ -562,7 +562,7 @@ jlink_transfer( cable_t *cable, int len, char *in, char *out )
/* ---------------------------------------------------------------------- */
static int
jlink_set_trst( cable_t *cable, int trst )
jlink_set_signal( cable_t *cable, int mask, int val )
{
return 1;
}
@ -579,8 +579,8 @@ cable_driver_t jlink_cable_driver = {
jlink_clock,
jlink_get_tdo,
jlink_transfer,
jlink_set_trst,
generic_get_trst,
jlink_set_signal,
generic_get_signal,
generic_flush_using_transfer,
generic_usbconn_help
};

@ -70,7 +70,7 @@ keithkoep_init( cable_t *cable )
return -1;
parport_set_control( cable->link.port, 1 << TRST );
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
return 0;
}
@ -89,23 +89,51 @@ keithkoep_clock( cable_t *cable, int tms, int tdi, int n )
parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
keithkoep_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, 0 << TCK );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
keithkoep_set_trst( cable_t *cable, int trst )
keithkoep_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified
if (mask != 0)
{
int sigs = (prev_sigs & ~mask) | (val & mask);
if ((mask & ~CS_TRST) != 0)
{
int data = 0;
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
parport_set_data( cable->link.port, data );
}
if ((mask & CS_TRST) != 0)
{
parport_set_control( cable->link.port, (sigs & CS_TRST) ? (1 << TRST) : 0 );
}
PARAM_SIGNALS(cable) = sigs;
}
parport_set_control( cable->link.port, PARAM_TRST(cable) << TRST );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t keithkoep_cable_driver = {
@ -120,8 +148,8 @@ cable_driver_t keithkoep_cable_driver = {
keithkoep_clock,
keithkoep_get_tdo,
generic_transfer,
keithkoep_set_trst,
generic_get_trst,
keithkoep_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -54,11 +54,18 @@
static int
lattice_init( cable_t *cable )
{
int data;
if (parport_open( cable->link.port ))
return -1;
PARAM_TRST(cable) = 1;
if ((data = parport_get_data( cable->link.port )) < 0) {
if (parport_set_data( cable->link.port, 1 << TRST ))
return -1;
PARAM_SIGNALS(cable) = CS_TRST;
} else
PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0;
return 0;
}
@ -66,30 +73,57 @@ static void
lattice_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
for (i = 0; i < n; i++) {
parport_set_data( cable->link.port, (0 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) );
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) | (1 << TRST) );
parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
lattice_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (0 << TCK) | (1 << TRST) );
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
lattice_set_trst( cable_t *cable, int trst )
lattice_set_signal( cable_t *cable, int mask, int val )
{
return parport_set_data( cable->link.port, trst << TRST );
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (PARAM_SIGNALS(cable) & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
data |= (sigs & CS_TRST) ? (1 << TRST) : 0;
parport_set_data( cable->link.port, data );
PARAM_SIGNALS(cable) = sigs;
}
return prev_sigs;
}
cable_driver_t lattice_cable_driver = {
@ -104,8 +138,8 @@ cable_driver_t lattice_cable_driver = {
lattice_clock,
lattice_get_tdo,
generic_transfer,
lattice_set_trst,
generic_get_trst,
lattice_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -67,8 +67,8 @@ mpcbdm_init( cable_t *cable )
if (parport_open( cable->link.port ))
return -1;
parport_set_control( cable->link.port, 0 << TRST );
PARAM_TRST(cable) = 1;
parport_set_control( cable->link.port, 0 );
PARAM_SIGNALS(cable) = ( CS_TRST | CS_RESET );
return 0;
}
@ -87,23 +87,54 @@ mpcbdm_clock( cable_t *cable, int tms, int tdi, int n )
parport_set_data( cable->link.port, (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= (CS_TRST | CS_RESET);
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
mpcbdm_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, 0 << TCK );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
mpcbdm_set_trst( cable_t *cable, int trst )
mpcbdm_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST | CS_RESET); // only these can be modified
if (mask)
{
int sigs = (PARAM_SIGNALS(cable) & ~mask) | (val & mask);
if ((mask & ~(CS_TRST | CS_RESET)) != 0)
{
int data = 0;
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
parport_set_data( cable->link.port, data );
}
if ((mask & (CS_TRST | CS_RESET)) != 0)
{
int data = 0;
data |= (sigs & CS_TRST) ? 0 : (1 << TRST);
// data |= (sigs & CS_RESET) ? 0 : (1 << SRESET); // use SRESET or HRESET? which polarity?
parport_set_control( cable->link.port, data );
}
PARAM_SIGNALS(cable) = sigs;
}
parport_set_control( cable->link.port, (PARAM_TRST(cable) ^ 1) << TRST );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t mpcbdm_cable_driver = {
@ -118,8 +149,8 @@ cable_driver_t mpcbdm_cable_driver = {
mpcbdm_clock,
mpcbdm_get_tdo,
generic_transfer,
mpcbdm_set_trst,
generic_get_trst,
mpcbdm_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -72,8 +72,8 @@ triton_init( cable_t *cable )
if (parport_open( cable->link.port ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SRESET(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST | CS_RESET;
parport_set_data( cable->link.port, (1 << TRST) | (1 << SRESET) );
return 0;
}
@ -82,33 +82,60 @@ static void
triton_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
int sreset = (PARAM_SIGNALS(cable) & CS_RESET) ? 1 : 0;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
for (i = 0; i < n; i++) {
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (sreset << SRESET) | (0 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
parport_set_data( cable->link.port, (trst << TRST) | (sreset << SRESET) | (1 << TCK) | (tms << TMS) | (tdi << TDI) );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= (CS_TRST | CS_RESET);
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
triton_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) | (0 << TCK) );
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
int sreset = (PARAM_SIGNALS(cable) & CS_RESET) ? 1 : 0;
parport_set_data( cable->link.port, (trst << TRST) | (sreset << SRESET) | (0 << TCK) );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
triton_set_trst( cable_t *cable, int trst )
triton_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST | CS_RESET); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (PARAM_SIGNALS(cable) & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
data |= (sigs & CS_TRST) ? (1 << TRST) : 0;
data |= (sigs & CS_RESET) ? (1 << SRESET) : 0;
parport_set_data( cable->link.port, data );
PARAM_SIGNALS(cable) = sigs;
}
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (PARAM_SRESET(cable) << SRESET) );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t triton_cable_driver = {
@ -123,8 +150,8 @@ cable_driver_t triton_cable_driver = {
triton_clock,
triton_get_tdo,
generic_transfer,
triton_set_trst,
generic_get_trst,
triton_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -71,7 +71,7 @@ typedef struct {
void *map_base;
size_t map_size;
uint32_t *gpio_base;
int trst;
int signals;
uint32_t lastout;
} ts7800_params_t;
@ -126,6 +126,7 @@ ts7800_gpio_close( cable_t *cable )
static int
ts7800_gpio_write( cable_t *cable, uint8_t data )
{
int sigs;
ts7800_params_t *p = cable->params;
p->gpio_base[GPIO_OUT] = p->lastout = (p->lastout & GPIO_BITMASK) | data;
@ -190,7 +191,7 @@ ts7800_init( cable_t *cable )
if (ts7800_gpio_open( cable ))
return -1;
p->trst = 1;
p->signals = CS_TRST;
return 0;
}
@ -225,24 +226,52 @@ ts7800_clock( cable_t *cable, int tms, int tdi, int n )
static int
ts7800_get_tdo( cable_t *cable )
{
ts7800_gpio_write( cable, ((ts7800_params_t *)cable->params)->lastout & ~(0 << TCK) );
ts7800_params_t *p = cable->params;
ts7800_gpio_write( cable, p->lastout & ~(0 << TCK) );
return (ts7800_gpio_read( cable ) >> TDO) & 1;
}
static int
ts7800_set_trst( cable_t *cable, int trst )
ts7800_current_signals( cable_t *cable )
{
ts7800_params_t *p = cable->params;
int sigs = p->signals & ~(CS_TMS | CS_TDI | CS_TCK);
if (p->lastout & (1 << TCK)) sigs |= CS_TCK;
if (p->lastout & (1 << TDI)) sigs |= CS_TDI;
if (p->lastout & (1 << TMS)) sigs |= CS_TMS;
return sigs;
}
static int
ts7800_set_signal( cable_t *cable, int mask, int val )
{
ts7800_params_t *p = cable->params;
p->trst = trst ? 1 : 0;
int prev_sigs = current_signals( cable );
return p->trst;
mask &= (CS_TDI | CS_TCK | CS_TMS); // only these can be modified
if (mask != 0)
{
sigs = (prev_sigs & ~mask) | (val & mask);
tms = (sigs & CS_TMS) ? (1 << TMS) : 0;
tdi = (sigs & CS_TDI) ? (1 << TDI) : 0;
tck = (sigs & CS_TCK) ? (1 << TCK) : 0;
ts7800_gpio_write( cable, tms | tdi | tck );
}
return prev_sigs;
}
static int
ts7800_get_trst( cable_t *cable )
ts7800_get_signal( cable_t *cable, pod_sigsel_t sig )
{
return ((ts7800_params_t *)cable->params)->trst;
ts7800_params_t *p = cable->params;
return (current_signals( cable ) & sig) ? 1 : 0;
}
static void
@ -266,8 +295,8 @@ cable_driver_t ts7800_cable_driver = {
ts7800_clock,
ts7800_get_tdo,
generic_transfer,
ts7800_set_trst,
ts7800_get_trst,
ts7800_set_signal,
ts7800_get_signal,
generic_flush_one_by_one,
ts7800_help
};

@ -230,7 +230,7 @@ usbblaster_get_tdo( cable_t *cable )
}
static int
usbblaster_set_trst( cable_t *cable, int trst )
usbblaster_set_signal( cable_t *cable, int mask, int val )
{
return 1;
}
@ -404,16 +404,20 @@ usbblaster_flush( cable_t *cable, cable_flush_amount_t how_much )
int m;
m = cable_add_queue_item( cable, &(cable->done) );
cable->done.data[m].action = CABLE_GET_TDO;
cable->done.data[m].arg.value.tdo = usbblaster_get_tdo_finish( cable );
cable->done.data[m].arg.value.val = usbblaster_get_tdo_finish( cable );
break;
}
case CABLE_GET_TRST:
case CABLE_GET_SIGNAL:
{
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;
cable->done.data[m].action = CABLE_GET_SIGNAL;
cable->done.data[m].arg.value.sig = cable->todo.data[j].arg.value.sig;
if (cable->todo.data[j].arg.value.sig == CS_TRST)
cable->done.data[m].arg.value.val = 1;
else
cable->done.data[m].arg.value.val = -1; // not supported yet
break;
}
}
case CABLE_TRANSFER:
{
int r = usbblaster_transfer_finish( cable,
@ -475,8 +479,8 @@ cable_driver_t usbblaster_cable_driver = {
usbblaster_clock,
usbblaster_get_tdo,
usbblaster_transfer,
usbblaster_set_trst,
generic_get_trst,
usbblaster_set_signal,
generic_get_signal,
// generic_flush_one_by_one,
// generic_flush_using_transfer,
usbblaster_flush,

@ -73,7 +73,8 @@ typedef struct {
void *map_base;
size_t map_size;
uint32_t *gpio_PHDR;
int trst;
uint32_t lastout;
int signals;
} ep9307_params_t;
static int
@ -167,6 +168,7 @@ ep9307_gpio_write( cable_t *cable, uint8_t data )
tmp &= ~GPIO_OUTPUT_MASK;
tmp |= data;
*((uint32_t*)p->gpio_PHDR) = tmp;
p->lastout = tmp;
return 0;
}
@ -224,7 +226,7 @@ ep9307_init( cable_t *cable )
ep9307_gpio_write( cable, 1 << TRST );
cable_wait( cable );
p->trst = 1;
p->signals = CS_TRST;
return 0;
}
@ -265,28 +267,50 @@ ep9307_get_tdo( cable_t *cable )
ep9307_gpio_write( cable, (0 << TCK) | (p->trst << TRST) );
cable_wait( cable );
return (ep9307_gpio_read( cable ) >> TDO) & 1;
}
/**
* NOTE: This also lowers the TCK, TDI, and TMS lines; is this intended?
*/
static int
ep9307_set_trst( cable_t *cable, int trst )
ep9307_current_signals( cable_t *cable )
{
ep9307_params_t *p = cable->params;
p->trst = trst ? 1 : 0;
int sigs = p->signals & ~(CS_TMS | CS_TDI | CS_TCK | CS_TRST);
if (p->lastout & (1 << TCK)) sigs |= CS_TCK;
if (p->lastout & (1 << TDI)) sigs |= CS_TDI;
if (p->lastout & (1 << TMS)) sigs |= CS_TMS;
if (p->lastout & (1 << TRST)) sigs |= CS_TRST;
ep9307_gpio_write( cable, p->trst << TRST );
cable_wait( cable );
return p->trst;
return sigs;
}
static int
ep9307_set_signal( cable_t *cable, int mask, int val )
{
ep9307_params_t *p = cable->params;
int prev_sigs = ep9307_current_signals (cable);
int mask &= (CS_TMS | CS_TDI | CS_TCK | CS_TRST); // only these can be modified
if (mask != 0)
{
int sigs = (prev_sigs & ~mask) | (val & mask);
int tms = (sigs & CS_TMS) ? (1 << TMS) : 0;
int tdi = (sigs & CS_TDI) ? (1 << TDI) : 0;
int tck = (sigs & CS_TCK) ? (1 << TCK) : 0;
int trst = (sigs & CS_TRST) ? (1 << TRST) : 0;
ep9307_gpio_write( cable, tms | tdi | tck | trst );
}
return prev_sigs;
}
static int
ep9307_get_trst( cable_t *cable )
ep9307_get_signal( cable_t *cable, pod_sigsel_t sig )
{
return (ep9307_gpio_read( cable ) >> TRST) & 1;
return (ep9307_current_signals( cable ) & sig) ? 1 : 0;
}
static void

@ -78,6 +78,7 @@ char *std_wgl_map = xstr(TDO) ","
/* private parameters of this cable driver */
typedef struct {
int signals;
int trst_lvl;
int srst_act, srst_inact;
int tms_act, tms_inact;
@ -90,6 +91,7 @@ typedef struct {
/* access macros for the parameters */
#define PRM_SIGNALS(cable) ((wiggler_params_t *) cable->params)->signals
#define PRM_TRST_LVL(cable) ((wiggler_params_t *) cable->params)->trst_lvl
#define PRM_SRST_ACT(cable) ((wiggler_params_t *) cable->params)->srst_act
#define PRM_SRST_INACT(cable) ((wiggler_params_t *) cable->params)->srst_inact
@ -245,6 +247,8 @@ wiggler_init( cable_t *cable )
} else
PRM_TRST_LVL(cable) = data & (PRM_TRST_ACT(cable) | PRM_TRST_INACT(cable));
PRM_SIGNALS (cable) = (PRM_TRST_LVL(cable) == PRM_TRST_ACT(cable)) ? CS_TRST : 0;
return 0;
}
@ -270,6 +274,10 @@ wiggler_clock( cable_t *cable, int tms, int tdi, int n )
PRM_UNUSED_BITS(cable) );
cable_wait( cable );
}
PRM_SIGNALS (cable) &= ~(CS_TDI | CS_TMS);
if (tms) PRM_SIGNALS(cable) |= CS_TMS;
if (tdi) PRM_SIGNALS(cable) |= CS_TDI;
}
static int
@ -279,24 +287,37 @@ wiggler_get_tdo( cable_t *cable )
PRM_TCK_INACT(cable) |
PRM_UNUSED_BITS(cable) );
cable_wait( cable );
return (parport_get_status( cable->link.port ) & (PRM_TDO_ACT(cable) | PRM_TDO_INACT(cable))) ^
PRM_TDO_ACT(cable) ? 0 : 1;
PRM_TDO_ACT(cable) ? 0 : 1;
}
static int
wiggler_set_trst( cable_t *cable, int trst )
wiggler_set_signal( cable_t *cable, int mask, int val )
{
PRM_TRST_LVL(cable) = trst ? PRM_TRST_ACT(cable) : PRM_TRST_INACT(cable);
int prev_sigs = PRM_SIGNALS(cable);
mask &= (CS_TMS | CS_TDI | CS_TCK | CS_TRST); // Only these can be modified
if (mask != 0)
{
int sigs = (prev_sigs & ~mask) | (val & mask);
PRM_TRST_LVL(cable) = ((sigs & CS_TRST) ? PRM_TRST_ACT(cable) : PRM_TRST_INACT(cable));
int data = PRM_UNUSED_BITS(cable) | PRM_TRST_LVL(cable);
data |= ((sigs & CS_TCK) ? PRM_TCK_ACT(cable) : PRM_TCK_INACT(cable));
data |= ((sigs & CS_TMS) ? PRM_TMS_ACT(cable) : PRM_TMS_INACT(cable));
data |= ((sigs & CS_TDI) ? PRM_TDI_ACT(cable) : PRM_TDI_INACT(cable));
parport_set_data( cable->link.port, data );
PRM_SIGNALS(cable) = sigs;
}
parport_set_data( cable->link.port, PRM_TRST_LVL(cable) |
PRM_UNUSED_BITS(cable) );
return PRM_TRST_LVL(cable) ^ PRM_TRST_ACT(cable) ? 0 : 1;
return prev_sigs;
}
static int
wiggler_get_trst( cable_t *cable )
wiggler_get_signal( cable_t *cable, pod_sigsel_t sig )
{
return PRM_TRST_LVL(cable) ^ PRM_TRST_ACT(cable) ? 0 : 1;
return (PRM_SIGNALS(cable) & sig) ? 1 : 0;
}
static void
@ -345,8 +366,8 @@ cable_driver_t wiggler_cable_driver = {
wiggler_clock,
wiggler_get_tdo,
generic_transfer,
wiggler_set_trst,
wiggler_get_trst,
wiggler_set_signal,
wiggler_get_signal,
generic_flush_one_by_one,
wiggler_help
};
@ -363,8 +384,8 @@ cable_driver_t igloo_cable_driver = {
wiggler_clock,
wiggler_get_tdo,
generic_transfer,
wiggler_set_trst,
wiggler_get_trst,
wiggler_set_signal,
wiggler_get_signal,
generic_flush_one_by_one,
wiggler_help
};

@ -73,12 +73,15 @@ wiggler2_init( cable_t *cable )
if (parport_open( cable->link.port ))
return -1;
// TODO: CPU_RESET bit is set to zero here and can't be changed afterwards
// If CPU_RESET=0 doesn't harm, it means it is an active high signal? - kawk
if ((data = parport_get_data( cable->link.port )) < 0) {
if (parport_set_data( cable->link.port, (0 << TRST) | UNUSED_BITS ))
if (parport_set_data( cable->link.port, (1 << TRST) | UNUSED_BITS ))
return -1;
PARAM_TRST(cable) = 1;
PARAM_SIGNALS(cable) = CS_TRST;
} else
PARAM_TRST(cable) = (data >> TRST) & 1;
PARAM_SIGNALS(cable) = ((data >> TRST) && 1) ? CS_TRST : 0;
return 0;
}
@ -87,33 +90,57 @@ static void
wiggler2_clock( cable_t *cable, int tms, int tdi, int n )
{
int i;
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
tms = tms ? 1 : 0;
tdi = tdi ? 1 : 0;
for (i = 0; i < n; i++) {
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS );
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS );
cable_wait( cable );
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS );
parport_set_data( cable->link.port, (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) | UNUSED_BITS );
cable_wait( cable );
}
PARAM_SIGNALS(cable) &= CS_TRST;
PARAM_SIGNALS(cable) |= CS_TCK;
PARAM_SIGNALS(cable) |= tms ? CS_TMS : 0;
PARAM_SIGNALS(cable) |= tdi ? CS_TDI : 0;
}
static int
wiggler2_get_tdo( cable_t *cable )
{
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | UNUSED_BITS );
int trst = (PARAM_SIGNALS(cable) & CS_TRST) ? 1 : 0;
parport_set_data( cable->link.port, (trst << TRST) | (0 << TCK) | UNUSED_BITS );
PARAM_SIGNALS(cable) &= ~(CS_TDI | CS_TCK | CS_TMS);
cable_wait( cable );
return (parport_get_status( cable->link.port ) >> TDO) & 1;
}
static int
wiggler2_set_trst( cable_t *cable, int trst )
wiggler2_set_signal( cable_t *cable, int mask, int val )
{
PARAM_TRST(cable) = trst ? 1 : 0;
int prev_sigs = PARAM_SIGNALS(cable);
mask &= (CS_TDI | CS_TCK | CS_TMS | CS_TRST); // only these can be modified
if (mask != 0)
{
int data = 0;
int sigs = (prev_sigs & ~mask) | (val & mask);
data |= (sigs & CS_TDI) ? (1 << TDI) : 0;
data |= (sigs & CS_TCK) ? (1 << TCK) : 0;
data |= (sigs & CS_TMS) ? (1 << TMS) : 0;
data |= (sigs & CS_TRST) ? (1 << TRST) : 0;
parport_set_data( cable->link.port, data | UNUSED_BITS );
PARAM_SIGNALS(cable) = sigs;
}
parport_set_data( cable->link.port, (PARAM_TRST(cable) << TRST) | UNUSED_BITS );
return PARAM_TRST(cable);
return prev_sigs;
}
cable_driver_t wiggler2_cable_driver = {
@ -128,8 +155,8 @@ cable_driver_t wiggler2_cable_driver = {
wiggler2_clock,
wiggler2_get_tdo,
generic_transfer,
wiggler2_set_trst,
generic_get_trst,
wiggler2_set_signal,
generic_get_signal,
generic_flush_one_by_one,
generic_parport_help
};

@ -437,7 +437,7 @@ xpc_get_tdo( cable_t *cable )
/* ---------------------------------------------------------------------- */
static int
xpc_set_trst( cable_t *cable, int trst )
xpc_set_signal( cable_t *cable, int mask, int val )
{
return 1;
}
@ -641,8 +641,8 @@ cable_driver_t xpc_int_cable_driver = {
xpc_clock,
xpc_get_tdo,
generic_transfer,
xpc_set_trst,
generic_get_trst,
xpc_set_signal,
generic_get_signal,
generic_flush_using_transfer,
generic_usbconn_help
};
@ -667,8 +667,8 @@ cable_driver_t xpc_ext_cable_driver = {
xpc_ext_clock,
xpc_ext_get_tdo,
xpc_ext_transfer,
xpc_set_trst,
generic_get_trst,
xpc_set_signal,
generic_get_signal,
generic_flush_using_transfer,
generic_usbconn_help
};

@ -105,8 +105,8 @@ chain_defer_clock( chain_t *chain, int tms, int tdi, int n )
int
chain_set_trst( chain_t *chain, int trst )
{
int old_trst = cable_get_trst( chain->cable );
trst = cable_set_trst( chain->cable, trst );
int old_trst = cable_set_signal( chain->cable, CS_TRST, trst ? CS_TRST : 0 );
old_trst = (old_trst & CS_TRST) ? 1 : 0;
tap_state_set_trst( chain, old_trst, trst );
return trst;
}
@ -114,7 +114,23 @@ chain_set_trst( chain_t *chain, int trst )
int
chain_get_trst( chain_t *chain )
{
return cable_get_trst( chain->cable );
return (cable_get_signal( chain->cable, CS_TRST ));
}
int
chain_set_pod_signal( chain_t *chain, int mask, int val )
{
int old_val = cable_set_signal( chain->cable, mask, val );
int old_trst = (old_trst & CS_TRST) ? 1 : 0;
int new_trst = (val & mask & CS_TRST) ? 1 : 0;
tap_state_set_trst( chain, old_trst, new_trst );
return old_val;
}
int
chain_get_pod_signal( chain_t *chain, pod_sigsel_t sig )
{
return (cable_get_signal( chain->cable, sig ));
}
void

Loading…
Cancel
Save