diff --git a/jtag/ChangeLog b/jtag/ChangeLog index 7f4927a7..d4be28c5 100644 --- a/jtag/ChangeLog +++ b/jtag/ChangeLog @@ -1,3 +1,27 @@ +2003-03-18 Marcel Telka + + * include/parport.h: New file. Added parport driver support. + All cable drivers modified. + * src/tap/parport.c: Ditto. + * src/tap/parport/direct.c: Ditto. + * src/jtag.c (jtag_parse_line) : Added parport driver support. + * include/Makefile.am (noinst_HEADERS): Added parport.h. + * src/tap/cable/generic.c: New file withgGeneric functions for cable drivers. + All cable drivers modified. + * src/tap/cable/generic.h: Ditto. + * src/tap/Makefile.am (libtap_a_SOURCES): Added parport.c, parport/direct.c, cable/generic.h, + and cable/generic.c. + + * include/cable.h: Added dynamic cable objects. Added cable interpose functions. + All callers changed. + * src/tap/cable.c: Ditto. + + * include/chain.h (chain_connect): Function removed. + (chain_disconnect): New function. + * src/tap/chain.c (chain_free): Modified for chain_disconnect() call. + (chain_connect): Removed. + (chain_disconnect): New function. + 2003-03-17 Marcel Telka * src/Makefile.am (bin_PROGRAMS, bsdl2jtag_SOURCES): Added new bsdl2jtag conversion diff --git a/jtag/include/Makefile.am b/jtag/include/Makefile.am index a2debf77..9861f234 100644 --- a/jtag/include/Makefile.am +++ b/jtag/include/Makefile.am @@ -29,6 +29,7 @@ noinst_HEADERS = \ data_register.h \ gettext.h \ instruction.h \ + parport.h \ part.h \ register.h \ signal.h \ diff --git a/jtag/include/cable.h b/jtag/include/cable.h index 79c4e380..07edb91e 100644 --- a/jtag/include/cable.h +++ b/jtag/include/cable.h @@ -28,18 +28,41 @@ #include -#define cable_t cable_driver_t +typedef struct cable_t cable_t; -typedef struct { +#include "parport.h" +#include "chain.h" + +typedef struct cable_driver_t cable_driver_t; + +struct cable_driver_t { const char *name; const char *description; - int (*init)( unsigned int ); - void (*done)( void ); - void (*clock)( int, int ); - int (*get_tdo)( void ); - int (*set_trst)( int ); - int (*get_trst)( void ); -} cable_driver_t; + cable_t *(*connect)( cable_driver_t *, parport_t * ); + void (*disconnect)( cable_t *cable ); + void (*cable_free)( cable_t *cable ); + int (*init)( cable_t * ); + void (*done)( cable_t * ); + void (*clock)( cable_t *, int, int ); + int (*get_tdo)( cable_t * ); + int (*set_trst)( cable_t *, int ); + int (*get_trst)( cable_t * ); +}; + +struct cable_t { + cable_driver_t *driver; + parport_t *port; + void *params; + chain_t *chain; +}; + +void cable_free( cable_t *cable ); +int cable_init( cable_t *cable ); +void cable_done( cable_t *cable ); +void cable_clock( cable_t *cable, int tms, int tdi ); +int cable_get_tdo( cable_t *cable ); +int cable_set_trst( cable_t *cable, int trst ); +int cable_get_trst( cable_t *cable ); extern uint32_t frequency; void cable_wait( void ); diff --git a/jtag/include/chain.h b/jtag/include/chain.h index 7aa9cf4d..74fe413d 100644 --- a/jtag/include/chain.h +++ b/jtag/include/chain.h @@ -25,18 +25,21 @@ #ifndef CHAIN_H #define CHAIN_H -#include "cable.h" #include "part.h" -typedef struct { +typedef struct chain_t chain_t; + +#include "cable.h" + +struct chain_t { int state; parts_t *parts; cable_t *cable; -} chain_t; +}; chain_t *chain_alloc( void ); void chain_free( chain_t *chain ); -int chain_connect( chain_t *chain, cable_t *cable, unsigned int port ); +void chain_disconnect( chain_t *chain ); void chain_clock( chain_t *chain, int tms, int tdi ); int chain_set_trst( chain_t *chain, int trst ); int chain_get_trst( chain_t *chain ); diff --git a/jtag/include/parport.h b/jtag/include/parport.h new file mode 100644 index 00000000..2f61814f --- /dev/null +++ b/jtag/include/parport.h @@ -0,0 +1,62 @@ +/* + * $Id$ + * + * Parallel Port Connection Driver Interface + * Copyright (C) 2003 ETC s.r.o. + * + * 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 Marcel Telka , 2003. + * + */ + +#ifndef PARPORT_H +#define PARPORT_H + +#include + +typedef struct parport_t parport_t; + +#include "cable.h" + +typedef struct { + const char *type; + cable_t *(*connect)( const char **, int ); + void (*parport_free)( parport_t * ); + int (*open)( parport_t * ); + int (*close)( parport_t * ); + int (*set_data)( parport_t *, uint8_t ); + int (*get_data)( parport_t * ); + int (*get_status)( parport_t * ); + int (*set_control)( parport_t *, uint8_t ); +} parport_driver_t; + +struct parport_t { + parport_driver_t *driver; + void *params; + cable_t *cable; +}; + +int parport_open( parport_t *port ); +int parport_close( parport_t *port ); +int parport_set_data( parport_t *port, uint8_t data ); +int parport_get_data( parport_t *port ); +int parport_get_status( parport_t *port ); +int parport_set_control( parport_t *port, uint8_t data ); + +extern parport_driver_t *parport_drivers[]; + +#endif /* PARPORT_H */ diff --git a/jtag/src/jtag.c b/jtag/src/jtag.c index ea0ba365..466bb78d 100644 --- a/jtag/src/jtag.c +++ b/jtag/src/jtag.c @@ -41,6 +41,7 @@ #include "part.h" #include "tap.h" +#include "parport.h" #include "bus.h" @@ -193,60 +194,43 @@ jtag_parse_line( char *line ) if (strcmp( t, "cable" ) == 0) { int i; - unsigned int port; + const char *params[10]; + int numpar; t = get_token( NULL ); if (!t) { printf( _("Missing argument(s)\n") ); return 1; } - if (strcmp( t, "parallel" ) != 0) { - printf( _("syntax error!\n") ); - return 1; - } - - t = get_token( NULL ); - if (!t) { - printf( _("Missing argument(s)\n") ); - return 1; - } - if ((sscanf( t, "0x%x", &port ) != 1) && (sscanf( t, "%d", &port ) != 1)) { - printf( _("syntax error\n") ); + for (i = 0; parport_drivers[i]; i++) + if (strcmp( t, parport_drivers[i]->type ) == 0) + break; + if (!parport_drivers[i]) { + printf( _("Unknown connection type: %s\n"), t ); return 1; } - t = get_token( NULL ); - if (!t) { - printf( _("Missing argument(s)\n") ); - return 1; + for (numpar = 0; numpar < 10; numpar++) { + params[numpar] = get_token( NULL ); + if (!params[numpar]) + break; } - if (get_token( NULL )) { printf( _("syntax error!\n") ); return 1; } - if (strcmp( t, "none" ) == 0) { - chain_connect( chain, NULL, 0 ); - printf( _("Cable disconnected\n") ); - return 1; - } - - for (i = 0; cable_drivers[i]; i++) - if (strcmp( t, cable_drivers[i]->name ) == 0) - break; - - if (!cable_drivers[i]) { - printf( _("Unknown cable: %s\n"), t ); + chain->cable = parport_drivers[i]->connect( params, numpar ); + if (!chain->cable) { + printf( _("Error: Cable connection failed!\n") ); return 1; } - printf( _("Initializing %s on parallel port at 0x%x\n"), cable_drivers[i]->description, port ); - if (chain_connect( chain, cable_drivers[i], port )) { - printf( _("Error: Cable driver initialization failed!\n") ); + if (cable_init( chain->cable )) { + printf( _("Error: Cable initialization failed!\n") ); + chain_disconnect( chain ); return 1; } - chain_set_trst( chain, 0 ); chain_set_trst( chain, 1 ); tap_reset( chain ); diff --git a/jtag/src/tap/Makefile.am b/jtag/src/tap/Makefile.am index 83c5aeb5..140e9679 100644 --- a/jtag/src/tap/Makefile.am +++ b/jtag/src/tap/Makefile.am @@ -28,7 +28,11 @@ libtap_a_SOURCES = \ register.c \ state.c \ chain.c \ + parport.c \ + parport/direct.c \ cable.c \ + cable/generic.h \ + cable/generic.c \ cable/arcom.c \ cable/byteblaster.c \ cable/dlc5.c \ diff --git a/jtag/src/tap/cable.c b/jtag/src/tap/cable.c index 35ace283..993a5114 100644 --- a/jtag/src/tap/cable.c +++ b/jtag/src/tap/cable.c @@ -54,6 +54,48 @@ cable_driver_t *cable_drivers[] = { NULL /* last must be NULL */ }; +void +cable_free( cable_t *cable ) +{ + cable->driver->cable_free( cable ); +} + +int +cable_init( cable_t *cable ) +{ + return cable->driver->init( cable ); +} + +void +cable_done( cable_t *cable ) +{ + return cable->driver->done( cable ); +} + +void +cable_clock( cable_t *cable, int tms, int tdi ) +{ + cable->driver->clock( cable, tms, tdi ); +} + +int +cable_get_tdo( cable_t *cable ) +{ + return cable->driver->get_tdo( cable ); +} + +int +cable_set_trst( cable_t *cable, int trst ) +{ + return cable->driver->set_trst( cable, trst ); +} + +int +cable_get_trst( cable_t *cable ) +{ + return cable->driver->get_trst( cable ); +} + void cable_wait( void ) { diff --git a/jtag/src/tap/cable/arcom.c b/jtag/src/tap/cable/arcom.c index 7f57920d..9dac899d 100644 --- a/jtag/src/tap/cable/arcom.c +++ b/jtag/src/tap/cable/arcom.c @@ -23,9 +23,11 @@ * */ -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* * data D[7:0] (pins 9:2) @@ -42,73 +44,65 @@ * 4 - SEL (pin 13) * 3 - ERROR (pin 15) */ -#define TDO 7 - -static int trst; -static unsigned int port; +#define TDO 7 static int -arcom_init( unsigned int aport ) +arcom_init( cable_t *cable ) { - port = aport; - if (((port + 2 <= 0x400) && ioperm( port, 2, 1 )) || ((port + 2 > 0x400) && iopl( 3 ))) - return 0; - trst = (inb( port ) >> TRST) & 1; + int data; - return 1; -} + if (parport_open( cable->port )) + return -1; -static void -arcom_done( void ) -{ - if (port + 2 <= 0x400) - ioperm( port, 2, 0 ); - else - iopl( 0 ); + if ((data = parport_get_data( cable->port )) < 0) { + if (parport_set_data( cable->port, 1 << TRST )) + return -1; + PARAM_TRST(cable) = 1; + } else + PARAM_TRST(cable) = (data >> TRST) & 1; + + return 0; } static void -arcom_clock( int tms, int tdi ) +arcom_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - outb( (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); } static int -arcom_get_tdo( void ) +arcom_get_tdo( cable_t *cable ) { - outb( (trst << TRST) | (0 << TCK), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -arcom_set_trst( int new_trst ) +arcom_set_trst( cable_t *cable, int trst ) { - trst = new_trst ? 1 : 0; - - outb( trst << TRST, port ); - return trst; -} + PARAM_TRST(cable) = trst ? 1 : 0; -static int -arcom_get_trst( void ) -{ - return trst; + parport_set_data( cable->port, PARAM_TRST(cable) << TRST ); + return PARAM_TRST(cable); } cable_driver_t arcom_cable_driver = { "ARCOM", "Arcom JTAG Cable", + generic_connect, + generic_disconnect, + generic_cable_free, arcom_init, - arcom_done, + generic_done, arcom_clock, arcom_get_tdo, arcom_set_trst, - arcom_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/cable/byteblaster.c b/jtag/src/tap/cable/byteblaster.c index 74b21f2c..cd93f02c 100644 --- a/jtag/src/tap/cable/byteblaster.c +++ b/jtag/src/tap/cable/byteblaster.c @@ -31,9 +31,11 @@ * */ -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* * data D[7:0] (pins 9:2) @@ -51,52 +53,39 @@ */ #define TDO 7 -static unsigned int port; - static int -byteblaster_init( unsigned int aport ) +byteblaster_init( cable_t *cable ) { - port = aport; - return !(((port + 2 <= 0x400) && ioperm( port, 2, 1 )) || ((port + 2 > 0x400) && iopl( 3 ))); -} + if (parport_open( cable->port )) + return -1; -static void -byteblaster_done( void ) -{ - if (port + 2 <= 0x400) - ioperm( port, 2, 0 ); - else - iopl( 0 ); + PARAM_TRST(cable) = 1; + + return 0; } static void -byteblaster_clock( int tms, int tdi ) +byteblaster_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - outb( (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); } static int -byteblaster_get_tdo( void ) +byteblaster_get_tdo( cable_t *cable ) { - outb( 0 << TCK, port ); + parport_set_data( cable->port, 0 << TCK ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ -} - -static int -byteblaster_set_trst( int new_trst ) -{ - return 1; + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -byteblaster_get_trst( void ) +byteblaster_set_trst( cable_t *cable, int trst ) { return 1; } @@ -104,10 +93,13 @@ byteblaster_get_trst( void ) cable_driver_t byteblaster_cable_driver = { "ByteBlaster", "Altera ByteBlaster/ByteBlaster II/ByteBlasterMV Parallel Port Download Cable", + generic_connect, + generic_disconnect, + generic_cable_free, byteblaster_init, - byteblaster_done, + generic_done, byteblaster_clock, byteblaster_get_tdo, byteblaster_set_trst, - byteblaster_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/cable/dlc5.c b/jtag/src/tap/cable/dlc5.c index eacefe53..7f3c2910 100644 --- a/jtag/src/tap/cable/dlc5.c +++ b/jtag/src/tap/cable/dlc5.c @@ -27,9 +27,11 @@ * */ -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* see Figure B-1 in [1] */ @@ -51,52 +53,39 @@ */ #define TDO 4 -static unsigned int port; - static int -dlc5_init( unsigned int aport ) +dlc5_init( cable_t *cable ) { - port = aport; - return !(((port + 2 <= 0x400) && ioperm( port, 2, 1 )) || ((port + 2 > 0x400) && iopl( 3 ))); -} + if (parport_open( cable->port )) + return -1; -static void -dlc5_done( void ) -{ - if (port + 2 <= 0x400) - ioperm( port, 2, 0 ); - else - iopl( 0 ); + PARAM_TRST(cable) = 1; + + return 0; } static void -dlc5_clock( int tms, int tdi ) +dlc5_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (1 << PROG) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - outb( (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (1 << PROG) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); } static int -dlc5_get_tdo( void ) +dlc5_get_tdo( cable_t *cable ) { - outb( (1 << PROG) | (0 << TCK), port ); + parport_set_data( cable->port, (1 << PROG) | (0 << TCK) ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ -} - -static int -dlc5_set_trst( int new_trst ) -{ - return 1; + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -dlc5_get_trst( void ) +dlc5_set_trst( cable_t *cable, int trst ) { return 1; } @@ -104,10 +93,13 @@ dlc5_get_trst( void ) cable_driver_t dlc5_cable_driver = { "DLC5", "Xilinx DLC5 JTAG Parallel Cable III", + generic_connect, + generic_disconnect, + generic_cable_free, dlc5_init, - dlc5_done, + generic_done, dlc5_clock, dlc5_get_tdo, dlc5_set_trst, - dlc5_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/cable/ea253.c b/jtag/src/tap/cable/ea253.c index c2e2d7aa..591f89f1 100644 --- a/jtag/src/tap/cable/ea253.c +++ b/jtag/src/tap/cable/ea253.c @@ -23,9 +23,11 @@ * */ -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* * data D[7:0] (pins 9:2) @@ -44,71 +46,63 @@ */ #define TDO 4 -static int trst; -static unsigned int port; - static int -ea253_init( unsigned int aport ) +ea253_init( cable_t *cable ) { - port = aport; - if (((port + 2 <= 0x400) && ioperm( port, 2, 1 )) || ((port + 2 > 0x400) && iopl( 3 ))) - return 0; - trst = (inb( port ) >> TRST) & 1; + int data; - return 1; -} + if (parport_open( cable->port )) + return -1; -static void -ea253_done( void ) -{ - if (port + 2 <= 0x400) - ioperm( port, 2, 0 ); - else - iopl( 0 ); + if ((data = parport_get_data( cable->port )) < 0) { + if (parport_set_data( cable->port, 1 << TRST )) + return -1; + PARAM_TRST(cable) = 1; + } else + PARAM_TRST(cable) = (data >> TRST) & 1; + + return 0; } static void -ea253_clock( int tms, int tdi ) +ea253_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - outb( (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); } static int -ea253_get_tdo( void ) +ea253_get_tdo( cable_t *cable ) { - outb( (trst << TRST) | (0 << TCK), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -ea253_set_trst( int new_trst ) +ea253_set_trst( cable_t *cable, int trst ) { - trst = new_trst ? 1 : 0; - - outb( trst << TRST, port ); - return trst; -} + PARAM_TRST(cable) = trst ? 1 : 0; -static int -ea253_get_trst( void ) -{ - return trst; + parport_set_data( cable->port, PARAM_TRST(cable) << TRST ); + return PARAM_TRST(cable); } cable_driver_t ea253_cable_driver = { "EA253", "ETC EA253 JTAG Cable", + generic_connect, + generic_disconnect, + generic_cable_free, ea253_init, - ea253_done, + generic_done, ea253_clock, ea253_get_tdo, ea253_set_trst, - ea253_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/cable/ei012.c b/jtag/src/tap/cable/ei012.c index a98982e0..0cdefa10 100644 --- a/jtag/src/tap/cable/ei012.c +++ b/jtag/src/tap/cable/ei012.c @@ -23,10 +23,11 @@ * */ -#include -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* * data D[7:0] (pins 9:2) @@ -45,71 +46,63 @@ */ #define TDO 7 -static int trst; -static unsigned int port; - static int -ei012_init( unsigned int aport ) +ei012_init( cable_t *cable ) { - port = aport; - if (((port + 2 <= 0x400) && ioperm( port, 2, 1 )) || ((port + 2 > 0x400) && iopl( 3 ))) - return 0; - trst = (inb( port ) >> TRST) & 1; + int data; - return 1; -} + if (parport_open( cable->port )) + return -1; -static void -ei012_done( void ) -{ - if (port + 2 <= 0x400) - ioperm( port, 2, 0 ); - else - iopl( 0 ); + if ((data = parport_get_data( cable->port )) < 0) { + if (parport_set_data( cable->port, 1 << TRST )) + return -1; + PARAM_TRST(cable) = 1; + } else + PARAM_TRST(cable) = (data >> TRST) & 1; + + return 0; } static void -ei012_clock( int tms, int tdi ) +ei012_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - outb( (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); } static int -ei012_get_tdo( void ) +ei012_get_tdo( cable_t *cable ) { - outb( (trst << TRST) | (0 << TCK), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -ei012_set_trst( int new_trst ) +ei012_set_trst( cable_t *cable, int trst ) { - trst = new_trst ? 1 : 0; - - outb( trst << TRST, port ); - return trst; -} + PARAM_TRST(cable) = trst ? 1 : 0; -static int -ei012_get_trst( void ) -{ - return trst; + parport_set_data( cable->port, PARAM_TRST(cable) << TRST ); + return PARAM_TRST(cable); } cable_driver_t ei012_cable_driver = { "EI012", "ETC EI012 JTAG Cable", + generic_connect, + generic_disconnect, + generic_cable_free, ei012_init, - ei012_done, + generic_done, ei012_clock, ei012_get_tdo, ei012_set_trst, - ei012_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/cable/generic.c b/jtag/src/tap/cable/generic.c new file mode 100644 index 00000000..61191482 --- /dev/null +++ b/jtag/src/tap/cable/generic.c @@ -0,0 +1,77 @@ +/* + * $Id$ + * + * Copyright (C) 2003 ETC s.r.o. + * + * 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 Marcel Telka , 2003. + * + */ + +#include + +#include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" + +cable_t * +generic_connect( cable_driver_t *cable_driver, parport_t *port ) +{ + generic_params_t *params = malloc( sizeof *params ); + cable_t *cable = malloc( sizeof *cable ); + if (!params || !cable) { + free( params ); + free( cable ); + return NULL; + } + + cable->driver = cable_driver; + cable->port = port; + cable->params = params; + cable->chain = NULL; + + return cable; +} + +void +generic_disconnect( cable_t *cable ) +{ + cable_done( cable ); + chain_disconnect( cable->chain ); +} + +void +generic_cable_free( cable_t *cable ) +{ + cable->port->driver->parport_free( cable->port ); + free( cable->params ); + free( cable ); +} + +void +generic_done( cable_t *cable ) +{ + parport_close( cable->port ); +} + +int +generic_get_trst( cable_t *cable ) +{ + return PARAM_TRST(cable); +} diff --git a/jtag/src/tap/cable/generic.h b/jtag/src/tap/cable/generic.h new file mode 100644 index 00000000..7b2d3d03 --- /dev/null +++ b/jtag/src/tap/cable/generic.h @@ -0,0 +1,43 @@ +/* + * $Id$ + * + * Copyright (C) 2003 ETC s.r.o. + * + * 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 Marcel Telka , 2003. + * + */ + +#ifndef GENERIC_H +#define GENERIC_H + +#include "cable.h" +#include "parport.h" + +typedef struct { + int trst; +} generic_params_t; + +#define PARAM_TRST(cable) ((generic_params_t *) cable->params)->trst + +cable_t *generic_connect( cable_driver_t *cable_driver, parport_t *port ); +void generic_disconnect( cable_t *cable ); +void generic_cable_free( cable_t *cable ); +void generic_done( cable_t *cable ); +int generic_get_trst( cable_t *cable ); + +#endif /* GENERIC_H */ diff --git a/jtag/src/tap/cable/mpcbdm.c b/jtag/src/tap/cable/mpcbdm.c index d12ff75a..e754bfd1 100644 --- a/jtag/src/tap/cable/mpcbdm.c +++ b/jtag/src/tap/cable/mpcbdm.c @@ -27,9 +27,11 @@ * */ -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* * data @@ -49,76 +51,60 @@ */ #define TDO 5 -static int trst; -static unsigned int port; - static int -mpcbdm_init( unsigned int aport ) +mpcbdm_init( cable_t *cable ) { - port = aport; - if (((port + 3 <= 0x400) && ioperm( port, 3, 1 )) || ((port + 3 > 0x400) && iopl( 3 ))) - return 0; + if (parport_open( cable->port )) + return -1; - outb( (1 << TRST) | (1 << TRST1), port + 2 ); - trst = 1; + parport_set_control( cable->port, (1 << TRST) | (1 << TRST1) ); + PARAM_TRST(cable) = 1; - return 1; + return 0; } static void -mpcbdm_done( void ) -{ - if (port + 3 <= 0x400) - ioperm( port, 3, 0 ); - else - iopl( 0 ); -} - -static void -mpcbdm_clock( int tms, int tdi ) +mpcbdm_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); - outb( (trst << TRST) | (trst << TRST1), port + 2 ); + parport_set_data( cable->port, (0 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_control( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_TRST(cable) << TRST1) ); cable_wait(); - outb( (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); - outb( (trst << TRST) | (trst << TRST1), port + 2 ); + parport_set_data( cable->port, (1 << TCK) | (tms << TMS) | (tdi << TDI) ); + parport_set_control( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_TRST(cable) << TRST1) ); cable_wait(); } static int -mpcbdm_get_tdo( void ) +mpcbdm_get_tdo( cable_t *cable ) { - outb( (0 << TCK), port ); - outb( (trst << TRST) | (trst << TRST1), port + 2 ); + parport_set_data( cable->port, 0 << TCK ); + parport_set_control( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_TRST(cable) << TRST1) ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -mpcbdm_set_trst( int new_trst ) +mpcbdm_set_trst( cable_t *cable, int trst ) { - trst = new_trst ? 1 : 0; - - outb( (trst << TRST) | (trst << TRST1), port + 2 ); - return trst; -} + PARAM_TRST(cable) = trst ? 1 : 0; -static int -mpcdbm_get_trst( void ) -{ - return trst; + parport_set_control( cable->port, (PARAM_TRST(cable) << TRST) | (PARAM_TRST(cable) << TRST1) ); + return PARAM_TRST(cable); } cable_driver_t mpcbdm_cable_driver = { "MPCBDM", "Mpcbdm JTAG cable", + generic_connect, + generic_disconnect, + generic_cable_free, mpcbdm_init, - mpcbdm_done, + generic_done, mpcbdm_clock, mpcbdm_get_tdo, mpcbdm_set_trst, - mpcdbm_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/cable/wiggler.c b/jtag/src/tap/cable/wiggler.c index edc9467c..e8626824 100644 --- a/jtag/src/tap/cable/wiggler.c +++ b/jtag/src/tap/cable/wiggler.c @@ -27,9 +27,11 @@ * */ -#include - #include "cable.h" +#include "parport.h" +#include "chain.h" + +#include "generic.h" /* * data D[7:0] (pins 9:2) @@ -48,71 +50,63 @@ */ #define TDO 7 -static int trst; -static unsigned int port; - static int -wiggler_init( unsigned int aport ) +wiggler_init( cable_t *cable ) { - port = aport; - if (((port + 2 <= 0x400) && ioperm( port, 2, 1 )) || ((port + 2 > 0x400) && iopl( 3 ))) - return 0; - trst = (inb( port ) >> TRST) & 1; + int data; - return 1; -} + if (parport_open( cable->port )) + return -1; -static void -wiggler_done( void ) -{ - if (port + 2 <= 0x400) - ioperm( port, 2, 0 ); - else - iopl( 0 ); + if ((data = parport_get_data( cable->port )) < 0) { + if (parport_set_data( cable->port, 1 << TRST )) + return -1; + PARAM_TRST(cable) = 1; + } else + PARAM_TRST(cable) = (data >> TRST) & 1; + + return 0; } static void -wiggler_clock( int tms, int tdi ) +wiggler_clock( cable_t *cable, int tms, int tdi ) { tms = tms ? 1 : 0; tdi = tdi ? 1 : 0; - outb( (trst << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); - outb( (trst << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (1 << TCK) | (tms << TMS) | (tdi << TDI) ); cable_wait(); } static int -wiggler_get_tdo( void ) +wiggler_get_tdo( cable_t *cable ) { - outb( (trst << TRST) | (0 << TCK), port ); + parport_set_data( cable->port, (PARAM_TRST(cable) << TRST) | (0 << TCK) ); cable_wait(); - return ((inb( port + 1 ) ^ 0x80) >> TDO) & 1; /* BUSY is inverted */ + return (parport_get_status( cable->port ) >> TDO) & 1; } static int -wiggler_set_trst( int new_trst ) +wiggler_set_trst( cable_t *cable, int trst ) { - trst = new_trst ? 1 : 0; - - outb( trst << TRST, port ); - return trst; -} + PARAM_TRST(cable) = trst ? 1 : 0; -static int -wiggler_get_trst( void ) -{ - return trst; + parport_set_data( cable->port, PARAM_TRST(cable) << TRST ); + return PARAM_TRST(cable); } cable_driver_t wiggler_cable_driver = { "WIGGLER", "Macraigor Wiggler JTAG Cable", + generic_connect, + generic_disconnect, + generic_cable_free, wiggler_init, - wiggler_done, + generic_done, wiggler_clock, wiggler_get_tdo, wiggler_set_trst, - wiggler_get_trst + generic_get_trst }; diff --git a/jtag/src/tap/chain.c b/jtag/src/tap/chain.c index bce112e8..c46e1de9 100644 --- a/jtag/src/tap/chain.c +++ b/jtag/src/tap/chain.c @@ -57,31 +57,22 @@ chain_free( chain_t *chain ) if (!chain) return; - if (chain->cable) { - chain->cable->set_trst( 0 ); - chain->cable->set_trst( 1 ); - tap_reset( chain ); - chain->cable->done(); - } - tap_state_done( chain ); - /* cable_free( chain->cable ); */ + chain_disconnect( chain ); + parts_free( chain->parts ); free( chain ); } -int -chain_connect( chain_t *chain, cable_t *cable, unsigned int port ) +void +chain_disconnect( chain_t *chain ) { - if (chain->cable) { - tap_state_done( chain ); - chain->cable->done(); - chain->cable = NULL; - } - if (!cable || !cable->init( port )) - return -1; + if (!chain->cable) + return; - chain->cable = cable; - return 0; + tap_state_done( chain ); + cable_done( chain->cable ); + cable_free( chain->cable ); + chain->cable = NULL; } void @@ -90,15 +81,15 @@ chain_clock( chain_t *chain, int tms, int tdi ) if (!chain || !chain->cable) return; - chain->cable->clock( tms, tdi ); + cable_clock( chain->cable, tms, tdi ); tap_state_clock( chain, tms ); } int chain_set_trst( chain_t *chain, int trst ) { - int old_trst = chain->cable->get_trst(); - trst = chain->cable->set_trst( trst ); + int old_trst = cable_get_trst( chain->cable ); + trst = cable_set_trst( chain->cable, trst ); tap_state_set_trst( chain, old_trst, trst ); return trst; } @@ -106,7 +97,7 @@ chain_set_trst( chain_t *chain, int trst ) int chain_get_trst( chain_t *chain ) { - return chain->cable->get_trst(); + return cable_get_trst( chain->cable ); } void diff --git a/jtag/src/tap/parport.c b/jtag/src/tap/parport.c new file mode 100644 index 00000000..0d16b179 --- /dev/null +++ b/jtag/src/tap/parport.c @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * Copyright (C) 2003 ETC s.r.o. + * + * 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 Marcel Telka , 2003. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "parport.h" + +extern parport_driver_t direct_parport_driver; + +parport_driver_t *parport_drivers[] = { + &direct_parport_driver, + NULL /* last must be NULL */ +}; + +int +parport_open( parport_t *port ) +{ + return port->driver->open( port ); +} + +int +parport_close( parport_t *port ) +{ + return port->driver->close( port ); +} + +int +parport_set_data( parport_t *port, uint8_t data ) +{ + return port->driver->set_data( port, data ); +} + +int +parport_get_data( parport_t *port ) +{ + return port->driver->get_data( port ); +} + +int +parport_get_status( parport_t *port ) +{ + return port->driver->get_status( port ); +} + +int +parport_set_control( parport_t *port, uint8_t data ) +{ + return port->driver->set_control( port, data ); +} diff --git a/jtag/src/tap/parport/direct.c b/jtag/src/tap/parport/direct.c new file mode 100644 index 00000000..0c341f0b --- /dev/null +++ b/jtag/src/tap/parport/direct.c @@ -0,0 +1,216 @@ +/* + * $Id$ + * + * Direct Parallel Port Connection Driver + * Copyright (C) 2003 ETC s.r.o. + * + * 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 Marcel Telka , 2003. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gettext.h" +#define _(s) gettext(s) +#define N_(s) gettext_noop(s) +#define P_(s,p,n) ngettext(s,p,n) + +#include +#include +#include + +#include "parport.h" +#include "cable.h" + +parport_driver_t direct_parport_driver; + +typedef struct port_node_t port_node_t; + +struct port_node_t { + parport_t *port; + port_node_t *next; +}; + +static port_node_t *ports = NULL; /* direct parallel ports */ + +typedef struct { + unsigned int port; +} direct_params_t; + +static parport_t * +direct_parport_alloc( unsigned int port ) +{ + direct_params_t *params = malloc( sizeof *params ); + parport_t *parport = malloc( sizeof *parport ); + port_node_t *node = malloc( sizeof *node ); + + if (!node || !parport || !params) { + free( node ); + free( parport ); + free( params ); + return NULL; + } + + params->port = port; + + parport->params = params; + parport->driver = &direct_parport_driver; + parport->cable = NULL; + + node->port = parport; + node->next = ports; + + ports = node; + + return parport; +} + +static void +direct_parport_free( parport_t *port ) +{ + port_node_t **prev; + + for (prev = &ports; *prev; prev = &((*prev)->next)) + if ((*prev)->port == port) + break; + + if (*prev) { + port_node_t *pn = *prev; + *prev = pn->next; + free( pn ); + } + + free( port->params ); + free( port ); +} + +static cable_t * +direct_connect( const char **par, int parnum ) +{ + int i; + unsigned int port; + port_node_t *pn; + parport_t *parport; + cable_t *cable; + + if (parnum != 2) { + printf( _("Syntax error!\n") ); + return NULL; + } + + if ((sscanf( par[0], "0x%x", &port ) != 1) && (sscanf( par[0], "%d", &port ) != 1)) { + printf( _("Invalid port address!\n") ); + return NULL; + } + + for (pn = ports; pn; pn = pn->next) { + unsigned int aport; + + aport = ((direct_params_t*) pn->port->params)->port; + if (abs( aport - port ) < 3) { + printf( _("Disconnecting %s from parallel port at 0x%x\n"), pn->port->cable->driver->description, aport ); + pn->port->cable->driver->disconnect( pn->port->cable ); + } + } + + if (strcmp( par[1], "none" ) == 0) { + printf( _("Changed cable to 'none'\n") ); + return NULL; + } + + for (i = 0; cable_drivers[i]; i++) + if (strcmp( par[1], cable_drivers[i]->name ) == 0) + break; + + if (!cable_drivers[i]) { + printf( _("Unknown cable: %s\n"), par[1] ); + return NULL; + } + + printf( _("Initializing %s on parallel port at 0x%x\n"), cable_drivers[i]->description, port ); + + parport = direct_parport_alloc( port ); + if (!parport) { + printf( _("%s(%d) Out of memory.\n"), __FILE__, __LINE__ ); + return NULL; + } + + cable = cable_drivers[i]->connect( cable_drivers[i], parport ); + if (!cable) + direct_parport_free( parport ); + + return cable; +} + +static int +direct_open( parport_t *parport ) +{ + unsigned int port = ((direct_params_t *) parport->params)->port; + return ((port + 3 <= 0x400) && ioperm( port, 3, 1 )) || ((port + 3 > 0x400) && iopl( 3 )); +} + +static int +direct_close( parport_t *parport ) +{ + unsigned int port = ((direct_params_t *) parport->params)->port; + return (port + 3 <= 0x400) ? ioperm( port, 3, 0 ) : iopl( 0 ); +} + +static int +direct_set_data( parport_t *parport, uint8_t data ) +{ + unsigned int port = ((direct_params_t *) parport->params)->port; + outb( data, port ); + return 0; +} + +static int +direct_get_data( parport_t *parport ) +{ + unsigned int port = ((direct_params_t *) parport->params)->port; + return inb( port ); +} + +static int +direct_get_status( parport_t *parport ) +{ + unsigned int port = ((direct_params_t *) parport->params)->port; + return inb( port + 1 ) ^ 0x80; /* BUSY is inverted */ +} + +static int +direct_set_control( parport_t *parport, uint8_t data ) +{ + unsigned int port = ((direct_params_t *) parport->params)->port; + outb( data, port + 2 ); + return 0; +} + +parport_driver_t direct_parport_driver = { + "parallel", + direct_connect, + direct_parport_free, + direct_open, + direct_close, + direct_set_data, + direct_get_data, + direct_get_status, + direct_set_control +}; diff --git a/jtag/src/tap/tap.c b/jtag/src/tap/tap.c index c36eff22..b9f6c9cd 100644 --- a/jtag/src/tap/tap.c +++ b/jtag/src/tap/tap.c @@ -65,7 +65,7 @@ tap_shift_register( chain_t *chain, const tap_register *in, tap_register *out, i chain_clock( chain, 0, 0 ); /* save last TDO bit :-) */ for (i = 0; i < in->len; i++) { if (out && (i < out->len)) - out->data[i] = chain->cable->get_tdo(); + out->data[i] = cable_get_tdo( chain->cable ); chain_clock( chain, (exit && ((i + 1) == in->len)) ? 1 : 0, in->data[i] ); /* Shift (& Exit1) */ } /* Shift-DR, Shift-IR, Exit1-DR or Exit1-IR state */