diff options
author | Alexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com> | 2015-01-05 03:33:41 +0300 |
---|---|---|
committer | Alexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com> | 2015-01-05 03:33:41 +0300 |
commit | 9ac4d1d996ee1700b033293a75472d1b7d6b9fbe (patch) | |
tree | cdc4dc0b3fb5993df052378bb593c8abaa0cde12 |
First commit
-rw-r--r-- | COPYING | 18 | ||||
-rw-r--r-- | Makefile | 17 | ||||
-rw-r--r-- | clujtag.c | 475 | ||||
-rw-r--r-- | jtag_commands.h | 10 | ||||
-rw-r--r-- | libxsvf.h | 141 | ||||
-rw-r--r-- | memname.c | 65 | ||||
-rw-r--r-- | play.c | 72 | ||||
-rw-r--r-- | scan.c | 58 | ||||
-rw-r--r-- | statename.c | 46 | ||||
-rw-r--r-- | svf.c | 690 | ||||
-rw-r--r-- | tap.c | 173 | ||||
-rw-r--r-- | xsvf.c | 516 |
12 files changed, 2281 insertions, 0 deletions
@@ -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; +} + @@ -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; +} + @@ -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"; +} + @@ -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; +} + @@ -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; +} @@ -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; +} + |