Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/clujtag-client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2015-01-05 03:33:41 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2015-01-05 03:33:41 +0300
commit9ac4d1d996ee1700b033293a75472d1b7d6b9fbe (patch)
treecdc4dc0b3fb5993df052378bb593c8abaa0cde12
First commit
-rw-r--r--COPYING18
-rw-r--r--Makefile17
-rw-r--r--clujtag.c475
-rw-r--r--jtag_commands.h10
-rw-r--r--libxsvf.h141
-rw-r--r--memname.c65
-rw-r--r--play.c72
-rw-r--r--scan.c58
-rw-r--r--statename.c46
-rw-r--r--svf.c690
-rw-r--r--tap.c173
-rw-r--r--xsvf.c516
12 files changed, 2281 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..daa098d
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,18 @@
+
+Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+
+Copyright (C) 2009 RIEGL Research ForschungsGmbH
+Copyright (C) 2009 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.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5cfd46f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+CC=gcc
+CFLAGS=-c -Wall -O2
+LDFLAGS=
+SOURCES=clujtag.c xsvf.c svf.c play.c memname.c scan.c statename.c tap.c
+OBJECTS=$(SOURCES:.c=.o)
+EXECUTABLE=clujtag.exe
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) -o $@
+
+.c.o:
+ $(CC) $(CFLAGS) $< -o $@
+
+clean:
+ rm -rf *.o $(EXECUTABLE)
diff --git a/clujtag.c b/clujtag.c
new file mode 100644
index 0000000..d3be723
--- /dev/null
+++ b/clujtag.c
@@ -0,0 +1,475 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Cluster <clusterrr@clusterrr.com>
+ *
+ * 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.
+ *
+ */
+#ifdef __MINGW32__
+#define WINDOWS
+#endif
+
+#include "libxsvf.h"
+#include "jtag_commands.h"
+
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <fcntl.h>
+#ifdef WINDOWS
+#include <windows.h>
+#else
+#include <termios.h>
+#endif
+
+#ifdef WINDOWS
+static void write_port(HANDLE portHandle, uint8_t data)
+{
+ DWORD writed = 0;
+ if (WriteFile(portHandle, &data, sizeof(data), &writed, NULL) && (writed == 1)) return;
+ int error = GetLastError();
+ fprintf(stderr, "Write error: %d\r\n", error);
+ exit(1);
+}
+#else
+static void write_port(int portHandle, uint8_t data)
+{
+ int res;
+ do
+ {
+ res = write(portHandle, &data, 1);
+ if (res == -1) usleep(10);
+ } while (res == -1 && errno == EAGAIN);
+ if (res == -1)
+ {
+ perror("Write error");
+ exit(1);
+ }
+}
+#endif
+
+#ifdef WINDOWS
+static uint8_t read_port(HANDLE portHandle)
+{
+ uint8_t buffer;
+ DWORD read = 0;
+ if (ReadFile(portHandle, &buffer, 1, &read, NULL) && (read == 1)) return buffer;
+ fprintf(stderr, "Read error: %d\r\n", (int)GetLastError());
+ exit(1);
+}
+#else
+static uint8_t read_port(int portHandle)
+{
+ uint8_t data;
+ int res, t = 0;
+ const int timeout = 5000;
+ do
+ {
+ res = read(portHandle, &data, 1);
+ t++;
+ if (res == 0) usleep(10);
+ }
+ while ((res == 0) && (t < timeout));
+ if (t == timeout)
+ {
+ printf("Read timeout\n");
+ exit(1);
+ }
+ if (res == 1) return data;
+ perror("Read error");
+ exit(1);
+}
+#endif
+
+struct udata_s {
+ char comPort[512];
+#ifdef WINDOWS
+ HANDLE portHandle;
+#else
+ int portHandle;
+#endif
+ FILE *f;
+ int verbose;
+};
+
+static int h_setup(struct libxsvf_host *h)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 2) {
+ fprintf(stderr, "[SETUP]\n");
+ fflush(stderr);
+ }
+
+#ifdef WINDOWS
+
+ char devicePath[50];
+ sprintf(devicePath, "\\\\.\\%s", u->comPort);
+
+ HANDLE mHandle = CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,/* FILE_FLAG_OVERLAPPED*/0, NULL);
+ if (mHandle == INVALID_HANDLE_VALUE)
+ {
+ fprintf(stderr, "Can't open serial port %s\r\n", u->comPort);
+ return -1;
+ }
+
+ DCB dcb;
+
+ FillMemory(&dcb, sizeof(dcb), 0);
+ if (!GetCommState(mHandle, &dcb)) // get current DCB
+ {
+ fprintf(stderr, "Can't get DCB\r\n");
+ return -1;
+ }
+
+ dcb.BaudRate = CBR_256000;
+
+ if (!SetCommState(mHandle, &dcb))
+ {
+ fprintf(stderr, "Can't set serial port settings\r\n");
+ return -1;
+ }
+
+ u->portHandle = mHandle;
+
+#else
+
+ int fd;
+ struct termios options;
+ fd = open(u->comPort, O_RDWR | O_NOCTTY);
+ if (fd == -1)
+ {
+ perror("Can't open serial port");
+ return -1;
+ }
+
+ fcntl(fd, F_SETFL, FNDELAY);
+
+ bzero(&options, sizeof(options));
+ options.c_cflag = B230400 | CS8 | CLOCAL | CREAD;
+ options.c_iflag = IGNPAR;
+ options.c_oflag = 0;
+ cfsetispeed(&options, B230400);
+ cfsetospeed(&options, B230400);
+ tcsetattr(fd, TCSANOW, &options);
+ tcflush(fd, TCIFLUSH);
+ u->portHandle = fd;
+
+#endif
+
+ // Reset device
+ write_port(u->portHandle, 0xFF);
+ // Setup JTAG port
+ write_port(u->portHandle,JTAG_SETUP);
+
+ return 0;
+}
+
+static int h_shutdown(struct libxsvf_host *h)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 2) {
+ fprintf(stderr, "[SHUTDOWN]\n");
+ fflush(stderr);
+ }
+
+ if (u->portHandle)
+ {
+ write_port(u->portHandle, JTAG_SHUTDOWN);
+#ifdef WINDOWS
+ CloseHandle(u->portHandle);
+#else
+ close(u->portHandle);
+#endif
+ }
+
+ return 0;
+}
+
+static void h_udelay(struct libxsvf_host *h, long usecs, int tms, long num_tck)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 3) {
+ fprintf(stderr, "[DELAY:%ld, TMS:%d, NUM_TCK:%ld]\n", usecs, tms, num_tck);
+ fflush(stderr);
+ }
+ if (num_tck > 0) {
+ struct timeval tv1, tv2;
+ gettimeofday(&tv1, NULL);
+ write_port(u->portHandle, JTAG_PULSE_TCK_DELAY);
+ write_port(u->portHandle, tms);
+ write_port(u->portHandle, num_tck);
+
+ gettimeofday(&tv2, NULL);
+ if (tv2.tv_sec > tv1.tv_sec) {
+ usecs -= (1000000 - tv1.tv_usec) + (tv2.tv_sec - tv1.tv_sec - 1) * 1000000;
+ tv1.tv_usec = 0;
+ }
+ usecs -= tv2.tv_usec - tv1.tv_usec;
+ if (u->verbose >= 3) {
+ fprintf(stderr, "[DELAY_AFTER_TCK:%ld]\n", usecs > 0 ? usecs : 0);
+ fflush(stderr);
+ }
+ }
+ if (usecs > 0) {
+ usleep(usecs);
+ }
+}
+
+static int h_getbyte(struct libxsvf_host *h)
+{
+ struct udata_s *u = h->user_data;
+ return fgetc(u->f);
+}
+
+static int h_pulse_tck(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync)
+{
+ struct udata_s *u = h->user_data;
+ uint8_t data = 0;
+ if (tms) data |= 1;
+ if (tdi) data |= (1<<1);
+ write_port(u->portHandle, JTAG_PULSE_TCK);
+ write_port(u->portHandle, data);
+ int line_tdo = read_port(u->portHandle);
+ int rc = line_tdo >= 0 ? line_tdo : 0;
+
+ if (tdo >= 0 && line_tdo >= 0) {
+ if (tdo != line_tdo)
+ rc = -1;
+ }
+
+ if (u->verbose >= 4) {
+ fprintf(stderr, "[TMS:%d, TDI:%d, TDO_ARG:%d, TDO_LINE:%d, RMASK:%d, RC:%d]\n", tms, tdi, tdo, line_tdo, rmask, rc);
+ }
+
+ return rc;
+}
+
+
+static int h_pulse_tck_multi(struct libxsvf_host *h, unsigned char* data, unsigned char count)
+{
+ struct udata_s *u = h->user_data;
+ write_port(u->portHandle, JTAG_PULSE_TCK_MULTI);
+ write_port(u->portHandle, count);
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ write_port(u->portHandle, data[i]);
+ }
+ if (u->verbose >= 4) {
+ fprintf(stderr, "[MULTI TCK: %d bits]\n", count);
+ fprintf(stderr, "[TMS:%d, TDI:%d, TDO:%d]\n", data[i]&1, (data[i]>>1)&1 ? (data[i]>>2)&1 : -1, (data[i]>>3)&1 ? (data[i]>>4)&1 : -1);
+ }
+ int result = read_port(u->portHandle);
+ if (!result) return -1;
+ return 0;
+}
+
+static void h_pulse_sck(struct libxsvf_host *h)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 4) {
+ fprintf(stderr, "[SCK]\n");
+ }
+ write_port(u->portHandle, JTAG_PULSE_SCK);
+}
+
+static void h_set_trst(struct libxsvf_host *h, int v)
+{
+ // Maybe I'll support it later
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 4) {
+ fprintf(stderr, "[TRST:%d]\n", v);
+ }
+}
+
+static int h_set_frequency(struct libxsvf_host *h, int v)
+{
+ fprintf(stderr, "WARNING: Setting JTAG clock frequency to %d ignored!\n", v);
+ return 0;
+}
+
+static void h_report_tapstate(struct libxsvf_host *h)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 3) {
+ fprintf(stderr, "[%s]\n", libxsvf_state2str(h->tap_state));
+ }
+}
+
+static void h_report_device(struct libxsvf_host *h, unsigned long idcode)
+{
+ 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 h_report_status(struct libxsvf_host *h, const char *message)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 2) {
+ fprintf(stderr, "[STATUS] %s\n", message);
+ }
+}
+
+static void h_report_error(struct libxsvf_host *h, const char *file, int line, const char *message)
+{
+ fprintf(stderr, "[%s:%d] %s\n", file, line, message);
+}
+
+static void *h_realloc(struct libxsvf_host *h, void *ptr, int size, enum libxsvf_mem which)
+{
+ struct udata_s *u = h->user_data;
+ if (u->verbose >= 3) {
+ fprintf(stderr, "[REALLOC:%s:%d]\n", libxsvf_mem2str(which), size);
+ }
+ return realloc(ptr, size);
+}
+
+static struct udata_s u;
+
+static struct libxsvf_host h = {
+ .udelay = h_udelay,
+ .setup = h_setup,
+ .shutdown = h_shutdown,
+ .getbyte = h_getbyte,
+ .pulse_tck = h_pulse_tck,
+ .pulse_tck_multi = h_pulse_tck_multi,
+ .pulse_sck = h_pulse_sck,
+ .set_trst = h_set_trst,
+ .set_frequency = h_set_frequency,
+ .report_tapstate = h_report_tapstate,
+ .report_device = h_report_device,
+ .report_status = h_report_status,
+ .report_error = h_report_error,
+ .realloc = h_realloc,
+ .user_data = &u
+};
+
+const char *progname;
+
+static void copyleft()
+{
+ static int already_printed = 0;
+ if (already_printed)
+ return;
+ fprintf(stderr, "xsvftool-clujtag\n");
+ fprintf(stderr, "Copyright (C) 2009 RIEGL Research ForschungsGmbH\n");
+ fprintf(stderr, "Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>\n");
+ fprintf(stderr, "Copyright (C) 2014 Cluster <clusterrr@clusterrr.com>\n");
+ fprintf(stderr, "Lib(X)SVF is free software licensed under the ISC license.\n");
+ already_printed = 1;
+}
+
+static void help()
+{
+ copyleft();
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Usage: %s [ -v ... ] { -s svf-file | -x xsvf-file | -c }\n", progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -p portname\n");
+ fprintf(stderr, " Use then specified COM port (default is COM14)\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -v, -vv, -vvv, -vvvv\n");
+ fprintf(stderr, " Verbose, more verbose and even more verbose\n");
+ fprintf(stderr, "\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;
+
+ strcpy(u.comPort, "COM14");
+ u.portHandle = 0;
+
+ progname = argc >= 1 ? argv[0] : "xvsftool";
+ while ((opt = getopt(argc, argv, "vp:x:s:c")) != -1)
+ {
+ switch (opt)
+ {
+ case 'v':
+ copyleft();
+ u.verbose++;
+ break;
+ case 'p':
+ strncpy(u.comPort, optarg, sizeof(u.comPort)-1);
+ u.comPort[sizeof(u.comPort)-1] = 0;
+ break;
+ case 'x':
+ case 's':
+ gotaction = 1;
+ if (u.verbose)
+ fprintf(stderr, "Playing %s file `%s'.\n", opt == 's' ? "SVF" : "XSVF", optarg);
+ if (!strcmp(optarg, "-"))
+ u.f = stdin;
+ else
+ u.f = fopen(optarg, "rb");
+ if (u.f == NULL) {
+ fprintf(stderr, "Can't open %s file `%s': %s\n", opt == 's' ? "SVF" : "XSVF", optarg, strerror(errno));
+ rc = 1;
+ break;
+ }
+ 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(u.f);
+ break;
+ case 'c':
+ gotaction = 1;
+ 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 (u.verbose) {
+ if (rc == 0) {
+ fprintf(stderr, "Done!\n");
+ } else {
+ fprintf(stderr, "Finished with errors!\n");
+ }
+ }
+
+
+ exit(rc);
+}
+
diff --git a/jtag_commands.h b/jtag_commands.h
new file mode 100644
index 0000000..39b6837
--- /dev/null
+++ b/jtag_commands.h
@@ -0,0 +1,10 @@
+#define JTAG_SETUP 1
+#define JTAG_SHUTDOWN 2
+//#define JTAG_SET_TMS 3
+//#define JTAG_SET_TCK 4
+//#define JTAG_GET_TDO 5
+//#define JTAG_SET_TDI 6
+#define JTAG_PULSE_TCK 7
+#define JTAG_PULSE_SCK 8
+#define JTAG_PULSE_TCK_DELAY 9
+#define JTAG_PULSE_TCK_MULTI 10
diff --git a/libxsvf.h b/libxsvf.h
new file mode 100644
index 0000000..a430f32
--- /dev/null
+++ b/libxsvf.h
@@ -0,0 +1,141 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#ifndef LIBXSVF_H
+#define LIBXSVF_H
+
+enum libxsvf_mode {
+ LIBXSVF_MODE_SVF = 1,
+ LIBXSVF_MODE_XSVF = 2,
+ LIBXSVF_MODE_SCAN = 3
+};
+
+enum libxsvf_tap_state {
+ /* Special States */
+ LIBXSVF_TAP_INIT = 0,
+ LIBXSVF_TAP_RESET = 1,
+ LIBXSVF_TAP_IDLE = 2,
+ /* DR States */
+ LIBXSVF_TAP_DRSELECT = 3,
+ LIBXSVF_TAP_DRCAPTURE = 4,
+ LIBXSVF_TAP_DRSHIFT = 5,
+ LIBXSVF_TAP_DREXIT1 = 6,
+ LIBXSVF_TAP_DRPAUSE = 7,
+ LIBXSVF_TAP_DREXIT2 = 8,
+ LIBXSVF_TAP_DRUPDATE = 9,
+ /* IR States */
+ LIBXSVF_TAP_IRSELECT = 10,
+ LIBXSVF_TAP_IRCAPTURE = 11,
+ LIBXSVF_TAP_IRSHIFT = 12,
+ LIBXSVF_TAP_IREXIT1 = 13,
+ LIBXSVF_TAP_IRPAUSE = 14,
+ LIBXSVF_TAP_IREXIT2 = 15,
+ LIBXSVF_TAP_IRUPDATE = 16
+};
+
+enum libxsvf_mem {
+ LIBXSVF_MEM_XSVF_TDI_DATA = 0,
+ LIBXSVF_MEM_XSVF_TDO_DATA = 1,
+ LIBXSVF_MEM_XSVF_TDO_MASK = 2,
+ LIBXSVF_MEM_XSVF_ADDR_MASK = 3,
+ LIBXSVF_MEM_XSVF_DATA_MASK = 4,
+ LIBXSVF_MEM_SVF_COMMANDBUF = 5,
+ LIBXSVF_MEM_SVF_SDR_TDI_DATA = 6,
+ LIBXSVF_MEM_SVF_SDR_TDI_MASK = 7,
+ LIBXSVF_MEM_SVF_SDR_TDO_DATA = 8,
+ LIBXSVF_MEM_SVF_SDR_TDO_MASK = 9,
+ LIBXSVF_MEM_SVF_SDR_RET_MASK = 10,
+ LIBXSVF_MEM_SVF_SIR_TDI_DATA = 11,
+ LIBXSVF_MEM_SVF_SIR_TDI_MASK = 12,
+ LIBXSVF_MEM_SVF_SIR_TDO_DATA = 13,
+ LIBXSVF_MEM_SVF_SIR_TDO_MASK = 14,
+ LIBXSVF_MEM_SVF_SIR_RET_MASK = 15,
+ LIBXSVF_MEM_SVF_HDR_TDI_DATA = 16,
+ LIBXSVF_MEM_SVF_HDR_TDI_MASK = 17,
+ LIBXSVF_MEM_SVF_HDR_TDO_DATA = 18,
+ LIBXSVF_MEM_SVF_HDR_TDO_MASK = 19,
+ LIBXSVF_MEM_SVF_HDR_RET_MASK = 20,
+ LIBXSVF_MEM_SVF_HIR_TDI_DATA = 21,
+ LIBXSVF_MEM_SVF_HIR_TDI_MASK = 22,
+ LIBXSVF_MEM_SVF_HIR_TDO_DATA = 23,
+ LIBXSVF_MEM_SVF_HIR_TDO_MASK = 24,
+ LIBXSVF_MEM_SVF_HIR_RET_MASK = 25,
+ LIBXSVF_MEM_SVF_TDR_TDI_DATA = 26,
+ LIBXSVF_MEM_SVF_TDR_TDI_MASK = 27,
+ LIBXSVF_MEM_SVF_TDR_TDO_DATA = 28,
+ LIBXSVF_MEM_SVF_TDR_TDO_MASK = 29,
+ LIBXSVF_MEM_SVF_TDR_RET_MASK = 30,
+ LIBXSVF_MEM_SVF_TIR_TDI_DATA = 31,
+ LIBXSVF_MEM_SVF_TIR_TDI_MASK = 32,
+ LIBXSVF_MEM_SVF_TIR_TDO_DATA = 33,
+ LIBXSVF_MEM_SVF_TIR_TDO_MASK = 34,
+ LIBXSVF_MEM_SVF_TIR_RET_MASK = 35,
+ LIBXSVF_MEM_NUM = 36
+};
+
+struct libxsvf_host {
+ int (*setup)(struct libxsvf_host *h);
+ int (*shutdown)(struct libxsvf_host *h);
+ void (*udelay)(struct libxsvf_host *h, long usecs, int tms, long num_tck);
+ int (*getbyte)(struct libxsvf_host *h);
+ int (*sync)(struct libxsvf_host *h);
+ int (*pulse_tck)(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync);
+ int (*pulse_tck_multi)(struct libxsvf_host *h, unsigned char* data, unsigned char count);
+ void (*pulse_sck)(struct libxsvf_host *h);
+ void (*set_trst)(struct libxsvf_host *h, int v);
+ int (*set_frequency)(struct libxsvf_host *h, int v);
+ void (*report_tapstate)(struct libxsvf_host *h);
+ void (*report_device)(struct libxsvf_host *h, unsigned long idcode);
+ void (*report_status)(struct libxsvf_host *h, const char *message);
+ void (*report_error)(struct libxsvf_host *h, const char *file, int line, const char *message);
+ void *(*realloc)(struct libxsvf_host *h, void *ptr, int size, enum libxsvf_mem which);
+ enum libxsvf_tap_state tap_state;
+ void *user_data;
+};
+
+int libxsvf_play(struct libxsvf_host *, enum libxsvf_mode mode);
+const char *libxsvf_state2str(enum libxsvf_tap_state tap_state);
+const char *libxsvf_mem2str(enum libxsvf_mem which);
+
+/* Internal API */
+int libxsvf_svf(struct libxsvf_host *h);
+int libxsvf_xsvf(struct libxsvf_host *h);
+int libxsvf_scan(struct libxsvf_host *h);
+int libxsvf_tap_walk(struct libxsvf_host *, enum libxsvf_tap_state);
+
+/* Host accessor macros (see README) */
+#define LIBXSVF_HOST_SETUP() h->setup(h)
+#define LIBXSVF_HOST_SHUTDOWN() h->shutdown(h)
+#define LIBXSVF_HOST_UDELAY(_usecs, _tms, _num_tck) h->udelay(h, _usecs, _tms, _num_tck)
+#define LIBXSVF_HOST_GETBYTE() h->getbyte(h)
+#define LIBXSVF_HOST_SYNC() (h->sync ? h->sync(h) : 0)
+#define LIBXSVF_HOST_PULSE_TCK(_tms, _tdi, _tdo, _rmask, _sync) h->pulse_tck(h, _tms, _tdi, _tdo, _rmask, _sync)
+#define LIBXSVF_HOST_PULSE_TCK_MULTI(_data, _count) h->pulse_tck_multi(h, _data, _count)
+#define LIBXSVF_HOST_PULSE_SCK() do { if (h->pulse_sck) h->pulse_sck(h); } while (0)
+#define LIBXSVF_HOST_SET_TRST(_v) do { if (h->set_trst) h->set_trst(h, _v); } while (0)
+#define LIBXSVF_HOST_SET_FREQUENCY(_v) (h->set_frequency ? h->set_frequency(h, _v) : -1)
+#define LIBXSVF_HOST_REPORT_TAPSTATE() do { if (h->report_tapstate) h->report_tapstate(h); } while (0)
+#define LIBXSVF_HOST_REPORT_DEVICE(_v) do { if (h->report_device) h->report_device(h, _v); } while (0)
+#define LIBXSVF_HOST_REPORT_STATUS(_msg) do { if (h->report_status) h->report_status(h, _msg); } while (0)
+#define LIBXSVF_HOST_REPORT_ERROR(_msg) h->report_error(h, __FILE__, __LINE__, _msg)
+#define LIBXSVF_HOST_REALLOC(_ptr, _size, _which) h->realloc(h, _ptr, _size, _which)
+
+#endif
+
diff --git a/memname.c b/memname.c
new file mode 100644
index 0000000..0cc3f31
--- /dev/null
+++ b/memname.c
@@ -0,0 +1,65 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+const char *libxsvf_mem2str(enum libxsvf_mem which)
+{
+#define X(_w, _t) if (which == LIBXSVF_MEM_ ## _w) return #_t;
+ X(XSVF_TDI_DATA, xsvf_tdi_data)
+ X(XSVF_TDO_DATA, xsvf_tdo_data)
+ X(XSVF_TDO_MASK, xsvf_tdo_mask)
+ X(XSVF_ADDR_MASK, xsvf_addr_mask)
+ X(XSVF_DATA_MASK, xsvf_data_mask)
+ X(SVF_COMMANDBUF, svf_commandbuf)
+ X(SVF_HDR_TDI_DATA, svf_hdr_tdi_data)
+ X(SVF_HDR_TDI_MASK, svf_hdr_tdi_mask)
+ X(SVF_HDR_TDO_DATA, svf_hdr_tdo_data)
+ X(SVF_HDR_TDO_MASK, svf_hdr_tdo_mask)
+ X(SVF_HDR_RET_MASK, svf_hdr_ret_mask)
+ X(SVF_HIR_TDI_DATA, svf_hir_tdi_data)
+ X(SVF_HIR_TDI_MASK, svf_hir_tdi_mask)
+ X(SVF_HIR_TDO_DATA, svf_hir_tdo_data)
+ X(SVF_HIR_TDO_MASK, svf_hir_tdo_mask)
+ X(SVF_HIR_RET_MASK, svf_hir_ret_mask)
+ X(SVF_TDR_TDI_DATA, svf_tdr_tdi_data)
+ X(SVF_TDR_TDI_MASK, svf_tdr_tdi_mask)
+ X(SVF_TDR_TDO_DATA, svf_tdr_tdo_data)
+ X(SVF_TDR_TDO_MASK, svf_tdr_tdo_mask)
+ X(SVF_TDR_RET_MASK, svf_tdr_ret_mask)
+ X(SVF_TIR_TDI_DATA, svf_tir_tdi_data)
+ X(SVF_TIR_TDI_MASK, svf_tir_tdi_mask)
+ X(SVF_TIR_TDO_DATA, svf_tir_tdo_data)
+ X(SVF_TIR_TDO_MASK, svf_tir_tdo_mask)
+ X(SVF_TIR_RET_MASK, svf_tir_ret_mask)
+ X(SVF_SDR_TDI_DATA, svf_sdr_tdi_data)
+ X(SVF_SDR_TDI_MASK, svf_sdr_tdi_mask)
+ X(SVF_SDR_TDO_DATA, svf_sdr_tdo_data)
+ X(SVF_SDR_TDO_MASK, svf_sdr_tdo_mask)
+ X(SVF_SDR_RET_MASK, svf_sdr_ret_mask)
+ X(SVF_SIR_TDI_DATA, svf_sir_tdi_data)
+ X(SVF_SIR_TDI_MASK, svf_sir_tdi_mask)
+ X(SVF_SIR_TDO_DATA, svf_sir_tdo_data)
+ X(SVF_SIR_TDO_MASK, svf_sir_tdo_mask)
+ X(SVF_SIR_RET_MASK, svf_sir_ret_mask)
+#undef X
+ return (void*)0;
+}
+
diff --git a/play.c b/play.c
new file mode 100644
index 0000000..e57c01e
--- /dev/null
+++ b/play.c
@@ -0,0 +1,72 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+int libxsvf_play(struct libxsvf_host *h, enum libxsvf_mode mode)
+{
+ int rc = -1;
+
+ h->tap_state = LIBXSVF_TAP_INIT;
+ if (LIBXSVF_HOST_SETUP() < 0) {
+ LIBXSVF_HOST_REPORT_ERROR("Setup of JTAG interface failed.");
+ return -1;
+ }
+
+ if (mode == LIBXSVF_MODE_SVF) {
+#ifdef LIBXSVF_WITHOUT_SVF
+ LIBXSVF_HOST_REPORT_ERROR("SVF support in libxsvf is disabled.");
+#else
+ rc = libxsvf_svf(h);
+#endif
+ }
+
+ if (mode == LIBXSVF_MODE_XSVF) {
+#ifdef LIBXSVF_WITHOUT_XSVF
+ LIBXSVF_HOST_REPORT_ERROR("XSVF support in libxsvf is disabled.");
+#else
+ rc = libxsvf_xsvf(h);
+#endif
+ }
+
+ if (mode == LIBXSVF_MODE_SCAN) {
+#ifdef LIBXSVF_WITHOUT_SCAN
+ LIBXSVF_HOST_REPORT_ERROR("SCAN support in libxsvf is disabled.");
+#else
+ rc = libxsvf_scan(h);
+#endif
+ }
+
+ libxsvf_tap_walk(h, LIBXSVF_TAP_RESET);
+ if (LIBXSVF_HOST_SYNC() != 0 && rc >= 0 ) {
+ LIBXSVF_HOST_REPORT_ERROR("TDO mismatch in TAP reset. (this is not possible!)");
+ rc = -1;
+ }
+
+ int shutdown_rc = LIBXSVF_HOST_SHUTDOWN();
+
+ if (shutdown_rc < 0) {
+ LIBXSVF_HOST_REPORT_ERROR("Shutdown of JTAG interface failed.");
+ rc = rc < 0 ? rc : shutdown_rc;
+ }
+
+ return rc;
+}
+
diff --git a/scan.c b/scan.c
new file mode 100644
index 0000000..cb24e56
--- /dev/null
+++ b/scan.c
@@ -0,0 +1,58 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+int libxsvf_scan(struct libxsvf_host *h)
+{
+ int i, j;
+
+ if (libxsvf_tap_walk(h, LIBXSVF_TAP_RESET) < 0)
+ return -1;
+
+ if (libxsvf_tap_walk(h, LIBXSVF_TAP_DRSHIFT) < 0)
+ return -1;
+
+ for (i=0; i<256; i++)
+ {
+ int bit = LIBXSVF_HOST_PULSE_TCK(0, 1, -1, 0, 1);
+
+ if (bit < 0)
+ return -1;
+
+ if (bit == 0) {
+ LIBXSVF_HOST_REPORT_DEVICE(0);
+ } else {
+ unsigned long idcode = 1;
+ for (j=1; j<32; j++) {
+ int bit = LIBXSVF_HOST_PULSE_TCK(0, 1, -1, 0, 1);
+ if (bit < 0)
+ return -1;
+ idcode |= ((unsigned long)bit) << j;
+ }
+ if (idcode == 0xffffffff)
+ break;
+ LIBXSVF_HOST_REPORT_DEVICE(idcode);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/statename.c b/statename.c
new file mode 100644
index 0000000..128fb7f
--- /dev/null
+++ b/statename.c
@@ -0,0 +1,46 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+const char *libxsvf_state2str(enum libxsvf_tap_state tap_state)
+{
+#define X(_s) if (tap_state == _s) return #_s;
+ X(LIBXSVF_TAP_INIT)
+ X(LIBXSVF_TAP_RESET)
+ X(LIBXSVF_TAP_IDLE)
+ X(LIBXSVF_TAP_DRSELECT)
+ X(LIBXSVF_TAP_DRCAPTURE)
+ X(LIBXSVF_TAP_DRSHIFT)
+ X(LIBXSVF_TAP_DREXIT1)
+ X(LIBXSVF_TAP_DRPAUSE)
+ X(LIBXSVF_TAP_DREXIT2)
+ X(LIBXSVF_TAP_DRUPDATE)
+ X(LIBXSVF_TAP_IRSELECT)
+ X(LIBXSVF_TAP_IRCAPTURE)
+ X(LIBXSVF_TAP_IRSHIFT)
+ X(LIBXSVF_TAP_IREXIT1)
+ X(LIBXSVF_TAP_IRPAUSE)
+ X(LIBXSVF_TAP_IREXIT2)
+ X(LIBXSVF_TAP_IRUPDATE)
+#undef X
+ return "UNKOWN_STATE";
+}
+
diff --git a/svf.c b/svf.c
new file mode 100644
index 0000000..8c56bd9
--- /dev/null
+++ b/svf.c
@@ -0,0 +1,690 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+static int read_command(struct libxsvf_host *h, char **buffer_p, int *len_p)
+{
+ char *buffer = *buffer_p;
+ int braket_mode = 0;
+ int len = *len_p;
+ int p = 0;
+
+ while (1)
+ {
+ if (len < p+10) {
+ len = len < 64 ? 96 : len*2;
+ buffer = LIBXSVF_HOST_REALLOC(buffer, len, LIBXSVF_MEM_SVF_COMMANDBUF);
+ *buffer_p = buffer;
+ *len_p = len;
+ if (!buffer) {
+ LIBXSVF_HOST_REPORT_ERROR("Allocating memory failed.");
+ return -1;
+ }
+ }
+ buffer[p] = 0;
+
+ int ch = LIBXSVF_HOST_GETBYTE();
+ if (ch < 0) {
+handle_eof:
+ if (p == 0)
+ return 0;
+ LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF.");
+ return -1;
+ }
+ if (ch <= ' ') {
+insert_eol:
+ if (!braket_mode && p > 0 && buffer[p-1] != ' ')
+ buffer[p++] = ' ';
+ continue;
+ }
+ if (ch == '!') {
+skip_to_eol:
+ while (1) {
+ ch = LIBXSVF_HOST_GETBYTE();
+ if (ch < 0)
+ goto handle_eof;
+ if (ch < ' ' && ch != '\t')
+ goto insert_eol;
+ }
+ }
+ if (ch == '/' && p > 0 && buffer[p-1] == '/') {
+ p--;
+ goto skip_to_eol;
+ }
+ if (ch == ';')
+ break;
+ if (ch == '(') {
+ if (!braket_mode && p > 0 && buffer[p-1] != ' ')
+ buffer[p++] = ' ';
+ braket_mode++;
+ }
+ if (ch >= 'a' && ch <= 'z')
+ buffer[p++] = ch - ('a' - 'A');
+ else
+ buffer[p++] = ch;
+ if (ch == ')') {
+ braket_mode--;
+ if (!braket_mode)
+ buffer[p++] = ' ';
+ }
+ }
+ return 1;
+}
+
+static int strtokencmp(const char *str1, const char *str2)
+{
+ int i = 0;
+ while (1) {
+ if ((str1[i] == ' ' || str1[i] == 0) && (str2[i] == ' ' || str2[i] == 0))
+ return 0;
+ if (str1[i] < str2[i])
+ return -1;
+ if (str1[i] > str2[i])
+ return +1;
+ i++;
+ }
+}
+
+static int strtokenskip(const char *str1)
+{
+ int i = 0;
+ while (str1[i] != 0 && str1[i] != ' ') i++;
+ while (str1[i] == ' ') i++;
+ return i;
+}
+
+static int token2tapstate(const char *str1)
+{
+#define X(_t) if (!strtokencmp(str1, #_t)) return LIBXSVF_TAP_ ## _t;
+ X(RESET)
+ X(IDLE)
+ X(DRSELECT)
+ X(DRCAPTURE)
+ X(DRSHIFT)
+ X(DREXIT1)
+ X(DRPAUSE)
+ X(DREXIT2)
+ X(DRUPDATE)
+ X(IRSELECT)
+ X(IRCAPTURE)
+ X(IRSHIFT)
+ X(IREXIT1)
+ X(IRPAUSE)
+ X(IREXIT2)
+ X(IRUPDATE)
+#undef X
+ return -1;
+}
+
+struct bitdata_s {
+ int len, alloced_len;
+ int alloced_bytes;
+ unsigned char *tdi_data;
+ unsigned char *tdi_mask;
+ unsigned char *tdo_data;
+ unsigned char *tdo_mask;
+ unsigned char *ret_mask;
+ int has_tdo_data;
+};
+
+static void bitdata_free(struct libxsvf_host *h, struct bitdata_s *bd, int offset)
+{
+ LIBXSVF_HOST_REALLOC(bd->tdi_data, 0, offset+0);
+ LIBXSVF_HOST_REALLOC(bd->tdi_mask, 0, offset+1);
+ LIBXSVF_HOST_REALLOC(bd->tdo_data, 0, offset+2);
+ LIBXSVF_HOST_REALLOC(bd->tdo_mask, 0, offset+3);
+ LIBXSVF_HOST_REALLOC(bd->ret_mask, 0, offset+4);
+
+ bd->tdi_data = (void*)0;
+ bd->tdi_mask = (void*)0;
+ bd->tdo_data = (void*)0;
+ bd->tdo_mask = (void*)0;
+ bd->ret_mask = (void*)0;
+}
+
+static int hex(char ch)
+{
+ if (ch >= 'A' && ch <= 'Z')
+ return (ch - 'A') + 10;
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ return 0;
+}
+
+static const char *bitdata_parse(struct libxsvf_host *h, const char *p, struct bitdata_s *bd, int offset)
+{
+ int i, j;
+ bd->len = 0;
+ bd->has_tdo_data = 0;
+ while (*p >= '0' && *p <= '9') {
+ bd->len = bd->len * 10 + (*p - '0');
+ p++;
+ }
+ while (*p == ' ') {
+ p++;
+ }
+ if (bd->len != bd->alloced_len) {
+ bitdata_free(h, bd, offset);
+ bd->alloced_len = bd->len;
+ bd->alloced_bytes = (bd->len+7) / 8;
+ }
+ while (*p)
+ {
+ int memnum = 0;
+ unsigned char **dp = (void*)0;
+ if (!strtokencmp(p, "TDI")) {
+ p += strtokenskip(p);
+ dp = &bd->tdi_data;
+ memnum = 0;
+ }
+ if (!strtokencmp(p, "TDO")) {
+ p += strtokenskip(p);
+ dp = &bd->tdo_data;
+ bd->has_tdo_data = 1;
+ memnum = 1;
+ }
+ if (!strtokencmp(p, "SMASK")) {
+ p += strtokenskip(p);
+ dp = &bd->tdi_mask;
+ memnum = 2;
+ }
+ if (!strtokencmp(p, "MASK")) {
+ p += strtokenskip(p);
+ dp = &bd->tdo_mask;
+ memnum = 3;
+ }
+ if (!strtokencmp(p, "RMASK")) {
+ p += strtokenskip(p);
+ dp = &bd->ret_mask;
+ memnum = 4;
+ }
+ if (!dp)
+ return (void*)0;
+ if (*dp == (void*)0) {
+ *dp = LIBXSVF_HOST_REALLOC(*dp, bd->alloced_bytes, offset+memnum);
+ }
+ if (*dp == (void*)0) {
+ LIBXSVF_HOST_REPORT_ERROR("Allocating memory failed.");
+ return (void*)0;
+ }
+
+ unsigned char *d = *dp;
+ for (i=0; i<bd->alloced_bytes; i++)
+ d[i] = 0;
+
+ if (*p != '(')
+ return (void*)0;
+ p++;
+
+ int hexdigits = 0;
+ for (i=0; (p[i] >= 'A' && p[i] <= 'F') || (p[i] >= '0' && p[i] <= '9'); i++)
+ hexdigits++;
+
+ i = bd->alloced_bytes*2 - hexdigits;
+ for (j=0; j<hexdigits; j++, i++, p++) {
+ if (i%2 == 0) {
+ d[i/2] |= hex(*p) << 4;
+ } else {
+ d[i/2] |= hex(*p);
+ }
+ }
+
+ if (*p != ')')
+ return (void*)0;
+ p++;
+ while (*p == ' ') {
+ p++;
+ }
+ }
+#if 0
+ /* Debugging Output, needs <stdio.h> */
+ printf("--- Parsed bitdata [%d] ---\n", bd->len);
+ if (bd->tdi_data) {
+ printf("TDI DATA:");
+ for (i=0; i<bd->alloced_bytes; i++)
+ printf(" %02x", bd->tdi_data[i]);
+ printf("\n");
+ }
+ if (bd->tdo_data && has_tdo_data) {
+ printf("TDO DATA:");
+ for (i=0; i<bd->alloced_bytes; i++)
+ printf(" %02x", bd->tdo_data[i]);
+ printf("\n");
+ }
+ if (bd->tdi_mask) {
+ printf("TDI MASK:");
+ for (i=0; i<bd->alloced_bytes; i++)
+ printf(" %02x", bd->tdi_mask[i]);
+ printf("\n");
+ }
+ if (bd->tdo_mask) {
+ printf("TDO MASK:");
+ for (i=0; i<bd->alloced_bytes; i++)
+ printf(" %02x", bd->tdo_mask[i]);
+ printf("\n");
+ }
+#endif
+ return p;
+}
+
+static int getbit(unsigned char *data, int n)
+{
+ return (data[n/8] & (1 << (7 - n%8))) ? 1 : 0;
+}
+
+static int bitdata_play(struct libxsvf_host *h, struct bitdata_s *bd, enum libxsvf_tap_state estate)
+{
+ int left_padding = (8 - bd->len % 8) % 8;
+ int tdo_error = 0;
+ int tms = 0;
+ int i;
+
+ //printf("bitpdata_play from %d to %d\r\n", bd->len+left_padding-1, left_padding);
+ unsigned char data[250];
+ unsigned char count = 0;
+
+ for (i=bd->len+left_padding-1; i >= left_padding; i--) {
+ if (i == left_padding && h->tap_state != estate) {
+ h->tap_state++;
+ tms = 1;
+ }
+ int tdi = -1;
+ if (bd->tdi_data) {
+ if (!bd->tdi_mask || getbit(bd->tdi_mask, i))
+ tdi = getbit(bd->tdi_data, i);
+ }
+ int tdo = -1;
+ if (bd->tdo_data && bd->has_tdo_data && (!bd->tdo_mask || getbit(bd->tdo_mask, i)))
+ tdo = getbit(bd->tdo_data, i);
+ //int rmask = bd->ret_mask && getbit(bd->ret_mask, i);
+ //if (LIBXSVF_HOST_PULSE_TCK(tms, tdi, tdo, rmask, 0) < 0)
+ data[count] = (tms&1);
+ if (tdi >= 0)
+ {
+ data[count] |= (1<<1);
+ data[count] |= tdi<<2;
+ }
+ if (tdo >= 0)
+ {
+ data[count] |= (1<<3);
+ data[count] |= tdo<<4;
+ }
+ count++;
+ if (count == sizeof(data))
+ {
+ if (LIBXSVF_HOST_PULSE_TCK_MULTI(data,count) < 0)
+ tdo_error = 1;
+ count = 0;
+ }
+ }
+
+ if (count > 0)
+ {
+ if (LIBXSVF_HOST_PULSE_TCK_MULTI(data,count) < 0)
+ tdo_error = 1;
+ count = 0;
+ }
+
+ if (tms)
+ LIBXSVF_HOST_REPORT_TAPSTATE();
+
+ if (!tdo_error)
+ return 0;
+
+ LIBXSVF_HOST_REPORT_ERROR("TDO mismatch.");
+ return -1;
+}
+
+int libxsvf_svf(struct libxsvf_host *h)
+{
+ char *command_buffer = (void*)0;
+ int command_buffer_len = 0;
+ int rc, i;
+
+ struct bitdata_s bd_hdr = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 };
+ struct bitdata_s bd_hir = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 };
+ struct bitdata_s bd_tdr = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 };
+ struct bitdata_s bd_tir = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 };
+ struct bitdata_s bd_sdr = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 };
+ struct bitdata_s bd_sir = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 };
+
+ int state_endir = LIBXSVF_TAP_IDLE;
+ int state_enddr = LIBXSVF_TAP_IDLE;
+ int state_run = LIBXSVF_TAP_IDLE;
+ int state_endrun = LIBXSVF_TAP_IDLE;
+
+ while (1)
+ {
+ rc = read_command(h, &command_buffer, &command_buffer_len);
+
+ if (rc <= 0)
+ break;
+
+ const char *p = command_buffer;
+
+ LIBXSVF_HOST_REPORT_STATUS(command_buffer);
+
+ if (!strtokencmp(p, "ENDIR")) {
+ p += strtokenskip(p);
+ state_endir = token2tapstate(p);
+ if (state_endir < 0)
+ goto syntax_error;
+ p += strtokenskip(p);
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "ENDDR")) {
+ p += strtokenskip(p);
+ state_enddr = token2tapstate(p);
+ if (state_endir < 0)
+ goto syntax_error;
+ p += strtokenskip(p);
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "FREQUENCY")) {
+ while (*p > 0 && *p >= ' ') {
+ p++;
+ }
+ /*
+ unsigned long number = 0;
+ int exp = 0;
+ p += strtokenskip(p);
+ if (*p < '0' || *p > '9')
+ goto syntax_error;
+ while (*p >= '0' && *p <= '9') {
+ number = number*10 + (*p - '0');
+ p++;
+ }
+ if(*p == 'E' || *p == 'e') {
+ p++;
+ while (*p >= '0' && *p <= '9') {
+ exp = exp*10 + (*p - '0');
+ p++;
+ }
+ for(i=0; i<exp; i++)
+ number *= 10;
+ }
+ while (*p == ' ') {
+ p++;
+ }
+ p += strtokenskip(p);
+ if (LIBXSVF_HOST_SET_FREQUENCY(number) < 0) {
+ LIBXSVF_HOST_REPORT_ERROR("FREQUENCY command failed!");
+ goto error;
+ }
+ */
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "HDR")) {
+ p += strtokenskip(p);
+ p = bitdata_parse(h, p, &bd_hdr, LIBXSVF_MEM_SVF_HDR_TDI_DATA);
+ if (!p)
+ goto syntax_error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "HIR")) {
+ p += strtokenskip(p);
+ p = bitdata_parse(h, p, &bd_hir, LIBXSVF_MEM_SVF_HIR_TDI_DATA);
+ if (!p)
+ goto syntax_error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "PIO") || !strtokencmp(p, "PIOMAP")) {
+ goto unsupported_error;
+ }
+
+ if (!strtokencmp(p, "RUNTEST")) {
+ p += strtokenskip(p);
+ int tck_count = -1;
+ int sck_count = -1;
+ int min_time = -1;
+ int max_time = -1;
+ while (*p) {
+ int got_maximum = 0;
+ if (!strtokencmp(p, "MAXIMUM")) {
+ p += strtokenskip(p);
+ got_maximum = 1;
+ }
+ int got_endstate = 0;
+ if (!strtokencmp(p, "ENDSTATE")) {
+ p += strtokenskip(p);
+ got_endstate = 1;
+ }
+ int st = token2tapstate(p);
+ if (st >= 0) {
+ p += strtokenskip(p);
+ if (got_endstate)
+ state_endrun = st;
+ else
+ state_run = st;
+ continue;
+ }
+ if (*p < '0' || *p > '9')
+ goto syntax_error;
+ int number = 0;
+ int exp = 0, expsign = 1;
+ int number_e6, exp_e6;
+ while (*p >= '0' && *p <= '9') {
+ number = number*10 + (*p - '0');
+ p++;
+ }
+ if(*p == 'E' || *p == 'e') {
+ p++;
+ if(*p == '-') {
+ expsign = -1;
+ p++;
+ }
+ while (*p >= '0' && *p <= '9') {
+ exp = exp*10 + (*p - '0');
+ p++;
+ }
+ exp = exp * expsign;
+ number_e6 = number;
+ exp_e6 = exp + 6;
+ while (exp < 0) {
+ number /= 10;
+ exp++;
+ }
+ while (exp > 0) {
+ number *= 10;
+ exp--;
+ }
+ while (exp_e6 < 0) {
+ number_e6 /= 10;
+ exp_e6++;
+ }
+ while (exp_e6 > 0) {
+ number_e6 *= 10;
+ exp_e6--;
+ }
+ } else {
+ number_e6 = number * 1000000;
+ }
+ while (*p == ' ') {
+ p++;
+ }
+ if (!strtokencmp(p, "SEC")) {
+ p += strtokenskip(p);
+ if (got_maximum)
+ max_time = number_e6;
+ else
+ min_time = number_e6;
+ continue;
+ }
+ if (!strtokencmp(p, "TCK")) {
+ p += strtokenskip(p);
+ tck_count = number;
+ continue;
+ }
+ if (!strtokencmp(p, "SCK")) {
+ p += strtokenskip(p);
+ sck_count = number;
+ continue;
+ }
+ goto syntax_error;
+ }
+ if (libxsvf_tap_walk(h, state_run) < 0)
+ goto error;
+ if (max_time >= 0) {
+ LIBXSVF_HOST_REPORT_ERROR("WARNING: Maximum time in SVF RUNTEST command is ignored.");
+ }
+ if (sck_count >= 0) {
+ for (i=0; i < sck_count; i++) {
+ LIBXSVF_HOST_PULSE_SCK();
+ }
+ }
+ if (min_time >= 0 || tck_count >= 0) {
+ LIBXSVF_HOST_UDELAY(min_time >= 0 ? min_time : 0, 0, tck_count >= 0 ? tck_count : 0);
+ }
+ if (libxsvf_tap_walk(h, state_endrun) < 0)
+ goto error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "SDR")) {
+ p += strtokenskip(p);
+ p = bitdata_parse(h, p, &bd_sdr, LIBXSVF_MEM_SVF_SDR_TDI_DATA);
+ if (!p)
+ goto syntax_error;
+ if (libxsvf_tap_walk(h, LIBXSVF_TAP_DRSHIFT) < 0)
+ goto error;
+ if (bitdata_play(h, &bd_hdr, bd_sdr.len+bd_tdr.len > 0 ? LIBXSVF_TAP_DRSHIFT : state_enddr) < 0)
+ goto error;
+ if (bitdata_play(h, &bd_sdr, bd_tdr.len > 0 ? LIBXSVF_TAP_DRSHIFT : state_enddr) < 0)
+ goto error;
+ if (bitdata_play(h, &bd_tdr, state_enddr) < 0)
+ goto error;
+ if (libxsvf_tap_walk(h, state_enddr) < 0)
+ goto error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "SIR")) {
+ p += strtokenskip(p);
+ p = bitdata_parse(h, p, &bd_sir, LIBXSVF_MEM_SVF_SIR_TDI_DATA);
+ if (!p)
+ goto syntax_error;
+ if (libxsvf_tap_walk(h, LIBXSVF_TAP_IRSHIFT) < 0)
+ goto error;
+ if (bitdata_play(h, &bd_hir, bd_sir.len+bd_tir.len > 0 ? LIBXSVF_TAP_IRSHIFT : state_endir) < 0)
+ goto error;
+ if (bitdata_play(h, &bd_sir, bd_tir.len > 0 ? LIBXSVF_TAP_IRSHIFT : state_endir) < 0)
+ goto error;
+ if (bitdata_play(h, &bd_tir, state_endir) < 0)
+ goto error;
+ if (libxsvf_tap_walk(h, state_endir) < 0)
+ goto error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "STATE")) {
+ p += strtokenskip(p);
+ while (*p) {
+ int st = token2tapstate(p);
+ if (st < 0)
+ goto syntax_error;
+ if (libxsvf_tap_walk(h, st) < 0)
+ goto error;
+ p += strtokenskip(p);
+ }
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "TDR")) {
+ p += strtokenskip(p);
+ p = bitdata_parse(h, p, &bd_tdr, LIBXSVF_MEM_SVF_TDR_TDI_DATA);
+ if (!p)
+ goto syntax_error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "TIR")) {
+ p += strtokenskip(p);
+ p = bitdata_parse(h, p, &bd_tir, LIBXSVF_MEM_SVF_TIR_TDI_DATA);
+ if (!p)
+ goto syntax_error;
+ goto eol_check;
+ }
+
+ if (!strtokencmp(p, "TRST")) {
+ p += strtokenskip(p);
+ if (!strtokencmp(p, "ON")) {
+ p += strtokenskip(p);
+ LIBXSVF_HOST_SET_TRST(1);
+ goto eol_check;
+ }
+ if (!strtokencmp(p, "OFF")) {
+ p += strtokenskip(p);
+ LIBXSVF_HOST_SET_TRST(0);
+ goto eol_check;
+ }
+ if (!strtokencmp(p, "Z")) {
+ p += strtokenskip(p);
+ LIBXSVF_HOST_SET_TRST(-1);
+ goto eol_check;
+ }
+ if (!strtokencmp(p, "ABSENT")) {
+ p += strtokenskip(p);
+ LIBXSVF_HOST_SET_TRST(-2);
+ goto eol_check;
+ }
+ goto syntax_error;
+ }
+
+eol_check:
+ while (*p == ' ')
+ p++;
+ if (*p == 0)
+ continue;
+
+syntax_error:
+ LIBXSVF_HOST_REPORT_ERROR("SVF Syntax Error:");
+ if (0) {
+unsupported_error:
+ LIBXSVF_HOST_REPORT_ERROR("Error in SVF input: unsupported command:");
+ }
+ LIBXSVF_HOST_REPORT_ERROR(command_buffer);
+error:
+ rc = -1;
+ break;
+ }
+
+ if (LIBXSVF_HOST_SYNC() != 0 && rc >= 0 ) {
+ LIBXSVF_HOST_REPORT_ERROR("TDO mismatch.");
+ rc = -1;
+ }
+
+ bitdata_free(h, &bd_hdr, LIBXSVF_MEM_SVF_HDR_TDI_DATA);
+ bitdata_free(h, &bd_hir, LIBXSVF_MEM_SVF_HIR_TDI_DATA);
+ bitdata_free(h, &bd_tdr, LIBXSVF_MEM_SVF_TDR_TDI_DATA);
+ bitdata_free(h, &bd_tir, LIBXSVF_MEM_SVF_TIR_TDI_DATA);
+ bitdata_free(h, &bd_sdr, LIBXSVF_MEM_SVF_SDR_TDI_DATA);
+ bitdata_free(h, &bd_sir, LIBXSVF_MEM_SVF_SIR_TDI_DATA);
+
+ LIBXSVF_HOST_REALLOC(command_buffer, 0, LIBXSVF_MEM_SVF_COMMANDBUF);
+
+ return rc;
+}
+
diff --git a/tap.c b/tap.c
new file mode 100644
index 0000000..c258fde
--- /dev/null
+++ b/tap.c
@@ -0,0 +1,173 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+static void tap_transition(struct libxsvf_host *h, int v)
+{
+ LIBXSVF_HOST_PULSE_TCK(v, -1, -1, 0, 0);
+}
+
+int libxsvf_tap_walk(struct libxsvf_host *h, enum libxsvf_tap_state s)
+{
+ int i, j;
+ for (i=0; s != h->tap_state; i++)
+ {
+ switch (h->tap_state)
+ {
+ /* Special States */
+ case LIBXSVF_TAP_INIT:
+ for (j = 0; j < 6; j++)
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_RESET;
+ break;
+ case LIBXSVF_TAP_RESET:
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IDLE;
+ break;
+ case LIBXSVF_TAP_IDLE:
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DRSELECT;
+ break;
+
+ /* DR States */
+ case LIBXSVF_TAP_DRSELECT:
+ if (s >= LIBXSVF_TAP_IRSELECT || s == LIBXSVF_TAP_RESET) {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_IRSELECT;
+ } else {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_DRCAPTURE;
+ }
+ break;
+ case LIBXSVF_TAP_DRCAPTURE:
+ if (s == LIBXSVF_TAP_DRSHIFT) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_DRSHIFT;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DREXIT1;
+ }
+ break;
+ case LIBXSVF_TAP_DRSHIFT:
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DREXIT1;
+ break;
+ case LIBXSVF_TAP_DREXIT1:
+ if (s == LIBXSVF_TAP_DRPAUSE) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_DRPAUSE;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DRUPDATE;
+ }
+ break;
+ case LIBXSVF_TAP_DRPAUSE:
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DREXIT2;
+ break;
+ case LIBXSVF_TAP_DREXIT2:
+ if (s == LIBXSVF_TAP_DRSHIFT) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_DRSHIFT;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DRUPDATE;
+ }
+ break;
+ case LIBXSVF_TAP_DRUPDATE:
+ if (s == LIBXSVF_TAP_IDLE) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IDLE;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DRSELECT;
+ }
+ break;
+
+ /* IR States */
+ case LIBXSVF_TAP_IRSELECT:
+ if (s == LIBXSVF_TAP_RESET) {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_RESET;
+ } else {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IRCAPTURE;
+ }
+ break;
+ case LIBXSVF_TAP_IRCAPTURE:
+ if (s == LIBXSVF_TAP_IRSHIFT) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IRSHIFT;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_IREXIT1;
+ }
+ break;
+ case LIBXSVF_TAP_IRSHIFT:
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_IREXIT1;
+ break;
+ case LIBXSVF_TAP_IREXIT1:
+ if (s == LIBXSVF_TAP_IRPAUSE) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IRPAUSE;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_IRUPDATE;
+ }
+ break;
+ case LIBXSVF_TAP_IRPAUSE:
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_IREXIT2;
+ break;
+ case LIBXSVF_TAP_IREXIT2:
+ if (s == LIBXSVF_TAP_IRSHIFT) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IRSHIFT;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_IRUPDATE;
+ }
+ break;
+ case LIBXSVF_TAP_IRUPDATE:
+ if (s == LIBXSVF_TAP_IDLE) {
+ tap_transition(h, 0);
+ h->tap_state = LIBXSVF_TAP_IDLE;
+ } else {
+ tap_transition(h, 1);
+ h->tap_state = LIBXSVF_TAP_DRSELECT;
+ }
+ break;
+
+ default:
+ LIBXSVF_HOST_REPORT_ERROR("Illegal tap state.");
+ return -1;
+ }
+ if (h->report_tapstate)
+ LIBXSVF_HOST_REPORT_TAPSTATE();
+ if (i>10) {
+ LIBXSVF_HOST_REPORT_ERROR("Loop in tap walker.");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/xsvf.c b/xsvf.c
new file mode 100644
index 0000000..e2dad07
--- /dev/null
+++ b/xsvf.c
@@ -0,0 +1,516 @@
+/*
+ * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players
+ *
+ * Copyright (C) 2009 RIEGL Research ForschungsGmbH
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include "libxsvf.h"
+
+/* command codes as defined in xilinx xapp503 */
+enum xsvf_cmd {
+ XCOMPLETE = 0x00,
+ XTDOMASK = 0x01,
+ XSIR = 0x02,
+ XSDR = 0x03,
+ XRUNTEST = 0x04,
+ XREPEAT = 0x07,
+ XSDRSIZE = 0x08,
+ XSDRTDO = 0x09,
+ XSETSDRMASKS = 0x0A,
+ XSDRINC = 0x0B,
+ XSDRB = 0x0C,
+ XSDRC = 0x0D,
+ XSDRE = 0x0E,
+ XSDRTDOB = 0x0F,
+ XSDRTDOC = 0x10,
+ XSDRTDOE = 0x11,
+ XSTATE = 0x12,
+ XENDIR = 0x13,
+ XENDDR = 0x14,
+ XSIR2 = 0x15,
+ XCOMMENT = 0x16,
+ XWAIT = 0x17,
+ /* Extensions used in svf2xsvf.py */
+ XWAITSTATE = 0x18,
+ XTRST = 0x1c
+};
+
+// This is to not confuse the VIM syntax highlighting
+#define VAL_OPEN (
+#define VAL_CLOSE )
+
+#define READ_BITS(_buf, _len) do { \
+ unsigned char *_p = _buf; int _i; \
+ for (_i=0; _i<(_len); _i+=8) { \
+ int tmp = LIBXSVF_HOST_GETBYTE(); \
+ if (tmp < 0) { \
+ LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); \
+ goto error; \
+ } \
+ *(_p++) = tmp; \
+ } \
+} while (0)
+
+#define READ_LONG() VAL_OPEN{ \
+ long _buf = 0; int _i; \
+ for (_i=0; _i<4; _i++) { \
+ int tmp = LIBXSVF_HOST_GETBYTE(); \
+ if (tmp < 0) { \
+ LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); \
+ goto error; \
+ } \
+ _buf = _buf << 8 | tmp; \
+ } \
+ _buf; \
+}VAL_CLOSE
+
+#define READ_BYTE() VAL_OPEN{ \
+ int _tmp = LIBXSVF_HOST_GETBYTE(); \
+ if (_tmp < 0) { \
+ LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); \
+ goto error; \
+ } \
+ _tmp; \
+}VAL_CLOSE
+
+#define SHIFT_DATA(_inp, _outp, _maskp, _len, _state, _estate, _edelay, _ret) do { \
+ if (shift_data(h, _inp, _outp, _maskp, _len, _state, _estate, _edelay, _ret) < 0) { \
+ goto error; \
+ } \
+} while (0)
+
+#define TAP(_state) do { \
+ if (libxsvf_tap_walk(h, _state) < 0) \
+ goto error; \
+} while (0)
+
+static int bits2bytes(int bits)
+{
+ return (bits+7) / 8;
+}
+
+static int getbit(unsigned char *data, int n)
+{
+ return (data[n/8] & (1 << (7 - n%8))) ? 1 : 0;
+}
+
+static void setbit(unsigned char *data, int n, int v)
+{
+ unsigned char mask = 1 << (7 - n%8);
+ if (v)
+ data[n/8] |= mask;
+ else
+ data[n/8] &= ~mask;
+}
+
+static int xilinx_tap(int state)
+{
+ /* state codes as defined in xilinx xapp503 */
+ switch (state)
+ {
+ case 0x00:
+ return LIBXSVF_TAP_RESET;
+ break;
+ case 0x01:
+ return LIBXSVF_TAP_IDLE;
+ break;
+ case 0x02:
+ return LIBXSVF_TAP_DRSELECT;
+ break;
+ case 0x03:
+ return LIBXSVF_TAP_DRCAPTURE;
+ break;
+ case 0x04:
+ return LIBXSVF_TAP_DRSHIFT;
+ break;
+ case 0x05:
+ return LIBXSVF_TAP_DREXIT1;
+ break;
+ case 0x06:
+ return LIBXSVF_TAP_DRPAUSE;
+ break;
+ case 0x07:
+ return LIBXSVF_TAP_DREXIT2;
+ break;
+ case 0x08:
+ return LIBXSVF_TAP_DRUPDATE;
+ break;
+ case 0x09:
+ return LIBXSVF_TAP_IRSELECT;
+ break;
+ case 0x0A:
+ return LIBXSVF_TAP_IRCAPTURE;
+ break;
+ case 0x0B:
+ return LIBXSVF_TAP_IRSHIFT;
+ break;
+ case 0x0C:
+ return LIBXSVF_TAP_IREXIT1;
+ break;
+ case 0x0D:
+ return LIBXSVF_TAP_IRPAUSE;
+ break;
+ case 0x0E:
+ return LIBXSVF_TAP_IREXIT2;
+ break;
+ case 0x0F:
+ return LIBXSVF_TAP_IRUPDATE;
+ break;
+ }
+ return -1;
+}
+
+static int shift_data(struct libxsvf_host *h, unsigned char *inp, unsigned char *outp, unsigned char *maskp, int len, enum libxsvf_tap_state state, enum libxsvf_tap_state estate, int edelay, int retries)
+{
+ int left_padding = (8 - len % 8) % 8;
+ int with_retries = retries > 0;
+ int i;
+
+ if (with_retries && LIBXSVF_HOST_SYNC() < 0) {
+ LIBXSVF_HOST_REPORT_ERROR("TDO mismatch.");
+ return -1;
+ }
+
+ while (1)
+ {
+ int tdo_error = 0;
+ int tms = 0;
+
+ TAP(state);
+ tms = 0;
+
+ unsigned char data[250];
+ unsigned char count = 0;
+
+ for (i=len+left_padding-1; i>=left_padding; i--) {
+ if (i == left_padding && h->tap_state != estate) {
+ h->tap_state++;
+ tms = 1;
+ }
+ int tdi = getbit(inp, i);
+ int tdo = -1;
+ if (maskp && getbit(maskp, i))
+ tdo = outp && getbit(outp, i);
+// int sync = with_retries && i == left_padding;
+
+ data[count] = (tms&1);
+ if (tdi >= 0)
+ {
+ data[count] |= (1<<1);
+ data[count] |= tdi<<2;
+ }
+ if (tdo >= 0)
+ {
+ data[count] |= (1<<3);
+ data[count] |= tdo<<4;
+ }
+ count++;
+ if (count == sizeof(data))
+ {
+ if (LIBXSVF_HOST_PULSE_TCK_MULTI(data,count) < 0)
+ tdo_error = 1;
+ count = 0;
+ }
+
+// if (LIBXSVF_HOST_PULSE_TCK(tms, tdi, tdo, 0, sync) < 0)
+// tdo_error = 1;
+ }
+
+ if (count > 0)
+ {
+ if (LIBXSVF_HOST_PULSE_TCK_MULTI(data,count) < 0)
+ tdo_error = 1;
+ count = 0;
+ }
+
+ if (tms)
+ LIBXSVF_HOST_REPORT_TAPSTATE();
+
+ if (edelay) {
+ TAP(LIBXSVF_TAP_IDLE);
+ LIBXSVF_HOST_UDELAY(edelay, 0, edelay);
+ } else {
+ TAP(estate);
+ }
+
+ if (!tdo_error)
+ return 0;
+
+ if (retries <= 0) {
+ LIBXSVF_HOST_REPORT_ERROR("TDO mismatch.");
+ return -1;
+ }
+
+ retries--;
+ }
+
+error:
+ return -1;
+}
+
+int libxsvf_xsvf(struct libxsvf_host *h)
+{
+ int rc = 0;
+ int i, j;
+
+ unsigned char *buf_tdi_data = (void*)0;
+ unsigned char *buf_tdo_data = (void*)0;
+ unsigned char *buf_tdo_mask = (void*)0;
+ unsigned char *buf_addr_mask = (void*)0;
+ unsigned char *buf_data_mask = (void*)0;
+
+ long state_dr_size = 0;
+ long state_data_size = 0;
+ long state_runtest = 0;
+ unsigned char state_xendir = 0;
+ unsigned char state_xenddr = 0;
+ unsigned char state_retries = 0;
+ unsigned char cmd = 0;
+
+ while (1)
+ {
+ unsigned char last_cmd = cmd;
+ cmd = LIBXSVF_HOST_GETBYTE();
+
+#define STATUS(_c) LIBXSVF_HOST_REPORT_STATUS("XSVF Command " #_c);
+
+ switch (cmd)
+ {
+ case XCOMPLETE: {
+ STATUS(XCOMPLETE);
+ goto got_complete_command;
+ }
+ case XTDOMASK: {
+ STATUS(XTDOMASK);
+ READ_BITS(buf_tdo_mask, state_dr_size);
+ break;
+ }
+ case XSIR: {
+ STATUS(XSIR);
+ int length = READ_BYTE();
+ unsigned char buf[bits2bytes(length)];
+ READ_BITS(buf, length);
+ SHIFT_DATA(buf, (void*)0, (void*)0, length, LIBXSVF_TAP_IRSHIFT,
+ state_xendir ? LIBXSVF_TAP_IRPAUSE : LIBXSVF_TAP_IDLE,
+ state_runtest, state_retries);
+ break;
+ }
+ case XSDR: {
+ STATUS(XSDR);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, buf_tdo_data, buf_tdo_mask, state_dr_size, LIBXSVF_TAP_DRSHIFT,
+ state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE,
+ state_runtest, state_retries);
+ break;
+ }
+ case XRUNTEST: {
+ STATUS(XRUNTEST);
+ state_runtest = READ_LONG();
+ break;
+ }
+ case XREPEAT: {
+ STATUS(XREPEAT);
+ state_retries = READ_BYTE();
+ break;
+ }
+ case XSDRSIZE: {
+ STATUS(XSDRSIZE);
+ state_dr_size = READ_LONG();
+ buf_tdi_data = LIBXSVF_HOST_REALLOC(buf_tdi_data, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_TDI_DATA);
+ buf_tdo_data = LIBXSVF_HOST_REALLOC(buf_tdo_data, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_TDO_DATA);
+ buf_tdo_mask = LIBXSVF_HOST_REALLOC(buf_tdo_mask, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_TDO_MASK);
+ buf_addr_mask = LIBXSVF_HOST_REALLOC(buf_addr_mask, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_ADDR_MASK);
+ buf_data_mask = LIBXSVF_HOST_REALLOC(buf_data_mask, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_DATA_MASK);
+ if (!buf_tdi_data || !buf_tdo_data || !buf_tdo_mask || !buf_addr_mask || !buf_data_mask) {
+ LIBXSVF_HOST_REPORT_ERROR("Allocating memory failed.");
+ goto error;
+ }
+ break;
+ }
+ case XSDRTDO: {
+ STATUS(XSDRTDO);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ READ_BITS(buf_tdo_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, buf_tdo_data, buf_tdo_mask, state_dr_size, LIBXSVF_TAP_DRSHIFT,
+ state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE,
+ state_runtest, state_retries);
+ break;
+ }
+ case XSETSDRMASKS: {
+ STATUS(XSETSDRMASKS);
+ READ_BITS(buf_addr_mask, state_dr_size);
+ READ_BITS(buf_data_mask, state_dr_size);
+ state_data_size = 0;
+ for (i=0; i<state_dr_size; i++)
+ state_data_size += getbit(buf_data_mask, i);
+ break;
+ }
+ case XSDRINC: {
+ STATUS(XSDRINC);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ int num = READ_BYTE();
+ while (1) {
+ SHIFT_DATA(buf_tdi_data, buf_tdo_data, buf_tdo_mask, state_dr_size, LIBXSVF_TAP_DRSHIFT,
+ state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE,
+ state_runtest, state_retries);
+ if (num-- <= 0)
+ break;
+ int carry = 1;
+ for (i=state_dr_size-1; i>=0; i--) {
+ if (getbit(buf_addr_mask, i) == 0)
+ continue;
+ if (getbit(buf_tdi_data, i)) {
+ setbit(buf_tdi_data, i, !carry);
+ } else {
+ setbit(buf_tdi_data, i, carry);
+ carry = 0;
+ }
+ }
+ unsigned char this_byte = 0;
+ for (i=0, j=0; i<state_data_size; i++) {
+ if (i%8 == 0)
+ this_byte = READ_BYTE();
+ while (getbit(buf_data_mask, j) == 0)
+ j++;
+ setbit(buf_tdi_data, j++, getbit(&this_byte, i%8));
+ }
+ }
+ break;
+ }
+ case XSDRB: {
+ STATUS(XSDRB);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, (void*)0, (void*)0, state_dr_size, LIBXSVF_TAP_DRSHIFT, LIBXSVF_TAP_DRSHIFT, 0, 0);
+ break;
+ }
+ case XSDRC: {
+ STATUS(XSDRC);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, (void*)0, (void*)0, state_dr_size, LIBXSVF_TAP_DRSHIFT, LIBXSVF_TAP_DRSHIFT, 0, 0);
+ break;
+ }
+ case XSDRE: {
+ STATUS(XSDRE);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, (void*)0, (void*)0, state_dr_size, LIBXSVF_TAP_DRSHIFT,
+ state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE, 0, 0);
+ break;
+ }
+ case XSDRTDOB: {
+ STATUS(XSDRTDOB);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ READ_BITS(buf_tdo_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, buf_tdo_data, (void*)0, state_dr_size, LIBXSVF_TAP_DRSHIFT, LIBXSVF_TAP_DRSHIFT, 0, 0);
+ break;
+ }
+ case XSDRTDOC: {
+ STATUS(XSDRTDOC);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ READ_BITS(buf_tdo_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, buf_tdo_data, (void*)0, state_dr_size, LIBXSVF_TAP_DRSHIFT, LIBXSVF_TAP_DRSHIFT, 0, 0);
+ break;
+ }
+ case XSDRTDOE: {
+ STATUS(XSDRTDOE);
+ READ_BITS(buf_tdi_data, state_dr_size);
+ READ_BITS(buf_tdo_data, state_dr_size);
+ SHIFT_DATA(buf_tdi_data, buf_tdo_data, (void*)0, state_dr_size, LIBXSVF_TAP_DRSHIFT,
+ state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE, 0, 0);
+ break;
+ }
+ case XSTATE: {
+ STATUS(XSTATE);
+ if (state_runtest && last_cmd == XRUNTEST) {
+ TAP(LIBXSVF_TAP_IDLE);
+ LIBXSVF_HOST_UDELAY(state_runtest, 0, state_runtest);
+ }
+ unsigned char state = READ_BYTE();
+ TAP(xilinx_tap(state));
+ break;
+ }
+ case XENDIR: {
+ STATUS(XENDIR);
+ state_xendir = READ_BYTE();
+ break;
+ }
+ case XENDDR: {
+ STATUS(XENDDR);
+ state_xenddr = READ_BYTE();
+ break;
+ }
+ case XSIR2: {
+ STATUS(XSIR2);
+ int length = READ_BYTE();
+ length = length << 8 | READ_BYTE();
+ unsigned char buf[bits2bytes(length)];
+ READ_BITS(buf, length);
+ SHIFT_DATA(buf, (void*)0, (void*)0, length, LIBXSVF_TAP_IRSHIFT,
+ state_xendir ? LIBXSVF_TAP_IRPAUSE : LIBXSVF_TAP_IDLE,
+ state_runtest, state_retries);
+ break;
+ }
+ case XCOMMENT: {
+ STATUS(XCOMMENT);
+ unsigned char this_byte;
+ do {
+ this_byte = READ_BYTE();
+ } while (this_byte);
+ break;
+ }
+ case XWAIT:
+ case XWAITSTATE: {
+ STATUS(XWAIT);
+ unsigned char state1 = READ_BYTE();
+ unsigned char state2 = READ_BYTE();
+ long usecs = READ_LONG();
+ TAP(xilinx_tap(state1));
+ LIBXSVF_HOST_UDELAY(usecs, 0, 0);
+ TAP(xilinx_tap(state2));
+ if (cmd==XWAITSTATE) {
+ READ_LONG(); /* XWAITSTATE has count, time arguments */
+ }
+ break;
+ }
+ case XTRST: {
+ STATUS(XTRST);
+ READ_BYTE(); /* enum: ON, OFF, Z, ABSENT */
+ break;
+ }
+ default:
+ LIBXSVF_HOST_REPORT_ERROR("Unknown XSVF command.");
+ goto error;
+ }
+ }
+
+error:
+ rc = -1;
+
+got_complete_command:
+ if (LIBXSVF_HOST_SYNC() != 0 && rc >= 0 ) {
+ LIBXSVF_HOST_REPORT_ERROR("TDO mismatch.");
+ rc = -1;
+ }
+
+ LIBXSVF_HOST_REALLOC(buf_tdi_data, 0, LIBXSVF_MEM_XSVF_TDI_DATA);
+ LIBXSVF_HOST_REALLOC(buf_tdo_data, 0, LIBXSVF_MEM_XSVF_TDO_DATA);
+ LIBXSVF_HOST_REALLOC(buf_tdo_mask, 0, LIBXSVF_MEM_XSVF_TDO_MASK);
+ LIBXSVF_HOST_REALLOC(buf_addr_mask, 0, LIBXSVF_MEM_XSVF_ADDR_MASK);
+ LIBXSVF_HOST_REALLOC(buf_data_mask, 0, LIBXSVF_MEM_XSVF_DATA_MASK);
+
+ return rc;
+}
+