You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

721 lines
21 KiB

/*
* xsvftool-xpcu - An (X)SVF player for the Xilinx Platform Cable USB
*
* Copyright (C) 2011 RIEGL Research ForschungsGmbH
* Copyright (C) 2011 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include "libxsvf.h"
#include "fx2usb-interface.h"
#include "filedata.h"
char *correct_cksum =
#include "hardware_cksum_c.inc"
;
#define UNUSED __attribute__((unused))
/**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/
// This is to not confuse the VIM syntax highlighting
#define CHECK_VAL_OPEN (
#define CHECK_VAL_CLOSE )
#define CHECK(result, check) \
CHECK_VAL_OPEN{ \
typeof(result) _R = (result); \
if (!(_R check)) { \
fprintf(stderr, "Error from '%s' (%d %s) in %s:%d.\n", \
#result, (int)_R, #check, __FILE__, __LINE__); \
fprintf(stderr, "ERRNO(%d): %s\n", errno, strerror(errno)); \
abort(); \
} \
_R; \
}CHECK_VAL_CLOSE
#define CHECK_PTR(result, check) \
CHECK_VAL_OPEN{ \
typeof(result) _R = (result); \
if (!(_R check)) { \
fprintf(stderr, "Error from '%s' (%p %s) in %s:%d.\n", \
#result, (void*)_R, #check, __FILE__, __LINE__); \
fprintf(stderr, "ERRNO(%d): %s\n", errno, strerror(errno)); \
abort(); \
} \
_R; \
}CHECK_VAL_CLOSE
/**** END: http://svn.clifford.at/tools/trunk/examples/check.h ****/
FILE *file_fp = NULL;
int usb_vendor_id = 0;
int usb_device_id = 0;
char *usb_device_file = NULL;
int mode_frequency = 6000;
int mode_async_check = 0;
int mode_internal_cpld = 0;
int mode_8bit_per_cycle = 0;
int mode_hex_rmask = 0;
usb_dev_handle *fx2usb;
int internal_jtag_scan_test = 0;
int sync_count;
int tck_cycle_count;
int blocks_without_sync;
int tdo_check_period_100;
int tdo_check_thisperiod;
int rmask_bits = 0, rmask_bytes = 0;
unsigned char *rmask_data = NULL;
/* This constant are used to determine when the error status should be synced.
* Syncinc to often would slow things down, syncinc not often enough might cause
* errors beeing reported by far to late.
*/
#define FORCE_SYNC_AFTER_N_BLOCKS 100
#define FORCE_SYNC_MIN_PERIOD 10000
#define FORCE_SYNC_INIT_PERIOD 100000
// send larger junks to USB stack and let the kernel split it up
// #define MAXBUF() (mode_internal_cpld ? 50 : mode_8bit_per_cycle ? 500 : 1000)
#define MAXBUF() (mode_internal_cpld ? 50 : 4000)
unsigned char fx2usb_retbuf[65];
int fx2usb_retlen;
unsigned char commandbuf[4096];
int commandbuf_len;
static void shrink_8bit_to_4bit()
{
int i;
if ((commandbuf_len & 1) != 0)
commandbuf[commandbuf_len++] = 0;
for (i = 0; i<commandbuf_len; i++) {
if ((i & 1) == 0)
commandbuf[i >> 1] = (commandbuf[i >> 1] & 0xf0) | commandbuf[i];
else
commandbuf[i >> 1] = (commandbuf[i >> 1] & 0x0f) | (commandbuf[i] << 4);
}
commandbuf_len = commandbuf_len >> 1;
}
void fx2usb_command(const char *cmd)
{
// fprintf(stderr, "Sending FX2USB Command: '%s' => ", cmd);
fx2usb_send_chunk(fx2usb, 1, cmd, strlen(cmd));
fx2usb_recv_chunk(fx2usb, 1, fx2usb_retbuf, sizeof(fx2usb_retbuf)-1, &fx2usb_retlen);
fx2usb_retbuf[fx2usb_retlen] = 0;
// fprintf(stderr, "'%s'\n", fx2usb_retbuf);
if (strchr((char*)fx2usb_retbuf, '!') != NULL) {
fprintf(stderr, "Internal ERROR in communication with probe: '%s' => '%s'\n", cmd, fx2usb_retbuf);
abort();
}
}
static int xpcu_set_frequency(struct libxsvf_host *h UNUSED, int v);
static int xpcu_pulse_tck(struct libxsvf_host *h UNUSED, int tms, int tdi, int tdo, int rmask UNUSED, int sync);
static int xpcu_setup(struct libxsvf_host *h UNUSED)
{
sync_count = 0;
blocks_without_sync = 0;
commandbuf_len = 0;
fx2usb_command("R");
if (!mode_internal_cpld) {
fx2usb_command("B1");
}
if (mode_frequency)
xpcu_set_frequency(h, mode_frequency * 1000);
tdo_check_period_100 = FORCE_SYNC_INIT_PERIOD * 100;
tdo_check_thisperiod = 0;
return 0;
}
static int xpcu_shutdown(struct libxsvf_host *h UNUSED)
{
int rc = 0;
if (commandbuf_len != 0) {
fprintf(stderr, "Found %d unsynced commands in command buffer on interface shutdown!\n", commandbuf_len);
commandbuf_len = 0;
rc = -1;
}
fx2usb_command("S");
if (fx2usb_retbuf[mode_internal_cpld ? 1 : 0] == '1') {
fprintf(stderr, "Found pending errors in interface status on shutdown!\n");
rc = -1;
}
fx2usb_command("R");
return rc;
}
static void xpcu_udelay(struct libxsvf_host *h UNUSED, long usecs, int tms, long num_tck)
{
struct timeval tv1, tv2;
long rem_usecs;
if (mode_internal_cpld)
{
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
unsigned char tempbuf[64];
tempbuf[0] = 'J';
memcpy(tempbuf+1, commandbuf, commandbuf_len);
fx2usb_send_chunk(fx2usb, 1, tempbuf, commandbuf_len + 1);
fx2usb_command("P");
commandbuf_len = 0;
}
else
{
sync_count = 0x08 | ((sync_count+1) & 0x0f);
commandbuf[commandbuf_len++] = 0x01;
commandbuf[commandbuf_len++] = sync_count;
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
fx2usb_send_chunk(fx2usb, 2, commandbuf, commandbuf_len);
commandbuf_len = 0;
char cmd[3];
snprintf(cmd, 3, "W%x", sync_count);
fx2usb_command(cmd);
}
gettimeofday(&tv1, NULL);
while (num_tck > 0) {
xpcu_pulse_tck(h, tms, 0, -1, 0, 0);
num_tck--;
}
if (mode_internal_cpld)
{
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
unsigned char tempbuf[64];
tempbuf[0] = 'J';
memcpy(tempbuf+1, commandbuf, commandbuf_len);
fx2usb_send_chunk(fx2usb, 1, tempbuf, commandbuf_len + 1);
fx2usb_command("P");
commandbuf_len = 0;
}
else
{
sync_count = 0x08 | ((sync_count+1) & 0x0f);
commandbuf[commandbuf_len++] = 0x01;
commandbuf[commandbuf_len++] = sync_count;
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
fx2usb_send_chunk(fx2usb, 2, commandbuf, commandbuf_len);
commandbuf_len = 0;
char cmd[3];
snprintf(cmd, 3, "W%x", sync_count);
fx2usb_command(cmd);
}
while (usecs > 0) {
gettimeofday(&tv2, NULL);
rem_usecs = usecs - ((tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec));
if (rem_usecs <= 0)
break;
usleep(rem_usecs);
}
}
static int xpcu_getbyte(struct libxsvf_host *h UNUSED)
{
return fgetc(file_fp);
}
static int xpcu_pulse_tck(struct libxsvf_host *h UNUSED, int tms, int tdi, int tdo, int rmask, int sync)
{
int dummy_sync = 0;
tck_cycle_count++;
if (tdo >= 0) {
commandbuf[commandbuf_len++] = 0x08 | ((tdo & 1) << 2) | ((tms & 1) << 1) | ((tdi & 1) << 0);
tdo_check_period_100 = (tdo_check_period_100 * 99) / 100 + tdo_check_thisperiod;
tdo_check_thisperiod = 0;
} else {
commandbuf[commandbuf_len++] = 0x04 | ((tms & 1) << 1) | ((tdi & 1) << 0);
}
if (mode_async_check == 0)
{
if (!sync && tdo >= 0 && (blocks_without_sync > FORCE_SYNC_AFTER_N_BLOCKS || tdo_check_period_100 > FORCE_SYNC_MIN_PERIOD))
sync = 1;
if (!sync && !mode_internal_cpld && blocks_without_sync > 10*FORCE_SYNC_AFTER_N_BLOCKS && commandbuf_len >= (MAXBUF() - 10))
dummy_sync = 1;
}
if (rmask && !sync)
dummy_sync = 1;
if ((dummy_sync || sync) && !mode_internal_cpld) {
sync_count = 0x08 | ((sync_count+1) & 0x0f);
commandbuf[commandbuf_len++] = 0x01;
commandbuf[commandbuf_len++] = sync_count;
}
if (commandbuf_len >= (MAXBUF() - 4) || sync || dummy_sync) {
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
if (mode_internal_cpld) {
unsigned char tempbuf[64];
tempbuf[0] = 'J';
memcpy(tempbuf+1, commandbuf, commandbuf_len);
fx2usb_send_chunk(fx2usb, 1, tempbuf, commandbuf_len + 1);
} else {
fx2usb_send_chunk(fx2usb, 2, commandbuf, commandbuf_len);
}
blocks_without_sync++;
commandbuf_len = 0;
}
if ((sync || dummy_sync) && !mode_internal_cpld) {
char cmd[3];
snprintf(cmd, 3, "W%x", sync_count);
fx2usb_command(cmd);
}
if (sync) {
fx2usb_command("S");
blocks_without_sync = 0;
}
if (dummy_sync) {
fx2usb_command("P");
blocks_without_sync = 0;
}
if (rmask) {
if (rmask_bits >= 8*rmask_bytes) {
int old_rmask_bytes = rmask_bytes;
rmask_bytes = rmask_bytes ? rmask_bytes*2 : 64;
rmask_data = realloc(rmask_data, rmask_bytes);
memset(rmask_data + old_rmask_bytes, 0, rmask_bytes-old_rmask_bytes);
}
if (fx2usb_retbuf[mode_internal_cpld ? 5 : 4] == '1')
rmask_data[rmask_bits/8] |= 1 << (rmask_bits%8);
rmask_bits++;
}
if (sync) {
if (fx2usb_retbuf[mode_internal_cpld ? 1 : 0] == '1')
return -1;
return fx2usb_retbuf[mode_internal_cpld ? 5 : 4] == '1';
}
return tdo < 0 ? 1 : tdo;
}
static int xpcu_sync(struct libxsvf_host *h UNUSED)
{
if (!mode_internal_cpld) {
sync_count = 0x08 | ((sync_count+1) & 0x0f);
commandbuf[commandbuf_len++] = 0x01;
commandbuf[commandbuf_len++] = sync_count;
}
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
if (mode_internal_cpld) {
unsigned char tempbuf[64];
tempbuf[0] = 'J';
memcpy(tempbuf+1, commandbuf, commandbuf_len);
fx2usb_send_chunk(fx2usb, 1, tempbuf, commandbuf_len + 1);
} else {
fx2usb_send_chunk(fx2usb, 2, commandbuf, commandbuf_len);
}
commandbuf_len = 0;
if (!mode_internal_cpld) {
char cmd[3];
snprintf(cmd, 3, "W%x", sync_count);
fx2usb_command(cmd);
}
fx2usb_command("S");
blocks_without_sync = 0;
if (fx2usb_retbuf[mode_internal_cpld ? 1 : 0] == '1')
return -1;
return 0;
}
static int xpcu_set_frequency(struct libxsvf_host *h UNUSED, int v)
{
int freq = 24000000, delay = 0;
if (mode_internal_cpld)
return 0;
if (!mode_internal_cpld) {
sync_count = 0x08 | ((sync_count+1) & 0x0f);
commandbuf[commandbuf_len++] = 0x01;
commandbuf[commandbuf_len++] = sync_count;
}
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
if (mode_internal_cpld) {
unsigned char tempbuf[64];
tempbuf[0] = 'J';
memcpy(tempbuf+1, commandbuf, commandbuf_len);
fx2usb_send_chunk(fx2usb, 1, tempbuf, commandbuf_len + 1);
} else {
fx2usb_send_chunk(fx2usb, 2, commandbuf, commandbuf_len);
}
commandbuf_len = 0;
if (!mode_internal_cpld) {
char cmd[3];
snprintf(cmd, 3, "W%x", sync_count);
fx2usb_command(cmd);
}
while (delay < 250 && v < freq) {
delay++;
freq = 48000000 / (2*delay + 2);
}
if (v < freq)
fprintf(stderr, "Requested FREQUENCY %dHz is to low! Using minimum value %dHz instead.\n", v, freq);
else if (v-freq > 10)
fprintf(stderr, "Requested FREQUENCY is %dHz. Using %dHz (24MHz/%d) instead.\n", v, freq, delay+1);
char cmd[4];
snprintf(cmd, 4, "T%02x", delay);
fx2usb_command(cmd);
mode_8bit_per_cycle = delay != 0;
if (!mode_internal_cpld)
{
sync_count = 0x08 | ((sync_count+1) & 0x0f);
commandbuf[commandbuf_len++] = 0x01;
commandbuf[commandbuf_len++] = sync_count;
if (!mode_8bit_per_cycle)
shrink_8bit_to_4bit();
fx2usb_send_chunk(fx2usb, 2, commandbuf, commandbuf_len);
commandbuf_len = 0;
char cmd[3];
snprintf(cmd, 3, "W%x", sync_count);
fx2usb_command(cmd);
}
return 0;
}
static void xpcu_report_tapstate(struct libxsvf_host *h UNUSED)
{
// fprintf(stderr, "[%s]\n", libxsvf_state2str(h->tap_state));
}
static void xpcu_report_device(struct libxsvf_host *h UNUSED, unsigned long idcode)
{
if (internal_jtag_scan_test != 0) {
// CPLD should be: idcode=0x16d4a093, revision=0x1, part=0x6d4a, manufactor=0x049
if (((idcode >> 12) & 0xffff) == 0x6d4a && ((idcode >> 1) & 0x7ff) == 0x049)
internal_jtag_scan_test += 1;
else
internal_jtag_scan_test += 2;
} else {
printf("idcode=0x%08lx, revision=0x%01lx, part=0x%04lx, manufactor=0x%03lx\n", idcode,
(idcode >> 28) & 0xf, (idcode >> 12) & 0xffff, (idcode >> 1) & 0x7ff);
}
}
static void xpcu_report_status(struct libxsvf_host *h UNUSED, const char *message UNUSED)
{
// fprintf(stderr, "[STATUS] %s\n", message);
}
static void xpcu_report_error(struct libxsvf_host *h UNUSED, const char *file, int line, const char *message)
{
fprintf(stderr, "[%s:%d] %s\n", file, line, message);
}
static void *xpcu_realloc(struct libxsvf_host *h UNUSED, void *ptr, int size, enum libxsvf_mem which UNUSED)
{
return realloc(ptr, size);
}
static struct libxsvf_host h = {
.udelay = xpcu_udelay,
.setup = xpcu_setup,
.shutdown = xpcu_shutdown,
.getbyte = xpcu_getbyte,
.pulse_tck = xpcu_pulse_tck,
.sync = xpcu_sync,
.set_frequency = xpcu_set_frequency,
.report_tapstate = xpcu_report_tapstate,
.report_device = xpcu_report_device,
.report_status = xpcu_report_status,
.report_error = xpcu_report_error,
.realloc = xpcu_realloc
};
const char *progname;
static void help()
{
fprintf(stderr, "\n");
fprintf(stderr, "A JTAG SVF/XSVF Player based on libxsvf for the Xilinx Platform Cable USB\n");
fprintf(stderr, "\n");
fprintf(stderr, "xsvftool-xpcu, part of Lib(X)SVF (http://www.clifford.at/libxsvf/).\n");
fprintf(stderr, "Copyright (C) 2011 RIEGL Research ForschungsGmbH\n");
fprintf(stderr, "Copyright (C) 2011 Clifford Wolf <clifford@clifford.at>\n");
fprintf(stderr, "Lib(X)SVF is free software licensed under the ISC license.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -L | -B ] [ -d <vendor>:<device> | -D <device_file> ] [ -f kHz ] [ -A ] [ -P ]\n", progname);
fprintf(stderr, " %*s { -E | -p | -s svf-file | -x xsvf-file | -c } ...\n", (int)strlen(progname), "");
fprintf(stderr, "\n");
fprintf(stderr, " -L, -B\n");
fprintf(stderr, " Print RMASK bits as hex value (little or big endian)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -d <vendor>:<device>\n");
fprintf(stderr, " Open the device with this USB vendor and device ID.\n");
fprintf(stderr, " (default: 03fd:000d and 04b4:8613\n");
fprintf(stderr, "\n");
fprintf(stderr, " -D <device_file>\n");
fprintf(stderr, " Open this USB device (usually something like /dev/bus/usb/012/345)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -f kHz\n");
fprintf(stderr, " Run probe with the specified frequency (default=6000, max=24000)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -A\n");
fprintf(stderr, " Use full asynchonous error checking\n");
fprintf(stderr, " (very fast but error reporting might be delayed)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -P\n");
fprintf(stderr, " Use CPLD on probe as target device\n");
fprintf(stderr, "\n");
fprintf(stderr, " -p\n");
fprintf(stderr, " Force (re-)programming the CPLD on the probe\n");
fprintf(stderr, "\n");
fprintf(stderr, " -E\n");
fprintf(stderr, " Erase the CPLD on the probe\n");
fprintf(stderr, "\n");
fprintf(stderr, " -s svf-file\n");
fprintf(stderr, " Play the specified SVF file\n");
fprintf(stderr, "\n");
fprintf(stderr, " -x xsvf-file\n");
fprintf(stderr, " Play the specified XSVF file\n");
fprintf(stderr, "\n");
fprintf(stderr, " -c\n");
fprintf(stderr, " List devices in JTAG chain\n");
fprintf(stderr, "\n");
exit(1);
}
int main(int argc, char **argv)
{
int rc = 0;
int gotaction = 0;
int opt, i, j;
int done_initialization = 0;
progname = argc >= 1 ? argv[0] : "xsvftool-xpcu";
while ((opt = getopt(argc, argv, "LBd:D:f:APpEs:x:c")) != -1)
{
if (!done_initialization && (opt == 'p' || opt == 'E' || opt == 's' || opt == 'x' || opt == 'c'))
{
usb_init();
usb_find_busses();
usb_find_devices();
fx2usb = fx2usb_open(usb_vendor_id, usb_device_id, usb_device_file);
if (fx2usb == NULL) {
fprintf(stderr, "Failed to find or open USB device!\n");
exit(1);
}
CHECK(fx2usb_claim(fx2usb), == 0);
FILE *ihexf = CHECK_PTR(fmemopen(firmware_ihx, sizeof(firmware_ihx), "r"), != NULL);
CHECK(fx2usb_upload_ihex(fx2usb, ihexf), == 0);
CHECK(fclose(ihexf), == 0);
i = mode_internal_cpld;
mode_internal_cpld = 1;
internal_jtag_scan_test = 1;
libxsvf_play(&h, LIBXSVF_MODE_SCAN);
if (internal_jtag_scan_test != 2) {
fprintf(stderr, "Probe (device %s on bus %s) failed internal JTAG scan test!\n",
usb_device(fx2usb)->filename, usb_device(fx2usb)->bus->dirname);
exit(1);
}
mode_internal_cpld = i;
internal_jtag_scan_test = 0;
fprintf(stderr, "Connected to probe (device %s on bus %s) and passed internal JTAG scan test.\n",
usb_device(fx2usb)->filename, usb_device(fx2usb)->bus->dirname);
if (opt != 'p' && opt != 'E' && !mode_internal_cpld) {
fx2usb_command("C");
if (memcmp(correct_cksum, fx2usb_retbuf, 6)) {
fprintf(stderr, "Mismatch in CPLD checksum (is=%.6s, should=%s): reprogramming CPLD on probe..\n",
fx2usb_retbuf, correct_cksum);
i = mode_internal_cpld;
mode_internal_cpld = 1;
file_fp = CHECK_PTR(fmemopen(hardware_svf, sizeof(hardware_svf), "r"), != NULL);
libxsvf_play(&h, LIBXSVF_MODE_SVF);
mode_internal_cpld = i;
fclose(file_fp);
}
}
done_initialization = 1;
}
switch (opt)
{
case 'L':
mode_hex_rmask = 1;
break;
case 'B':
mode_hex_rmask = 2;
break;
case 'd':
if (usb_vendor_id || usb_device_id || usb_device_file || fx2usb)
help();
if (sscanf(optarg, "%x:%x", &usb_vendor_id, &usb_device_id) != 2)
help();
break;
case 'D':
if (usb_vendor_id || usb_device_id || usb_device_file || fx2usb)
help();
usb_device_file = strdup(optarg);
break;
case 'f':
mode_frequency = atoi(optarg);
break;
case 'P':
mode_internal_cpld = 1;
break;
case 'A':
mode_async_check = 1;
break;
case 'p':
case 'E':
gotaction = 1;
i = mode_internal_cpld;
mode_internal_cpld = 1;
if (opt == 'p') {
file_fp = CHECK_PTR(fmemopen(hardware_svf, sizeof(hardware_svf), "r"), != NULL);
fprintf(stderr, "(Re-)programming CPLD on the probe..\n");
} else {
file_fp = CHECK_PTR(fmemopen(erasecpld_svf, sizeof(erasecpld_svf), "r"), != NULL);
fprintf(stderr, "Erasing CPLD on the probe..\n");
}
libxsvf_play(&h, LIBXSVF_MODE_SVF);
mode_internal_cpld = i;
fclose(file_fp);
break;
case 'x':
case 's':
gotaction = 1;
if (!strcmp(optarg, "-"))
file_fp = stdin;
else
file_fp = fopen(optarg, "rb");
if (file_fp == NULL) {
fprintf(stderr, "Can't open %s file `%s': %s\n", opt == 's' ? "SVF" : "XSVF", optarg, strerror(errno));
rc = 1;
break;
}
fprintf(stderr, "Playing %s file `%s'..\n", opt == 's' ? "SVF" : "XSVF", optarg);
if (libxsvf_play(&h, opt == 's' ? LIBXSVF_MODE_SVF : LIBXSVF_MODE_XSVF) < 0) {
fprintf(stderr, "Error while playing %s file `%s'.\n", opt == 's' ? "SVF" : "XSVF", optarg);
rc = 1;
}
if (strcmp(optarg, "-"))
fclose(file_fp);
break;
case 'c':
gotaction = 1;
fprintf(stderr, "Scanning JTAG chain..\n");
if (libxsvf_play(&h, LIBXSVF_MODE_SCAN) < 0) {
fprintf(stderr, "Error while scanning JTAG chain.\n");
rc = 1;
}
break;
default:
help();
break;
}
}
if (!gotaction)
help();
if (rmask_bits > 0) {
fprintf(stderr, "Total number of rmask bits acquired: %d\n", rmask_bits);
if (mode_hex_rmask) {
printf("0x");
for (i = 0; i < rmask_bits; i += 4) {
int val = 0;
for (j = i; j < i + 4; j++) {
int pos = mode_hex_rmask > 1 ? j : rmask_bits - j - 1;
val = (val << 1) | (rmask_data[pos/8] & (1 << (pos%8)) ? 1 : 0);
}
printf("%x", val);
}
} else {
for (i = 0; i < rmask_bits; i++)
putchar((rmask_data[i / 8] & (1 << (i % 8))) != 0 ? '1' : '0');
}
putchar('\n');
}
if (done_initialization) {
fx2usb_command("X");
fx2usb_release(fx2usb);
usb_close(fx2usb);
}
fprintf(stderr, "Total number of JTAG clock cycles performed: %d\n", tck_cycle_count);
if (rc == 0)
fprintf(stderr, "READY.\n");
else
fprintf(stderr, "TERMINATED WITH ERROR(s)! (see above)\n");
return rc;
}