diff options
author | kc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2009-01-19 07:13:02 +0000 |
---|---|---|
committer | kc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60> | 2009-01-19 07:13:02 +0000 |
commit | c8bc0bb1aee7e7280229a6ec0c104a8fb512782f (patch) | |
tree | 184934c96da1b155b17cf21027064eed0676c48f /src/svf | |
parent | 2aed5dd40b42f8381d62658522a7ada453e22022 (diff) | |
download | openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.tar.gz openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.tar.bz2 openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.tar.xz openocd+libswd-c8bc0bb1aee7e7280229a6ec0c104a8fb512782f.zip |
SVF player courtesy of Simon Qian <simonqian@SimonQian.com>
git-svn-id: svn://svn.berlios.de/openocd/trunk@1339 b42882b7-edfa-0310-969c-e2dbd0fdcd60
Diffstat (limited to 'src/svf')
-rw-r--r-- | src/svf/Makefile.am | 5 | ||||
-rw-r--r-- | src/svf/Makefile.in | 406 | ||||
-rw-r--r-- | src/svf/svf.c | 1305 | ||||
-rw-r--r-- | src/svf/svf.h | 27 |
4 files changed, 1743 insertions, 0 deletions
diff --git a/src/svf/Makefile.am b/src/svf/Makefile.am new file mode 100644 index 00000000..fa789d66 --- /dev/null +++ b/src/svf/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag $(all_includes) +METASOURCES = AUTO +noinst_LIBRARIES = libsvf.a +noinst_HEADERS = svf.h +libsvf_a_SOURCES = svf.c diff --git a/src/svf/Makefile.in b/src/svf/Makefile.in new file mode 100644 index 00000000..adb85453 --- /dev/null +++ b/src/svf/Makefile.in @@ -0,0 +1,406 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/svf +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libsvf_a_AR = $(AR) $(ARFLAGS) +libsvf_a_LIBADD = +am_libsvf_a_OBJECTS = svf.$(OBJEXT) +libsvf_a_OBJECTS = $(am_libsvf_a_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libsvf_a_SOURCES) +DIST_SOURCES = $(libsvf_a_SOURCES) +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag $(all_includes) +METASOURCES = AUTO +noinst_LIBRARIES = libsvf.a +noinst_HEADERS = svf.h +libsvf_a_SOURCES = svf.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/svf/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/svf/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libsvf.a: $(libsvf_a_OBJECTS) $(libsvf_a_DEPENDENCIES) + -rm -f libsvf.a + $(libsvf_a_AR) libsvf.a $(libsvf_a_OBJECTS) $(libsvf_a_LIBADD) + $(RANLIB) libsvf.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svf.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(HEADERS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/svf/svf.c b/src/svf/svf.c new file mode 100644 index 00000000..baa00885 --- /dev/null +++ b/src/svf/svf.c @@ -0,0 +1,1305 @@ +/*************************************************************************** + * Copyright (C) 2009 by Simon Qian * + * SimonQian@SimonQian.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +/* The specification for SVF is available here: + * http://www.asset-intertech.com/support/svf.pdf + * Below, this document is refered to as the "SVF spec". + * + * The specification for XSVF is available here: + * http://www.xilinx.com/support/documentation/application_notes/xapp503.pdf + * Below, this document is refered to as the "XSVF spec". + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "svf.h" + +#include "jtag.h" +#include "command.h" +#include "log.h" + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> + +#include <sys/time.h> +#include <time.h> + +// SVF command +typedef enum +{ + ENDDR, + ENDIR, + FREQUENCY, + HDR, + HIR, + PIO, + PIOMAP, + RUNTEST, + SDR, + SIR, + STATE, + TDR, + TIR, + TRST, +}svf_command_t; + +const char *svf_command_name[14] = +{ + "ENDDR", + "ENDIR", + "FREQUENCY", + "HDR", + "HIR", + "PIO", + "PIOMAP", + "RUNTEST", + "SDR", + "SIR", + "STATE", + "TDR", + "TIR", + "TRST" +}; + +typedef enum +{ + TRST_ON, + TRST_OFF, + TRST_Z, + TRST_ABSENT +}trst_mode_t; + +const char *svf_trst_mode_name[4] = +{ + "ON", + "OFF", + "Z", + "ABSENT" +}; + +char *svf_tap_state_name[16]; + +#define XXR_TDI (1 << 0) +#define XXR_TDO (1 << 1) +#define XXR_MASK (1 << 2) +#define XXR_SMASK (1 << 3) +typedef struct +{ + int len; + int data_mask; + u8 *tdi; + u8 *tdo; + u8 *mask; + u8 *smask; +}svf_xxr_para_t; + +typedef struct +{ + float frequency; + tap_state_t ir_end_state; + tap_state_t dr_end_state; + tap_state_t runtest_run_state; + tap_state_t runtest_end_state; + trst_mode_t trst_mode; + + svf_xxr_para_t hir_para; + svf_xxr_para_t hdr_para; + svf_xxr_para_t tir_para; + svf_xxr_para_t tdr_para; + svf_xxr_para_t sir_para; + svf_xxr_para_t sdr_para; +}svf_para_t; + +svf_para_t svf_para; +const svf_para_t svf_para_init = +{ +// frequency, ir_end_state, dr_end_state, runtest_run_state, runtest_end_state, trst_mode + 0, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TRST_Z, +// hir_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// hdr_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// tir_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// tdr_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// sir_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +// sdr_para +// {len, data_mask, tdi, tdo, mask, smask}, + {0, 0, NULL, NULL, NULL, NULL}, +}; + +typedef struct +{ + int line_num; // used to record line number of the check operation + // so more information could be printed + int enabled; // check is enabled or not + int buffer_offset; // buffer_offset to buffers + int bit_len; // bit length to check +}svf_check_tdo_para_t; + +#define SVF_CHECK_TDO_PARA_SIZE 1024 +static svf_check_tdo_para_t *svf_check_tdo_para = NULL; +static int svf_check_tdo_para_index = 0; + +#define dimof(a) (sizeof(a) / sizeof((a)[0])) + +static int svf_read_command_from_file(int fd); +static int svf_check_tdo(void); +static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len); +static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str); +static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +static int svf_fd = 0; +static char *svf_command_buffer = NULL; +static int svf_command_buffer_size = 0; +static int svf_line_number = 1; + +static jtag_tap_t *tap = NULL; + +#define SVF_MAX_BUFFER_SIZE_TO_COMMIT (4 * 1024) +static u8 *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL; +static int svf_buffer_index = 0, svf_buffer_size = 0; + + +int svf_register_commands(struct command_context_s *cmd_ctx) +{ + register_command(cmd_ctx, NULL, "svf", handle_svf_command, + COMMAND_EXEC, "run svf <file>"); + + return ERROR_OK; +} + +void svf_free_xxd_para(svf_xxr_para_t *para) +{ + if (NULL != para) + { + if (para->tdi != NULL) + { + free(para->tdi); + para->tdi = NULL; + } + if (para->tdo != NULL) + { + free(para->tdo); + para->tdo = NULL; + } + if (para->mask != NULL) + { + free(para->mask); + para->mask = NULL; + } + if (para->smask != NULL) + { + free(para->smask); + para->smask = NULL; + } + } +} + +static int handle_svf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + int command_num = 0, i; + int ret = ERROR_OK; + + if (argc < 1) + { + command_print(cmd_ctx, "usage: svf <file>"); + return ERROR_FAIL; + } + + if ((svf_fd = open(args[0], O_RDONLY)) < 0) + { + command_print(cmd_ctx, "file \"%s\" not found", args[0]); + return ERROR_FAIL; + } + + LOG_USER("svf processing file: \"%s\"", args[0]); + + // init + svf_line_number = 1; + svf_command_buffer_size = 0; + + svf_check_tdo_para_index = 0; + svf_check_tdo_para = malloc(sizeof(svf_check_tdo_para_t) * SVF_CHECK_TDO_PARA_SIZE); + if (NULL == svf_check_tdo_para) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + + svf_buffer_index = 0; + // double the buffer size + // in case current command cannot be commited, and next command is a bit scan command + // here is 32K bits for this big scan command, it should be enough + // buffer will be reallocated if buffer size is not enough + svf_tdi_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT); + if (NULL == svf_tdi_buffer) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + svf_tdo_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT); + if (NULL == svf_tdo_buffer) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + svf_mask_buffer = (u8 *)malloc(2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT); + if (NULL == svf_mask_buffer) + { + LOG_ERROR("not enough memory"); + ret = ERROR_FAIL; + goto free_all; + } + svf_buffer_size = 2 * SVF_MAX_BUFFER_SIZE_TO_COMMIT; + + memcpy(&svf_para, &svf_para_init, sizeof(svf_para)); + for (i = 0; i < dimof(svf_tap_state_name); i++) + { + svf_tap_state_name[i] = (char *)jtag_state_name(i); + } + // TAP_RESET + jtag_add_tlr(); + + while ( ERROR_OK == svf_read_command_from_file(svf_fd) ) + { + if (ERROR_OK != svf_run_command(cmd_ctx, svf_command_buffer)) + { + LOG_ERROR("fail to run command at line %d", svf_line_number); + ret = ERROR_FAIL; + break; + } + command_num++; + } + if (ERROR_OK != jtag_execute_queue()) + { + ret = ERROR_FAIL; + } + else if (ERROR_OK != svf_check_tdo()) + { + ret = ERROR_FAIL; + } + +free_all: + + close(svf_fd); + svf_fd = 0; + + // free buffers + if (svf_command_buffer) + { + free(svf_command_buffer); + svf_command_buffer = NULL; + svf_command_buffer_size = 0; + } + if (svf_check_tdo_para) + { + free(svf_check_tdo_para); + svf_check_tdo_para = NULL; + svf_check_tdo_para_index = 0; + } + if (svf_tdi_buffer) + { + free(svf_tdi_buffer); + svf_tdi_buffer = NULL; + } + if (svf_tdo_buffer) + { + free(svf_tdo_buffer); + svf_tdo_buffer = NULL; + } + if (svf_mask_buffer) + { + free(svf_mask_buffer); + svf_mask_buffer = NULL; + } + svf_buffer_index = 0; + svf_buffer_size = 0; + + svf_free_xxd_para(&svf_para.hdr_para); + svf_free_xxd_para(&svf_para.hir_para); + svf_free_xxd_para(&svf_para.tdr_para); + svf_free_xxd_para(&svf_para.tir_para); + svf_free_xxd_para(&svf_para.sdr_para); + svf_free_xxd_para(&svf_para.sir_para); + + if (ERROR_OK == ret) + { + command_print(cmd_ctx, "svf file programmed successfully for %d commands", command_num); + } + else + { + command_print(cmd_ctx, "svf file programmed failed"); + } + + return ret; +} + +#define SVFP_CMD_INC_CNT 1024 +static int svf_read_command_from_file(int fd) +{ + char ch, *tmp_buffer = NULL; + int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0; + + while (!cmd_ok && (read(fd, &ch, 1) > 0) ) + { + switch(ch) + { + case '!': + slash = 0; + comment = 1; + break; + case '/': + if (++slash == 2) + { + comment = 1; + } + break; + case ';': + slash = 0; + if (!comment) + { + cmd_ok = 1; + } + break; + case '\n': + svf_line_number++; + case '\r': + slash = 0; + comment = 0; + break; + default: + if (!comment) + { + if (cmd_pos >= svf_command_buffer_size - 1) + { + tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT); // 1 more byte for '\0' + if (NULL == tmp_buffer) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + if (svf_command_buffer_size > 0) + { + memcpy(tmp_buffer, svf_command_buffer, svf_command_buffer_size); + } + if (svf_command_buffer != NULL) + { + free(svf_command_buffer); + } + svf_command_buffer = tmp_buffer; + svf_command_buffer_size += SVFP_CMD_INC_CNT; + tmp_buffer = NULL; + } + svf_command_buffer[cmd_pos++] = (char)toupper(ch); + } + break; + } + } + + if (cmd_ok) + { + svf_command_buffer[cmd_pos] = '\0'; + return ERROR_OK; + } + else + { + return ERROR_FAIL; + } +} + +static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu) +{ + int pos = 0, num = 0, space_found = 1; + + while (pos < len) + { + switch(str[pos]) + { + case '\n': + case '\r': + case '!': + case '/': + LOG_ERROR("fail to parse svf command"); + return ERROR_FAIL; + break; + case ' ': + space_found = 1; + str[pos] = '\0'; + break; + default: + if (space_found) + { + argus[num++] = &str[pos]; + space_found = 0; + } + break; + } + pos++; + } + + *num_of_argu = num; + + return ERROR_OK; +} + +static int svf_tap_state_is_stable(tap_state_t state) +{ + return ((TAP_RESET == state) || (TAP_IDLE == state) || (TAP_DRPAUSE == state) || (TAP_IRPAUSE == state)); +} + +static int svf_tap_state_is_valid(tap_state_t state) +{ + return ((state >= 0) && (state < sizeof(svf_tap_state_name))); +} + +static int svf_find_string_in_array(char *str, char **strs, int num_of_element) +{ + int i; + + for (i = 0; i < num_of_element; i++) + { + if (!strcmp(str, strs[i])) + { + return i; + } + } + return 0xFF; +} + +static int svf_adjust_array_length(u8 **arr, int orig_bit_len, int new_bit_len) +{ + int new_byte_len = (new_bit_len + 7) >> 3; + + if ((NULL == *arr) || (((orig_bit_len + 7) >> 3) < ((new_bit_len + 7) >> 3))) + { + if (*arr != NULL) + { + free(*arr); + *arr = NULL; + } + *arr = (u8*)malloc(new_byte_len); + if (NULL == *arr) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memset(*arr, 0, new_byte_len); + } + return ERROR_OK; +} + +static int svf_copy_hexstring_to_binary(char *str, u8 **bin, int orig_bit_len, int bit_len) +{ + int i, str_len = strlen(str), str_byte_len = (bit_len + 3) >> 2, loop_cnt; + u8 ch, need_write = 1; + + if (ERROR_OK != svf_adjust_array_length(bin, orig_bit_len, bit_len)) + { + LOG_ERROR("fail to adjust length of array"); + return ERROR_FAIL; + } + + if (str_byte_len > str_len) + { + loop_cnt = str_byte_len; + } + else + { + loop_cnt = str_len; + } + + for (i = 0; i < loop_cnt; i++) + { + if (i < str_len) + { + ch = str[str_len - i - 1]; + if ((ch >= '0') && (ch <= '9')) + { + ch = ch - '0'; + } + else if ((ch >= 'A') && (ch <= 'F')) + { + ch = ch - 'A' + 10; + } + else + { + LOG_ERROR("invalid hex string"); + return ERROR_FAIL; + } + } + else + { + ch = 0; + } + + // check valid + if (i >= str_byte_len) + { + // all data written, other data should be all '0's and needn't to be written + need_write = 0; + if (ch != 0) + { + LOG_ERROR("value execede length"); + return ERROR_FAIL; + } + } + else if (i == (str_byte_len - 1)) + { + // last data byte, written if valid + if ((ch & ~((1 << (bit_len - 4 * i)) - 1)) != 0) + { + LOG_ERROR("value execede length"); + return ERROR_FAIL; + } + } + + if (need_write) + { + // write bin + if (i % 2) + { + // MSB + (*bin)[i / 2] |= ch << 4; + } + else + { + // LSB + (*bin)[i / 2] = 0; + (*bin)[i / 2] |= ch; + } + } + } + + return ERROR_OK; +} + +static int svf_check_tdo(void) +{ + int i, j, byte_len, index; + + for (i = 0; i < svf_check_tdo_para_index; i++) + { + if (svf_check_tdo_para[i].enabled) + { + byte_len = (svf_check_tdo_para[i].bit_len + 7) >> 3; + index = svf_check_tdo_para[i].buffer_offset; + for (j = 0; j < byte_len; j++) + { + if ((svf_tdi_buffer[index + j] & svf_mask_buffer[index + j]) != svf_tdo_buffer[index + j]) + { + LOG_ERROR("tdo check error at line %d, read = 0x%X, want = 0x%X, mask = 0x%X", + svf_check_tdo_para[i].line_num, + (*(int*)(svf_tdi_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1), + (*(int*)(svf_tdo_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1), + (*(int*)(svf_mask_buffer + index)) & ((1 << svf_check_tdo_para[i].bit_len) - 1)); + return ERROR_FAIL; + } + } + } + } + svf_check_tdo_para_index = 0; + + return ERROR_OK; +} + +static int svf_add_check_para(u8 enabled, int buffer_offset, int bit_len) +{ + if (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE) + { + LOG_ERROR("toooooo many operation undone"); + return ERROR_FAIL; + } + + svf_check_tdo_para[svf_check_tdo_para_index].line_num = svf_line_number; + svf_check_tdo_para[svf_check_tdo_para_index].bit_len = bit_len; + svf_check_tdo_para[svf_check_tdo_para_index].enabled = enabled; + svf_check_tdo_para[svf_check_tdo_para_index].buffer_offset = buffer_offset; + svf_check_tdo_para_index++; + + return ERROR_OK; +} + +// not good to use this +extern jtag_command_t** jtag_get_last_command_p(void); +extern void* cmd_queue_alloc(size_t size); +extern jtag_command_t **last_comand_pointer; + +static int svf_run_command(struct command_context_s *cmd_ctx, char *cmd_str) +{ + char *argus[256], command; + int num_of_argu = 0, i; + + // tmp variable + int i_tmp; + + // not good to use this + jtag_command_t **last_cmd; + + // for RUNTEST + int run_count; + float min_time, max_time; + // for XXR + svf_xxr_para_t *xxr_para_tmp; + u8 **pbuffer_tmp; + scan_field_t field; + // for STATE + tap_state_t *path = NULL, state; + + LOG_DEBUG("%s", cmd_str); + + if (ERROR_OK != svf_parse_cmd_string(cmd_str, strlen(cmd_str), argus, &num_of_argu)) + { + return ERROR_FAIL; + } + + command = svf_find_string_in_array(argus[0], (char **)svf_command_name, dimof(svf_command_name)); + switch(command) + { + case ENDDR: + case ENDIR: + if (num_of_argu != 2) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + i_tmp = svf_find_string_in_array(argus[1], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_stable(i_tmp)) + { + if (command == ENDIR) + { + svf_para.ir_end_state = i_tmp; + LOG_DEBUG("\tir_end_state = %s", svf_tap_state_name[svf_para.ir_end_state]); + } + else + { + svf_para.dr_end_state = i_tmp; + LOG_DEBUG("\tdr_end_state = %s", svf_tap_state_name[svf_para.dr_end_state]); + } + } + else + { + LOG_ERROR("%s is not valid state", argus[1]); + return ERROR_FAIL; + } + break; + case FREQUENCY: + if ((num_of_argu != 1) && (num_of_argu != 3)) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + if (1 == num_of_argu) + { + // TODO: set jtag speed to full speed + svf_para.frequency = 0; + } + else + { + if (strcmp(argus[2], "HZ")) + { + LOG_ERROR("HZ not found in FREQUENCY command"); + return ERROR_FAIL; + } + svf_para.frequency = atof(argus[1]); + // TODO: set jtag speed to + if (svf_para.frequency > 0) + { + command_run_linef(cmd_ctx, "jtag_khz %d", (int)svf_para.frequency / 1000); + LOG_DEBUG("\tfrequency = %f", svf_para.frequency); + } + } + break; + case HDR: + xxr_para_tmp = &svf_para.hdr_para; + goto XXR_common; + case HIR: + xxr_para_tmp = &svf_para.hir_para; + goto XXR_common; + case TDR: + xxr_para_tmp = &svf_para.tdr_para; + goto XXR_common; + case TIR: + xxr_para_tmp = &svf_para.tir_para; + goto XXR_common; + case SDR: + xxr_para_tmp = &svf_para.sdr_para; + goto XXR_common; + case SIR: + xxr_para_tmp = &svf_para.sir_para; + goto XXR_common; + XXR_common: + // XXR length [TDI (tdi)] [TDO (tdo)][MASK (mask)] [SMASK (smask)] + if ((num_of_argu > 10) || (num_of_argu % 2)) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + i_tmp = xxr_para_tmp->len; + xxr_para_tmp->len = atoi(argus[1]); + LOG_DEBUG("\tlength = %d", xxr_para_tmp->len); + xxr_para_tmp->data_mask = 0; + for (i = 2; i < num_of_argu; i += 2) + { + if ((argus[i + 1][0] != '(') || (argus[i + 1][strlen(argus[i + 1]) - 1] != ')')) + { + LOG_ERROR("data section error"); + return ERROR_FAIL; + } + argus[i + 1][strlen(argus[i + 1]) - 1] = '\0'; + // TDI, TDO, MASK, SMASK + if (!strcmp(argus[i], "TDI")) + { + // TDI + pbuffer_tmp = &xxr_para_tmp->tdi; + xxr_para_tmp->data_mask |= XXR_TDI; + } + else if (!strcmp(argus[i], "TDO")) + { + // TDO + pbuffer_tmp = &xxr_para_tmp->tdo; + xxr_para_tmp->data_mask |= XXR_TDO; + } + else if (!strcmp(argus[i], "MASK")) + { + // MASK + pbuffer_tmp = &xxr_para_tmp->mask; + xxr_para_tmp->data_mask |= XXR_MASK; + } + else if (!strcmp(argus[i], "SMASK")) + { + // SMASK + pbuffer_tmp = &xxr_para_tmp->smask; + xxr_para_tmp->data_mask |= XXR_SMASK; + } + else + { + LOG_ERROR("unknow parameter: %s", argus[i]); + return ERROR_FAIL; + } + if (ERROR_OK != svf_copy_hexstring_to_binary(&argus[i + 1][1], pbuffer_tmp, i_tmp, xxr_para_tmp->len)) + { + LOG_ERROR("fail to parse hex value"); + return ERROR_FAIL; + } + LOG_DEBUG("\t%s = 0x%X", argus[i], (**(int**)pbuffer_tmp) & ((1 << (xxr_para_tmp->len)) - 1)); + } + // If a command changes the length of the last scan of the same type and the MASK parameter is absent, + // the mask pattern used is all cares + if (!(xxr_para_tmp->data_mask & XXR_MASK) && (i_tmp != xxr_para_tmp->len)) + { + // MASK not defined and length changed + if (ERROR_OK != svf_adjust_array_length(&xxr_para_tmp->mask, i_tmp, xxr_para_tmp->len)) + { + LOG_ERROR("fail to adjust length of array"); + return ERROR_FAIL; + } + buf_set_ones(xxr_para_tmp->mask, xxr_para_tmp->len); + } + // do scan if necessary + if (SDR == command) + { + // check buffer size first, reallocate if necessary + i = svf_para.hdr_para.len + svf_para.sdr_para.len + svf_para.tdr_para.len; + if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) + { +#if 1 + // simply print error message + LOG_ERROR("buffer is not enough, report to author"); + return ERROR_FAIL; +#else + u8 *buffer_tmp; + + // reallocate buffer + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdi_buffer, svf_buffer_index); + // svf_tdi_buffer isn't NULL here + free(svf_tdi_buffer); + svf_tdi_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdo_buffer, svf_buffer_index); + // svf_tdo_buffer isn't NULL here + free(svf_tdo_buffer); + svf_tdo_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_mask_buffer, svf_buffer_index); + // svf_mask_buffer isn't NULL here + free(svf_mask_buffer); + svf_mask_buffer = buffer_tmp; + + buffer_tmp = NULL; + svf_buffer_size = svf_buffer_index + ((i + 7) >> 3); +#endif + } + + // assemble dr data + i = 0; + buf_set_buf(svf_para.hdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hdr_para.len); + i += svf_para.hdr_para.len; + buf_set_buf(svf_para.sdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sdr_para.len); + i += svf_para.sdr_para.len; + buf_set_buf(svf_para.tdr_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tdr_para.len); + i += svf_para.tdr_para.len; + + // add check data + if (svf_para.sdr_para.data_mask & XXR_TDO) + { + // assemble dr mask data + i = 0; + buf_set_buf(svf_para.hdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hdr_para.len); + i += svf_para.hdr_para.len; + buf_set_buf(svf_para.sdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sdr_para.len); + i += svf_para.sdr_para.len; + buf_set_buf(svf_para.tdr_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tdr_para.len); + i += svf_para.tdr_para.len; + // assemble dr check data + i = 0; + buf_set_buf(svf_para.hdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hdr_para.len); + i += svf_para.hdr_para.len; + buf_set_buf(svf_para.sdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sdr_para.len); + i += svf_para.sdr_para.len; + buf_set_buf(svf_para.tdr_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tdr_para.len); + i += svf_para.tdr_para.len; + + svf_add_check_para(1, svf_buffer_index, i); + } + else + { + svf_add_check_para(0, svf_buffer_index, i); + } + field.tap = tap; + field.num_bits = i; + field.out_value = &svf_tdi_buffer[svf_buffer_index]; + field.out_mask = NULL; + field.in_value = &svf_tdi_buffer[svf_buffer_index]; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state); + + svf_buffer_index += (i + 7) >> 3; + } + else if (SIR == command) + { + // check buffer size first, reallocate if necessary + i = svf_para.hir_para.len + svf_para.sir_para.len + svf_para.tir_para.len; + if ((svf_buffer_size - svf_buffer_index) < ((i + 7) >> 3)) + { +#if 1 + // simply print error message + LOG_ERROR("buffer is not enough, report to author"); + return ERROR_FAIL; +#else + u8 *buffer_tmp; + + // reallocate buffer + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdi_buffer, svf_buffer_index); + // svf_tdi_buffer isn't NULL here + free(svf_tdi_buffer); + svf_tdi_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_tdo_buffer, svf_buffer_index); + // svf_tdo_buffer isn't NULL here + free(svf_tdo_buffer); + svf_tdo_buffer = buffer_tmp; + + buffer_tmp = (u8 *)malloc(svf_buffer_index + ((i + 7) >> 3)); + if (NULL == buffer_tmp) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + memcpy(buffer_tmp, svf_mask_buffer, svf_buffer_index); + // svf_mask_buffer isn't NULL here + free(svf_mask_buffer); + svf_mask_buffer = buffer_tmp; + + buffer_tmp = NULL; + svf_buffer_size = svf_buffer_index + ((i + 7) >> 3); +#endif + } + + // assemble ir data + i = 0; + buf_set_buf(svf_para.hir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.hir_para.len); + i += svf_para.hir_para.len; + buf_set_buf(svf_para.sir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.sir_para.len); + i += svf_para.sir_para.len; + buf_set_buf(svf_para.tir_para.tdi, 0, &svf_tdi_buffer[svf_buffer_index], i, svf_para.tir_para.len); + i += svf_para.tir_para.len; + + // add check data + if (svf_para.sir_para.data_mask & XXR_TDO) + { + // assemble dr mask data + i = 0; + buf_set_buf(svf_para.hir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.hir_para.len); + i += svf_para.hir_para.len; + buf_set_buf(svf_para.sir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.sir_para.len); + i += svf_para.sir_para.len; + buf_set_buf(svf_para.tir_para.mask, 0, &svf_mask_buffer[svf_buffer_index], i, svf_para.tir_para.len); + i += svf_para.tir_para.len; + // assemble dr check data + i = 0; + buf_set_buf(svf_para.hir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.hir_para.len); + i += svf_para.hir_para.len; + buf_set_buf(svf_para.sir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.sir_para.len); + i += svf_para.sir_para.len; + buf_set_buf(svf_para.tir_para.tdo, 0, &svf_tdo_buffer[svf_buffer_index], i, svf_para.tir_para.len); + i += svf_para.tir_para.len; + + svf_add_check_para(1, svf_buffer_index, i); + } + else + { + svf_add_check_para(0, svf_buffer_index, i); + } + field.tap = tap; + field.num_bits = i; + field.out_value = &svf_tdi_buffer[svf_buffer_index]; + field.out_mask = NULL; + field.in_value = &svf_tdi_buffer[svf_buffer_index]; + field.in_check_value = NULL; + field.in_check_mask = NULL; + field.in_handler = NULL; + field.in_handler_priv = NULL; + jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state); + + svf_buffer_index += (i + 7) >> 3; + } + break; + case PIO: + case PIOMAP: + LOG_ERROR("PIO and PIOMAP are not supported"); + return ERROR_FAIL; + break; + case RUNTEST: + // RUNTEST [run_state] run_count run_clk [min_time SEC [MAXIMUM max_time SEC]] [ENDSTATE end_state] + // RUNTEST [run_state] min_time SEC [MAXIMUM max_time SEC] [ENDSTATE end_state] + if ((num_of_argu < 3) && (num_of_argu > 11)) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + // init + run_count = 0; + min_time = 0; + max_time = 0; + i = 1; + // run_state + i_tmp = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_valid(i_tmp)) + { + if (svf_tap_state_is_stable(i_tmp)) + { + svf_para.runtest_run_state = i_tmp; + + // When a run_state is specified, the new run_state becomes the default end_state + svf_para.runtest_end_state = i_tmp; + LOG_DEBUG("\trun_state = %s", svf_tap_state_name[svf_para.runtest_run_state]); + i++; + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]); + return ERROR_FAIL; + } + } + // run_count run_clk + if (((i + 2) <= num_of_argu) && strcmp(argus[i + 1], "SEC")) + { + if (!strcmp(argus[i + 1], "TCK")) + { + // clock source is TCK + run_count = atoi(argus[i]); + LOG_DEBUG("\trun_count@TCK = %d", run_count); + } + else + { + LOG_ERROR("%s not supported for clock", argus[i + 1]); + return ERROR_FAIL; + } + i += 2; + } + // min_time SEC + if (((i + 2) <= num_of_argu) && !strcmp(argus[i + 1], "SEC")) + { + min_time = atof(argus[i]); + LOG_DEBUG("\tmin_time = %fs", min_time); + i += 2; + } + // MAXIMUM max_time SEC + if (((i + 3) <= num_of_argu) && !strcmp(argus[i], "MAXIMUM") && !strcmp(argus[i + 2], "SEC")) + { + max_time = atof(argus[i + 1]); + LOG_DEBUG("\tmax_time = %fs", max_time); + i += 3; + } + // ENDSTATE end_state + if (((i + 2) <= num_of_argu) && !strcmp(argus[i], "ENDSTATE")) + { + i_tmp = svf_find_string_in_array(argus[i + 1], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_stable(i_tmp)) + { + svf_para.runtest_end_state = i_tmp; + LOG_DEBUG("\tend_state = %s", svf_tap_state_name[svf_para.runtest_end_state]); + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[i_tmp]); + return ERROR_FAIL; + } + i += 2; + } + // calculate run_count + if ((0 == run_count) && (min_time > 0)) + { + run_count = min_time * svf_para.frequency; + } + // all parameter should be parsed + if (i == num_of_argu) + { + if (run_count > 0) + { + // TODO: do runtest + if (svf_para.runtest_run_state != TAP_IDLE) + { + // RUNTEST can only executed in TAP_IDLE + LOG_ERROR("cannot runtest in %s state", svf_tap_state_name[svf_para.runtest_run_state]); + return ERROR_FAIL; + } + jtag_add_runtest(run_count, svf_para.runtest_end_state); + } + } + else + { + LOG_ERROR("fail to parse parameter of RUNTEST, %d out of %d is parsed", i, num_of_argu); + return ERROR_FAIL; + } + break; + case STATE: + // STATE [pathstate1 [pathstate2 ...[pathstaten]]] stable_state + if (num_of_argu < 2) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + if (num_of_argu > 2) + { + // STATE pathstate1 ... stable_state + path = (tap_state_t *)malloc((num_of_argu - 1) * sizeof(tap_state_t)); + if (NULL == path) + { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + for (i = 1; i < num_of_argu; i++) + { + path[i - 1] = svf_find_string_in_array(argus[i], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (!svf_tap_state_is_valid(path[i - 1])) + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[path[i - 1]]); + return ERROR_FAIL; + } + if (TAP_RESET == path[i - 1]) + { + LOG_ERROR("TAP_RESET is not allowed in pathmove"); + return ERROR_FAIL; + } + } + if (svf_tap_state_is_stable(path[num_of_argu - 1])) + { + // last state MUST be stable state + // TODO: call path_move + jtag_add_pathmove(num_of_argu - 1, path); + LOG_DEBUG("\tmove to %s by path_move", svf_tap_state_name[path[num_of_argu - 1]]); + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[path[num_of_argu - 1]]); + return ERROR_FAIL; + } + if (NULL != path) + { + free(path); + path = NULL; + } + } + else + { + // STATE stable_state + state = svf_find_string_in_array(argus[1], (char **)svf_tap_state_name, dimof(svf_tap_state_name)); + if (svf_tap_state_is_stable(state)) + { + // TODO: move to state + last_cmd = jtag_get_last_command_p(); + *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t)); + last_comand_pointer = &((*last_cmd)->next); + (*last_cmd)->next = NULL; + (*last_cmd)->type = JTAG_STATEMOVE; + (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t)); + (*last_cmd)->cmd.statemove->end_state = state; + + LOG_DEBUG("\tmove to %s by state_move", svf_tap_state_name[state]); + } + else + { + LOG_ERROR("%s is not valid state", svf_tap_state_name[state]); + return ERROR_FAIL; + } + } + break; + case TRST: + // TRST trst_mode + if (num_of_argu != 2) + { + LOG_ERROR("invalid parameter of %s", argus[0]); + return ERROR_FAIL; + } + if (svf_para.trst_mode != TRST_ABSENT) + { + i_tmp = svf_find_string_in_array(argus[1], (char **)svf_trst_mode_name, dimof(svf_trst_mode_name)); + switch (i_tmp) + { + case TRST_ON: + jtag_add_reset(1, 0); + break; + case TRST_OFF: + jtag_add_reset(1, 1); + break; + case TRST_Z: + break; + case TRST_ABSENT: + break; + default: + LOG_ERROR("unknown TRST mode: %s", argus[1]); + return ERROR_FAIL; + } + svf_para.trst_mode = i_tmp; + LOG_DEBUG("\ttrst_mode = %s", svf_trst_mode_name[svf_para.trst_mode]); + } + else + { + LOG_ERROR("can not accpet TRST command if trst_mode is ABSENT"); + return ERROR_FAIL; + } + break; + default: + LOG_ERROR("invalid svf command: %s", argus[0]); + return ERROR_FAIL; + break; + } + + if (debug_level >= LOG_LVL_DEBUG) + { + // for convenient debugging, execute tap if possible + if ((svf_buffer_index > 0) && \ + (((command != STATE) && (command != RUNTEST)) || \ + ((command == STATE) && (num_of_argu == 2)))) + { + // there is data to be executed + if (ERROR_OK != jtag_execute_queue()) + { + return ERROR_FAIL; + } + // output debug info + if ((SIR == command) || (SDR == command)) + { + LOG_DEBUG("\tTDO read = 0x%X", (*(int*)svf_tdi_buffer) & ((1 << (svf_check_tdo_para[0].bit_len)) - 1)); + } + if (ERROR_OK != svf_check_tdo()) + { + return ERROR_FAIL; + } + + svf_buffer_index = 0; + } + } + else + { + // for fast executing, execute tap if necessary + // half of the buffer is for the next command + if (((svf_buffer_index >= SVF_MAX_BUFFER_SIZE_TO_COMMIT) || (svf_check_tdo_para_index >= SVF_CHECK_TDO_PARA_SIZE / 2)) && \ + (((command != STATE) && (command != RUNTEST)) || \ + ((command == STATE) && (num_of_argu == 2)))) + { + if (ERROR_OK != jtag_execute_queue()) + { + return ERROR_FAIL; + } + else if (ERROR_OK != svf_check_tdo()) + { + return ERROR_FAIL; + } + + svf_buffer_index = 0; + } + } + + return ERROR_OK; +} diff --git a/src/svf/svf.h b/src/svf/svf.h new file mode 100644 index 00000000..822cad22 --- /dev/null +++ b/src/svf/svf.h @@ -0,0 +1,27 @@ +/*************************************************************************** + * Copyright (C) 2009 by Simon Qian * + * SimonQian@SimonQian.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef SVF_H +#define SVF_H + +#include "command.h" + +extern int svf_register_commands(struct command_context_s *cmd_ctx); + +#endif /* SVF_H */ |