summaryrefslogtreecommitdiffstats
path: root/fpga/xilinx/programmer/dependencies/libxsvf/xsvftool-xpcu.src/xsvftool-xpcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/xilinx/programmer/dependencies/libxsvf/xsvftool-xpcu.src/xsvftool-xpcu.c')
-rw-r--r--fpga/xilinx/programmer/dependencies/libxsvf/xsvftool-xpcu.src/xsvftool-xpcu.c720
1 files changed, 720 insertions, 0 deletions
diff --git a/fpga/xilinx/programmer/dependencies/libxsvf/xsvftool-xpcu.src/xsvftool-xpcu.c b/fpga/xilinx/programmer/dependencies/libxsvf/xsvftool-xpcu.src/xsvftool-xpcu.c
new file mode 100644
index 0000000..b76e2d8
--- /dev/null
+++ b/fpga/xilinx/programmer/dependencies/libxsvf/xsvftool-xpcu.src/xsvftool-xpcu.c
@@ -0,0 +1,720 @@
+/*
+ * 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;
+}
+