ZY1000 code
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 25 Sep 2008 14:31:10 +0000 (14:31 +0000)
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 25 Sep 2008 14:31:10 +0000 (14:31 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@1005 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/Makefile.am
src/ecosboard.c [new file with mode: 0644]
src/jtag/Makefile.am
src/jtag/zy1000.c [new file with mode: 0644]

index 81de281..d04308e 100644 (file)
@@ -1,7 +1,7 @@
 bin_PROGRAMS = openocd
 
 if ECOSBOARD
-MAINFILE = $(ECOS_SOURCE_FILES)/ecosboard.c
+MAINFILE = ecosboard.c
 else
 MAINFILE = main.c
 endif
diff --git a/src/ecosboard.c b/src/ecosboard.c
new file mode 100644 (file)
index 0000000..44c0f0b
--- /dev/null
@@ -0,0 +1,2403 @@
+/***************************************************************************\r
+ *   Copyright (C) 2007-2008 by Øyvind Harboe                              *\r
+ *                                                                         *\r
+ *   This program is free software; you can redistribute it and/or modify  *\r
+ *   it under the terms of the GNU General Public License as published by  *\r
+ *   the Free Software Foundation; either version 2 of the License, or     *\r
+ *   (at your option) any later version.                                   *\r
+ *                                                                         *\r
+ *   This program is distributed in the hope that it will be useful,       *\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
+ *   GNU General Public License for more details.                          *\r
+ *                                                                         *\r
+ *   You should have received a copy of the GNU General Public License     *\r
+ *   along with this program; if not, write to the                         *\r
+ *   Free Software Foundation, Inc.,                                       *\r
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
+ ***************************************************************************/\r
+\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+#include "log.h"\r
+#include "types.h"\r
+#include "jtag.h"\r
+#include "configuration.h"\r
+#include "xsvf.h"\r
+#include "target.h"\r
+#include "flash.h"\r
+#include "nand.h"\r
+#include "pld.h"\r
+\r
+#include "command.h"\r
+#include "server.h"\r
+#include "telnet_server.h"\r
+#include "gdb_server.h"\r
+\r
+#include <time_support.h>\r
+#include <sys/time.h>\r
+#include <sys/types.h>\r
+#include <strings.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+\r
+#include <cyg/io/flash.h>\r
+#include <pkgconf/fs_jffs2.h>  // Address of JFFS2\r
+#include <network.h>\r
+\r
+#include <fcntl.h>\r
+#include <sys/stat.h>\r
+#include <cyg/fileio/fileio.h>\r
+#include <dirent.h>\r
+#include <cyg/athttpd/http.h>\r
+#include <cyg/athttpd/socket.h>\r
+#include <cyg/athttpd/handler.h>\r
+#include <cyg/athttpd/cgi.h>\r
+#include <cyg/athttpd/forms.h>\r
+#include <cyg/hal/hal_diag.h>\r
+#include <cyg/kernel/kapi.h>\r
+#include <cyg/io/serialio.h>\r
+#include <cyg/io/io.h>\r
+#include <netinet/tcp.h>\r
+#include "rom.h"\r
+#include <sys/ioctl.h>\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#include <net/if.h>\r
+#include <arpa/inet.h>\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <netdb.h>\r
+#include <netinet/in.h>\r
+#include <unistd.h>\r
+#include <arpa/inet.h>\r
+#include <stdio.h>\r
+#include <ifaddrs.h>\r
+#include <string.h>\r
+\r
+#include <unistd.h>\r
+#include <stdio.h>\r
+#define MAX_IFS 64\r
+#if defined(CYGPKG_NET_FREEBSD_STACK)\r
+#include <tftp_support.h>\r
+/* posix compatibility broken*/\r
+struct tftpd_fileops fileops =\r
+{\r
+       (int (*)(const char *, int))open,\r
+       close,\r
+       (int (*)(int, const void *, int))write,\r
+       ( int (*)(int, void *, int))read\r
+};\r
+\r
+#endif\r
+\r
+#define ZYLIN_VERSION "1.42"\r
+#define ZYLIN_DATE __DATE__\r
+#define ZYLIN_TIME __TIME__\r
+#define ZYLIN_OPENOCD 921\r
+#define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME\r
+#define ZYLIN_CONFIG_DIR "/config/settings"\r
+\r
+void diag_write(char *buf, int len)\r
+{\r
+       int j;\r
+       for (j = 0; j < len; j++)\r
+       {\r
+               diag_printf("%c", buf[j]);\r
+       }\r
+}\r
+\r
+static bool serialLog = true;\r
+static bool writeLog = true;\r
+\r
+\r
+struct FastLoad\r
+{\r
+       u32 address;\r
+       u8 *data;\r
+       int length;\r
+\r
+};\r
+\r
+static int fastload_num;\r
+static struct FastLoad *fastload;\r
+\r
+static void free_fastload()\r
+{\r
+       if (fastload!=NULL)\r
+       {\r
+               int i;\r
+               for (i=0; i<fastload_num; i++)\r
+               {\r
+                       if (fastload[i].data)\r
+                               free(fastload[i].data);\r
+               }\r
+               free(fastload);\r
+               fastload=NULL;\r
+       }\r
+}\r
+\r
+\r
+int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       u8 *buffer;\r
+       u32 buf_cnt;\r
+       u32 image_size;\r
+       u32 min_address=0;\r
+       u32 max_address=0xffffffff;\r
+       int i;\r
+       int retval;\r
+\r
+       image_t image;\r
+\r
+       duration_t duration;\r
+       char *duration_text;\r
+\r
+       if ((argc < 1)||(argc > 5))\r
+       {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+\r
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */\r
+       if (argc >= 2)\r
+       {\r
+               image.base_address_set = 1;\r
+               image.base_address = strtoul(args[1], NULL, 0);\r
+       }\r
+       else\r
+       {\r
+               image.base_address_set = 0;\r
+       }\r
+\r
+\r
+       image.start_address_set = 0;\r
+\r
+       if (argc>=4)\r
+       {\r
+               min_address=strtoul(args[3], NULL, 0);\r
+       }\r
+       if (argc>=5)\r
+       {\r
+               max_address=strtoul(args[4], NULL, 0)+min_address;\r
+       }\r
+\r
+       if (min_address>max_address)\r
+       {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+\r
+       duration_start_measure(&duration);\r
+\r
+       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
+       {\r
+               return ERROR_OK;\r
+       }\r
+\r
+       image_size = 0x0;\r
+       retval = ERROR_OK;\r
+       fastload_num=image.num_sections;\r
+       fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);\r
+       if (fastload==NULL)\r
+       {\r
+               image_close(&image);\r
+               return ERROR_FAIL;\r
+       }\r
+       memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);\r
+       for (i = 0; i < image.num_sections; i++)\r
+       {\r
+               buffer = malloc(image.sections[i].size);\r
+               if (buffer == NULL)\r
+               {\r
+                       command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);\r
+                       break;\r
+               }\r
+\r
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)\r
+               {\r
+                       free(buffer);\r
+                       break;\r
+               }\r
+\r
+               u32 offset=0;\r
+               u32 length=buf_cnt;\r
+\r
+\r
+               /* DANGER!!! beware of unsigned comparision here!!! */\r
+\r
+               if ((image.sections[i].base_address+buf_cnt>=min_address)&&\r
+                               (image.sections[i].base_address<max_address))\r
+               {\r
+                       if (image.sections[i].base_address<min_address)\r
+                       {\r
+                               /* clip addresses below */\r
+                               offset+=min_address-image.sections[i].base_address;\r
+                               length-=offset;\r
+                       }\r
+\r
+                       if (image.sections[i].base_address+buf_cnt>max_address)\r
+                       {\r
+                               length-=(image.sections[i].base_address+buf_cnt)-max_address;\r
+                       }\r
+\r
+                       fastload[i].address=image.sections[i].base_address+offset;\r
+                       fastload[i].data=malloc(length);\r
+                       if (fastload[i].data==NULL)\r
+                       {\r
+                               free(buffer);\r
+                               break;\r
+                       }\r
+                       memcpy(fastload[i].data, buffer+offset, length);\r
+                       fastload[i].length=length;\r
+\r
+                       image_size += length;\r
+                       command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);\r
+               }\r
+\r
+               free(buffer);\r
+       }\r
+\r
+       duration_stop_measure(&duration, &duration_text);\r
+       if (retval==ERROR_OK)\r
+       {\r
+               command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);\r
+       }\r
+       free(duration_text);\r
+\r
+       image_close(&image);\r
+\r
+       if (retval!=ERROR_OK)\r
+       {\r
+               free_fastload();\r
+       }\r
+\r
+       return retval;\r
+}\r
+\r
+int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       if (argc>0)\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       if (fastload==NULL)\r
+       {\r
+               LOG_ERROR("No image in memory");\r
+               return ERROR_FAIL;\r
+       }\r
+       int i;\r
+       int ms=timeval_ms();\r
+       int size=0;\r
+       for (i=0; i<fastload_num;i++)\r
+       {\r
+               int retval;\r
+               target_t *target = get_current_target(cmd_ctx);\r
+               if ((retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data)) != ERROR_OK)\r
+               {\r
+                       return retval;\r
+               }\r
+               size+=fastload[i].length;\r
+       }\r
+       int after=timeval_ms();\r
+       command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+/* Give TELNET a way to find out what version this is */\r
+int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,\r
+               char **args, int argc)\r
+{\r
+       if (argc > 1)\r
+       {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+       if (argc == 0)\r
+       {\r
+               command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);\r
+       } else if (strcmp("openocd", args[0])==0)\r
+       {\r
+               command_print(cmd_ctx, "%d", ZYLIN_OPENOCD);\r
+       } else if (strcmp("zy1000", args[0])==0)\r
+       {\r
+               command_print(cmd_ctx, "%s", ZYLIN_VERSION);\r
+       } else if (strcmp("date", args[0])==0)\r
+       {\r
+               command_print(cmd_ctx, "%s", ZYLIN_DATE);\r
+       } else\r
+       {\r
+               return ERROR_COMMAND_SYNTAX_ERROR;\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+extern flash_driver_t *flash_drivers[];\r
+extern target_type_t *target_types[];\r
+\r
+#ifdef CYGPKG_PROFILE_GPROF\r
+#include <cyg/profile/profile.h>\r
+\r
+extern char _stext, _etext; // Defined by the linker\r
+\r
+void start_profile(void)\r
+{\r
+       // This starts up the system-wide profiling, gathering\r
+       // profile information on all of the code, with a 16 byte\r
+       // "bucket" size, at a rate of 100us/profile hit.\r
+       // Note: a bucket size of 16 will give pretty good function\r
+       //       resolution.  Much smaller and the buffer becomes\r
+       //       much too large for very little gain.\r
+       // Note: a timer period of 100us is also a reasonable\r
+       //       compromise.  Any smaller and the overhead of\r
+       //       handling the timter (profile) interrupt could\r
+       //       swamp the system.  A fast processor might get\r
+       //       by with a smaller value, but a slow one could\r
+       //       even be swamped by this value.  If the value is\r
+       //       too large, the usefulness of the profile is reduced.\r
+\r
+       // no more interrupts than 1/10ms.\r
+       //    profile_on(&_stext, &_etext, 16, 10000); // DRAM\r
+       //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM\r
+       profile_on(0, &_etext, 16, 10000); // SRAM & DRAM\r
+}\r
+#endif\r
+\r
+// launch GDB server if a config file exists\r
+bool zylinjtag_parse_config_file(struct command_context_s *cmd_ctx, const char *config_file_name)\r
+{\r
+       bool foundFile = false;\r
+       FILE *config_file = NULL;\r
+       command_print(cmd_ctx, "executing config file %s", config_file_name);\r
+       config_file = fopen(config_file_name, "r");\r
+       if (config_file)\r
+       {\r
+               fclose(config_file);\r
+               int retval;\r
+               retval = command_run_linef(cmd_ctx, "script %s", config_file_name);\r
+               if (retval == ERROR_OK)\r
+               {\r
+                       foundFile = true;\r
+               }\r
+               else\r
+               {\r
+                       command_print(cmd_ctx, "Failed executing %s %d", config_file_name, retval);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               command_print(cmd_ctx, "No %s found", config_file_name);\r
+       }\r
+\r
+       return foundFile;\r
+}\r
+\r
+extern int eth0_up;\r
+static FILE *log;\r
+\r
+static char reboot_stack[2048];\r
+\r
+\r
+static void\r
+zylinjtag_reboot(cyg_addrword_t data)\r
+{\r
+       serialLog = true;\r
+       diag_printf("Rebooting in 100 ticks..\n");\r
+       cyg_thread_delay(100);\r
+       diag_printf("Unmounting /config..\n");\r
+       umount("/config");\r
+       diag_printf("Rebooting..\n");\r
+       HAL_PLATFORM_RESET();\r
+}\r
+static cyg_thread zylinjtag_thread_object;\r
+static cyg_handle_t zylinjtag_thread_handle;\r
+\r
+void reboot(void)\r
+{\r
+    cyg_thread_create(1,\r
+                      zylinjtag_reboot,\r
+                      (cyg_addrword_t)0,\r
+                      "reboot Thread",\r
+                      (void *)reboot_stack,\r
+                      sizeof(reboot_stack),\r
+                      &zylinjtag_thread_handle,\r
+                      &zylinjtag_thread_object);\r
+       cyg_thread_resume(zylinjtag_thread_handle);\r
+}\r
+\r
+int configuration_output_handler(struct command_context_s *context, const char* line)\r
+{\r
+       diag_printf("%s", line);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int zy1000_configuration_output_handler_log(struct command_context_s *context, const char* line)\r
+{\r
+       LOG_USER_N("%s", line);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,\r
+               char **args, int argc)\r
+{\r
+       if (argc != 1)\r
+       {\r
+               command_print(cmd_ctx, "rm <filename>");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       if (unlink(args[0]) != 0)\r
+       {\r
+               command_print(cmd_ctx, "failed: %d", errno);\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int loadFile(const char *fileName, void **data, int *len);\r
+\r
+int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,\r
+               char **args, int argc)\r
+{\r
+       if (argc != 1)\r
+       {\r
+               command_print(cmd_ctx, "cat <filename>");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       // NOTE!!! we only have line printing capability so we print the entire file as a single line.\r
+       void *data;\r
+       int len;\r
+\r
+       int retval = loadFile(args[0], &data, &len);\r
+       if (retval == ERROR_OK)\r
+       {\r
+               command_print(cmd_ctx, "%s", data);\r
+               free(data);\r
+       }\r
+       else\r
+       {\r
+               command_print(cmd_ctx, "%s not found %d", args[0], retval);\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,\r
+               char **args, int argc)\r
+{\r
+       if (argc != 1)\r
+       {\r
+               command_print(cmd_ctx, "trunc <filename>");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       FILE *config_file = NULL;\r
+       config_file = fopen(args[0], "w");\r
+       if (config_file != NULL)\r
+               fclose(config_file);\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       static int prev = 0;\r
+       struct mallinfo info;\r
+\r
+       if (argc != 0)\r
+       {\r
+               command_print(cmd_ctx, "meminfo");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       info = mallinfo();\r
+\r
+       if (prev > 0)\r
+       {\r
+               command_print(cmd_ctx, "Diff:            %d", prev - info.fordblks);\r
+       }\r
+       prev = info.fordblks;\r
+\r
+       command_print(cmd_ctx, "Available ram:   %d", info.fordblks );\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+static bool savePower;\r
+\r
+static void setPower(bool power)\r
+{\r
+       savePower = power;\r
+       if (power)\r
+       {\r
+               HAL_WRITE_UINT32(0x08000014, 0x8);\r
+       } else\r
+       {\r
+               HAL_WRITE_UINT32(0x08000010, 0x8);\r
+       }\r
+}\r
+\r
+int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       if (argc > 1)\r
+       {\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       if (argc == 1)\r
+       {\r
+               if (strcmp(args[0], "on") == 0)\r
+               {\r
+                       setPower(1);\r
+               }\r
+               else if (strcmp(args[0], "off") == 0)\r
+               {\r
+                       setPower(0);\r
+               } else\r
+               {\r
+                       command_print(cmd_ctx, "arg is \"on\" or \"off\"");\r
+                       return ERROR_INVALID_ARGUMENTS;\r
+               }\r
+       }\r
+\r
+       command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,\r
+               char **args, int argc)\r
+{\r
+       if (argc < 1)\r
+       {\r
+               command_print(cmd_ctx,\r
+                               "append <filename> [<string1>, [<string2>, ...]]");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       FILE *config_file = NULL;\r
+       config_file = fopen(args[0], "a");\r
+       if (config_file != NULL)\r
+       {\r
+               int i;\r
+               fseek(config_file, 0, SEEK_END);\r
+\r
+               for (i = 1; i < argc; i++)\r
+               {\r
+                       fwrite(args[i], strlen(args[i]), 1, config_file);\r
+                       if (i != argc - 1)\r
+                       {\r
+                               fwrite(" ", 1, 1, config_file);\r
+                       }\r
+               }\r
+               fwrite("\n", 1, 1, config_file);\r
+               fclose(config_file);\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+extern int telnet_socket;\r
+\r
+int readMore(int fd, void *data, int length)\r
+{\r
+       /* used in select() */\r
+       fd_set read_fds;\r
+\r
+       /* monitor sockets for acitvity */\r
+       int fd_max = 1;\r
+       FD_ZERO(&read_fds);\r
+       /* listen for new connections */\r
+       FD_SET(fd, &read_fds);\r
+\r
+       // Maximum 5 seconds.\r
+       struct timeval tv;\r
+       tv.tv_sec = 5;\r
+       tv.tv_usec = 0;\r
+\r
+       int retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);\r
+       if (retval == 0)\r
+       {\r
+               diag_printf("Timed out waiting for binary payload\n");\r
+               return -1;\r
+       }\r
+       if (retval != 1)\r
+               return -1;\r
+\r
+       return read_socket(fd, data, length);\r
+}\r
+\r
+int readAll(int fd, void *data, int length)\r
+{\r
+       int pos = 0;\r
+       for (;;)\r
+       {\r
+               int actual = readMore(fd, ((char *) data) + pos, length - pos);\r
+               //              diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);\r
+               if (actual <= 0)\r
+                       return -1;\r
+               pos += actual;\r
+               if (pos == length)\r
+                       break;\r
+       }\r
+       return length;\r
+}\r
+\r
+int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       cyg_uint32 value;\r
+       if (argc != 1)\r
+       {\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+       HAL_READ_UINT32(strtoul(args[0], NULL, 0), value);\r
+       command_print(cmd_ctx, "0x%x : 0x%x", strtoul(args[0], NULL, 0), value);\r
+       return ERROR_OK;\r
+}\r
+\r
+int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       if (argc != 2)\r
+       {\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+       HAL_WRITE_UINT32(strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0));\r
+       return ERROR_OK;\r
+}\r
+\r
+int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       if (argc != 2)\r
+       {\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       // NOTE!!! we only have line printing capability so we print the entire file as a single line.\r
+       void *data;\r
+       int len;\r
+\r
+       int retval = loadFile(args[0], &data, &len);\r
+       if (retval != ERROR_OK)\r
+               return retval;\r
+\r
+       FILE *f = fopen(args[1], "wb");\r
+       if (f == NULL)\r
+               retval = ERROR_INVALID_ARGUMENTS;\r
+\r
+       int pos = 0;\r
+       for (;;)\r
+       {\r
+               int chunk = len - pos;\r
+               static const int maxChunk = 512 * 1024; // ~1/sec\r
+               if (chunk > maxChunk)\r
+               {\r
+                       chunk = maxChunk;\r
+               }\r
+\r
+               if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))\r
+                       retval = ERROR_INVALID_ARGUMENTS;\r
+\r
+               if (retval != ERROR_OK)\r
+               {\r
+                       break;\r
+               }\r
+\r
+               command_print(cmd_ctx, "%d", len - pos);\r
+\r
+               pos += chunk;\r
+\r
+               if (pos == len)\r
+                       break;\r
+       }\r
+\r
+       if (retval == ERROR_OK)\r
+       {\r
+               command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);\r
+       } else\r
+       {\r
+               command_print(cmd_ctx, "Failed: %d", retval);\r
+       }\r
+\r
+       if (data != NULL)\r
+               free(data);\r
+       if (f != NULL)\r
+               fclose(f);\r
+\r
+       if (retval != ERROR_OK)\r
+               unlink(args[1]);\r
+\r
+       return retval;\r
+}\r
+\r
+#ifdef CYGPKG_PROFILE_GPROF\r
+extern void start_profile();\r
+\r
+int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       command_print(cmd_ctx, "Profiling started");\r
+       start_profile();\r
+       return ERROR_OK;\r
+}\r
+\r
+#endif\r
+\r
+externC void phi_init_all_network_interfaces();\r
+\r
+command_context_t *cmd_ctx;\r
+\r
+static bool webRunning = false;\r
+\r
+void keep_webserver()\r
+{\r
+       // Target initialisation is only attempted at startup, so we sleep forever and\r
+       // let the http server bail us out(i.e. get config files set up).\r
+       diag_printf("OpenOCD has invoked exit().\n"\r
+               "Use web server to correct any configuration settings and reboot.\n");\r
+       if (!webRunning)\r
+               reboot();\r
+\r
+       // exit() will terminate the current thread and we we'll then sleep eternally or\r
+       // we'll have a reboot scheduled.\r
+}\r
+\r
+extern void printDccChar(char c);\r
+\r
+static char logBuffer[128 * 1024];\r
+static const int logSize = sizeof(logBuffer);\r
+int writePtr = 0;\r
+int logCount = 0;\r
+\r
+void _zylinjtag_diag_write_char(char c, void **param)\r
+{\r
+       if (writeLog)\r
+       {\r
+               logBuffer[writePtr] = c;\r
+               writePtr = (writePtr + 1) % logSize;\r
+               logCount++;\r
+       }\r
+       if (serialLog)\r
+       {\r
+               if (c == '\n')\r
+               {\r
+                       HAL_DIAG_WRITE_CHAR('\r');\r
+               }\r
+               HAL_DIAG_WRITE_CHAR(c);\r
+       }\r
+\r
+       printDccChar(c);\r
+}\r
+\r
+#define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)\r
+\r
+#define IOSIZE 512\r
+static void copyfile(char *name2, char *name1)\r
+{\r
+\r
+       int err;\r
+       char buf[IOSIZE];\r
+       int fd1, fd2;\r
+       ssize_t done, wrote;\r
+\r
+       fd1 = open(name1, O_WRONLY | O_CREAT);\r
+       if (fd1 < 0)\r
+               SHOW_RESULT( open, fd1 );\r
+\r
+       fd2 = open(name2, O_RDONLY);\r
+       if (fd2 < 0)\r
+               SHOW_RESULT( open, fd2 );\r
+\r
+       for (;;)\r
+       {\r
+               done = read(fd2, buf, IOSIZE );\r
+               if (done < 0)\r
+               {\r
+                       SHOW_RESULT( read, done );\r
+                       break;\r
+               }\r
+\r
+        if( done == 0 ) break;\r
+\r
+               wrote = write(fd1, buf, done);\r
+        if( wrote != done ) SHOW_RESULT( write, wrote );\r
+\r
+        if( wrote != done ) break;\r
+       }\r
+\r
+       err = close(fd1);\r
+    if( err < 0 ) SHOW_RESULT( close, err );\r
+\r
+       err = close(fd2);\r
+    if( err < 0 ) SHOW_RESULT( close, err );\r
+\r
+}\r
+static void copydir(char *name)\r
+{\r
+       int err;\r
+       DIR *dirp;\r
+\r
+       mkdir("/ram/cgi", 0777);\r
+\r
+       dirp = opendir(name);\r
+    if( dirp == NULL ) SHOW_RESULT( opendir, -1 );\r
+\r
+       for (;;)\r
+       {\r
+               struct dirent *entry = readdir(dirp);\r
+\r
+               if (entry == NULL)\r
+                       break;\r
+\r
+               if (strcmp(entry->d_name, ".") == 0)\r
+                       continue;\r
+               if (strcmp(entry->d_name, "..") == 0)\r
+                       continue;\r
+\r
+               bool isDir = false;\r
+               struct stat buf;\r
+               char fullPath[PATH_MAX];\r
+               strncpy(fullPath, name, PATH_MAX);\r
+               strcat(fullPath, "/");\r
+               strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));\r
+\r
+               if (stat(fullPath, &buf) == -1)\r
+               {\r
+                       diag_printf("unable to read status from %s", fullPath);\r
+                       break;\r
+               }\r
+               isDir = S_ISDIR(buf.st_mode) != 0;\r
+\r
+               if (isDir)\r
+                       continue;\r
+\r
+               //        diag_printf("<INFO>: entry %14s",entry->d_name);\r
+               char fullname[PATH_MAX];\r
+               char fullname2[PATH_MAX];\r
+\r
+               strcpy(fullname, name);\r
+               strcat(fullname, entry->d_name);\r
+\r
+               strcpy(fullname2, "/ram/cgi/");\r
+               strcat(fullname2, entry->d_name);\r
+               //        diag_printf("from %s to %s\n", fullname, fullname2);\r
+               copyfile(fullname, fullname2);\r
+\r
+               //       diag_printf("\n");\r
+       }\r
+\r
+       err = closedir(dirp);\r
+    if( err < 0 ) SHOW_RESULT( stat, err );\r
+}\r
+\r
+#if 0\r
+MTAB_ENTRY( romfs_mte1,\r
+               "/rom",\r
+               "romfs",\r
+               "",\r
+               (CYG_ADDRWORD) &filedata[0] );\r
+#endif\r
+\r
+void openocd_sleep_prelude()\r
+{\r
+       cyg_mutex_unlock(&httpstate.jim_lock);\r
+}\r
+\r
+void openocd_sleep_postlude()\r
+{\r
+       cyg_mutex_lock(&httpstate.jim_lock);\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_rm(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       int del;\r
+       if (argc != 2)\r
+       {\r
+               Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");\r
+               return JIM_ERR;\r
+       }\r
+\r
+       del = 0;\r
+       if (unlink(Jim_GetString(argv[1], NULL)) == 0)\r
+               del = 1;\r
+       if (rmdir(Jim_GetString(argv[1], NULL)) == 0)\r
+               del = 1;\r
+\r
+       return del ? JIM_OK : JIM_ERR;\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_ls(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       if (argc != 2)\r
+       {\r
+               Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");\r
+               return JIM_ERR;\r
+       }\r
+\r
+       char *name = (char*) Jim_GetString(argv[1], NULL);\r
+\r
+       DIR *dirp = NULL;\r
+       dirp = opendir(name);\r
+       if (dirp == NULL)\r
+       {\r
+               return JIM_ERR;\r
+       }\r
+       Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);\r
+\r
+       for (;;)\r
+       {\r
+               struct dirent *entry = NULL;\r
+               entry = readdir(dirp);\r
+               if (entry == NULL)\r
+                       break;\r
+\r
+               if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))\r
+                       continue;\r
+\r
+        Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));\r
+       }\r
+       closedir(dirp);\r
+\r
+       Jim_SetResult(interp, objPtr);\r
+\r
+       return JIM_OK;\r
+}\r
+\r
+\r
+static int\r
+zylinjtag_Jim_Command_getmem(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       if (argc != 3)\r
+       {\r
+               Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");\r
+               return JIM_ERR;\r
+       }\r
+\r
+       long address;\r
+       long length;\r
+       if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)\r
+               return JIM_ERR;\r
+       if (Jim_GetLong(interp, argv[2], &length) != JIM_OK)\r
+               return JIM_ERR;\r
+\r
+       if (length < 0 && length > (4096 * 1024))\r
+       {\r
+               Jim_WrongNumArgs(interp, 1, argv, "getmem ?dir?");\r
+               return JIM_ERR;\r
+       }\r
+\r
+       void *mem = malloc(length);\r
+       if (mem == NULL)\r
+               return JIM_ERR;\r
+\r
+       target_t *target = get_current_target(cmd_ctx);\r
+\r
+       int retval;\r
+       int size = 1;\r
+       int count = length;\r
+       if ((address % 4 == 0) && (count % 4 == 0))\r
+       {\r
+               size = 4;\r
+               count /= 4;\r
+       }\r
+\r
+       if ((retval  = target->type->read_memory(target, address, size, count, mem)) != ERROR_OK)\r
+       {\r
+               free(mem);\r
+               return JIM_ERR;\r
+       }\r
+\r
+       Jim_Obj *objPtr = Jim_NewStringObj(interp, mem, length);\r
+       Jim_SetResult(interp, objPtr);\r
+\r
+       free(mem);\r
+\r
+       return JIM_OK;\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_peek(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       if (argc != 2)\r
+       {\r
+               Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");\r
+               return JIM_ERR;\r
+       }\r
+\r
+       long address;\r
+       if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)\r
+               return JIM_ERR;\r
+\r
+       int value = *((volatile int *) address);\r
+\r
+       Jim_SetResult(interp, Jim_NewIntObj(interp, value));\r
+\r
+       return JIM_OK;\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_poke(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       if (argc != 3)\r
+       {\r
+               Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");\r
+               return JIM_ERR;\r
+       }\r
+\r
+       long address;\r
+       if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)\r
+               return JIM_ERR;\r
+       long value;\r
+       if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)\r
+               return JIM_ERR;\r
+\r
+       *((volatile int *) address) = value;\r
+\r
+       return JIM_OK;\r
+}\r
+\r
+\r
+\r
+static int\r
+zylinjtag_Jim_Command_flash(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       int retval;\r
+       u32 base = 0;\r
+       flash_bank_t *t = get_flash_bank_by_num_noprobe(0);\r
+       if (t != NULL)\r
+       {\r
+               base = t->base;\r
+               retval = JIM_OK;\r
+    } else\r
+       {\r
+               retval = JIM_ERR;\r
+       }\r
+\r
+       if (retval == JIM_OK)\r
+       {\r
+               Jim_SetResult(interp, Jim_NewIntObj(interp, base));\r
+       }\r
+\r
+       return retval;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+static int\r
+zylinjtag_Jim_Command_log(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);\r
+\r
+       if (logCount >= logSize)\r
+       {\r
+       Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer+logCount%logSize, logSize-logCount%logSize);\r
+       }\r
+       Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);\r
+\r
+       Jim_SetResult(interp, tclOutput);\r
+       return JIM_OK;\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_reboot(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       reboot();\r
+       return JIM_OK;\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_mac(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       int s;\r
+       struct ifreq ifr;\r
+       s = socket(AF_INET, SOCK_DGRAM, 0);\r
+       if (s >= 0)\r
+       {\r
+               strcpy(ifr.ifr_name, "eth0");\r
+               int res;\r
+               res = ioctl(s, SIOCGIFHWADDR, &ifr);\r
+               close(s);\r
+\r
+               if (res < 0)\r
+               {\r
+                       return JIM_OK;\r
+               }\r
+       }\r
+\r
+       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);\r
+\r
+       char hwaddr[512];\r
+       sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",\r
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],\r
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],\r
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],\r
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],\r
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],\r
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);\r
+\r
+       Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));\r
+\r
+       Jim_SetResult(interp, tclOutput);\r
+\r
+       return JIM_OK;\r
+}\r
+\r
+static int\r
+zylinjtag_Jim_Command_ip(Jim_Interp *interp,\r
+                                   int argc,\r
+               Jim_Obj * const *argv)\r
+{\r
+       Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);\r
+\r
+       struct ifaddrs *ifa = NULL, *ifp = NULL;\r
+\r
+       if (getifaddrs(&ifp) < 0)\r
+       {\r
+               return JIM_ERR;\r
+       }\r
+\r
+       for (ifa = ifp; ifa; ifa = ifa->ifa_next)\r
+       {\r
+               char ip[200];\r
+               socklen_t salen;\r
+\r
+               if (ifa->ifa_addr->sa_family == AF_INET)\r
+                       salen = sizeof(struct sockaddr_in);\r
+               else if (ifa->ifa_addr->sa_family == AF_INET6)\r
+                       salen = sizeof(struct sockaddr_in6);\r
+               else\r
+                       continue;\r
+\r
+               if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,\r
+                               NI_NUMERICHOST) < 0)\r
+               {\r
+                       continue;\r
+               }\r
+\r
+               Jim_AppendString(httpstate.jim_interp, tclOutput, ip, strlen(ip));\r
+               break;\r
+\r
+       }\r
+\r
+       freeifaddrs(ifp);\r
+\r
+       Jim_SetResult(interp, tclOutput);\r
+\r
+       return JIM_OK;\r
+}\r
+\r
+extern Jim_Interp *interp;\r
+\r
+static void zylinjtag_startNetwork()\r
+{\r
+       // Bring TCP/IP up immediately before we're ready to accept commands.\r
+       //\r
+       // That is as soon as a PING responds, we're accepting telnet sessions.\r
+#if defined(CYGPKG_NET_FREEBSD_STACK)\r
+       phi_init_all_network_interfaces();\r
+#else\r
+       lwip_init();\r
+#endif\r
+       if (!eth0_up)\r
+       {\r
+               diag_printf("Network not up and running\n");\r
+               exit(-1);\r
+       }\r
+#if defined(CYGPKG_NET_FREEBSD_STACK)\r
+       /*start TFTP*/\r
+       tftpd_start(69, &fileops);\r
+#endif\r
+\r
+       cyg_httpd_init_tcl_interpreter();\r
+\r
+       interp = httpstate.jim_interp;\r
+\r
+    Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "reboot", zylinjtag_Jim_Command_reboot, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);\r
+    Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);\r
+\r
+       cyg_httpd_start();\r
+\r
+       webRunning = true;\r
+\r
+       diag_printf("Web server running\n");\r
+}\r
+\r
+static bool readPowerDropout()\r
+{\r
+       cyg_uint32 state;\r
+       // sample and clear power dropout\r
+       HAL_WRITE_UINT32(0x08000010, 0x80);\r
+       HAL_READ_UINT32(0x08000010, state);\r
+       bool powerDropout;\r
+       powerDropout = (state & 0x80) != 0;\r
+       return powerDropout;\r
+}\r
+\r
+bool readSRST()\r
+{\r
+       cyg_uint32 state;\r
+       // sample and clear SRST sensing\r
+       HAL_WRITE_UINT32(0x08000010, 0x00000040);\r
+       HAL_READ_UINT32(0x08000010, state);\r
+       bool srstAsserted;\r
+       srstAsserted = (state & 0x40) != 0;\r
+       return srstAsserted;\r
+}\r
+\r
+// every 300ms we check for reset & powerdropout and issue a "reset halt" if\r
+// so.\r
+\r
+\r
+static int sense_handler(void *priv)\r
+{\r
+       struct command_context_s *cmd_ctx;\r
+       cmd_ctx = (struct command_context_s *) priv;\r
+\r
+       static bool prevSrstAsserted = false;\r
+       static bool prevPowerdropout = false;\r
+\r
+       bool powerDropout;\r
+       powerDropout = readPowerDropout();\r
+\r
+       bool powerRestored;\r
+       powerRestored = prevPowerdropout && !powerDropout;\r
+       if (powerRestored)\r
+       {\r
+               LOG_USER("Sensed power restore.");\r
+       }\r
+\r
+       cyg_tick_count_t current = cyg_current_time();\r
+       static cyg_tick_count_t lastPower = 0;\r
+       bool waitMore = lastPower + 200 > current;\r
+       if (powerDropout && !waitMore)\r
+       {\r
+               LOG_USER("Sensed power dropout.");\r
+               lastPower = current;\r
+       }\r
+\r
+       bool srstAsserted = readSRST();\r
+\r
+       bool srstDeasserted;\r
+       srstDeasserted = prevSrstAsserted && !srstAsserted;\r
+\r
+       static cyg_tick_count_t lastSrst = 0;\r
+       waitMore = lastSrst + 200 > current;\r
+       if (srstDeasserted && !waitMore)\r
+       {\r
+               LOG_USER("Sensed nSRST deasserted");\r
+               lastSrst = current;\r
+       }\r
+\r
+       if (!prevSrstAsserted && srstAsserted)\r
+       {\r
+               LOG_USER("Sensed nSRST asserted");\r
+       }\r
+\r
+       prevSrstAsserted = srstAsserted;\r
+       prevPowerdropout = powerDropout;\r
+\r
+       if (srstDeasserted || powerRestored)\r
+       {\r
+               /* Other than logging the event we can't do anything here.\r
+                * Issuing a reset is a particularly bad idea as we might\r
+                * be inside a reset already.\r
+                */\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+\r
+static void\r
+print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_t info)\r
+{\r
+       writeLog = false;\r
+       serialLog = true;\r
+       char *infoStr = "unknown";\r
+       switch (exception)\r
+       {\r
+       case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:\r
+               infoStr = "undefined instruction";\r
+               break;\r
+       case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:\r
+               infoStr = "software interrupt";\r
+               break;\r
+       case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:\r
+               infoStr = "abort prefetch";\r
+               break;\r
+       case CYGNUM_HAL_VECTOR_ABORT_DATA:\r
+               infoStr = "abort data";\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+\r
+       diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);\r
+\r
+       diag_printf("Dumping log\n---\n");\r
+       if (logCount >= logSize)\r
+       {\r
+               diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);\r
+       }\r
+       diag_write(logBuffer, writePtr);\r
+\r
+       diag_printf("---\nLogdump complete.\n");\r
+       diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);\r
+       diag_printf("\n---\nRebooting\n");\r
+       HAL_PLATFORM_RESET();\r
+\r
+}\r
+\r
+static void setHandler(cyg_code_t exception)\r
+{\r
+       cyg_exception_handler_t *old_handler;\r
+       cyg_addrword_t old_data;\r
+\r
+       cyg_exception_set_handler(exception,\r
+       print_exception_handler,\r
+       0,\r
+       &old_handler,\r
+       &old_data);\r
+}\r
+\r
+static cyg_thread zylinjtag_uart_thread_object;\r
+static cyg_handle_t zylinjtag_uart_thread_handle;\r
+static char uart_stack[4096];\r
+\r
+static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!\r
+static char backwardBuffer[1024];\r
+\r
+static cyg_io_handle_t serial_handle;\r
+\r
+void setNoDelay(int session, int flag)\r
+{\r
+#if 1\r
+       // This decreases latency dramatically for e.g. GDB load which\r
+       // does not have a sliding window protocol\r
+       //\r
+       // Can cause *lots* of TCP/IP packets to be sent and it would have\r
+       // to be enabled/disabled on the fly to avoid the CPU being\r
+       // overloaded...\r
+       setsockopt(session, /* socket affected */\r
+       IPPROTO_TCP, /* set option at TCP level */\r
+       TCP_NODELAY, /* name of option */\r
+       (char *) &flag, /* the cast is historical\r
+        cruft */\r
+       sizeof(int)); /* length of option value */\r
+#endif\r
+}\r
+\r
+struct\r
+{\r
+       int req;\r
+       int actual;\r
+       int req2;\r
+       int actual2;\r
+} tcpipSent[512 * 1024];\r
+int cur;\r
+\r
+static void\r
+zylinjtag_uart(cyg_addrword_t data)\r
+{\r
+       int so_reuseaddr_option = 1;\r
+\r
+       int fd;\r
+       if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)\r
+       {\r
+               LOG_ERROR("error creating socket: %s", strerror(errno));\r
+               exit(-1);\r
+       }\r
+\r
+       setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));\r
+\r
+       struct sockaddr_in sin;\r
+       unsigned int address_size;\r
+       address_size = sizeof(sin);\r
+       memset(&sin, 0, sizeof(sin));\r
+       sin.sin_family = AF_INET;\r
+       sin.sin_addr.s_addr = INADDR_ANY;\r
+       sin.sin_port = htons(5555);\r
+\r
+       if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)\r
+       {\r
+               LOG_ERROR("couldn't bind to socket: %s", strerror(errno));\r
+               exit(-1);\r
+       }\r
+\r
+       if (listen(fd, 1) == -1)\r
+       {\r
+               LOG_ERROR("couldn't listen on socket: %s", strerror(errno));\r
+               exit(-1);\r
+       }\r
+       //      socket_nonblock(fd);\r
+\r
+\r
+       for (;;)\r
+       {\r
+               int session = accept(fd, (struct sockaddr *) &sin, &address_size);\r
+               if (session < 0)\r
+               {\r
+                       continue;\r
+               }\r
+\r
+               setNoDelay(session, 1);\r
+               int oldopts = fcntl(session, F_GETFL, 0);\r
+               fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //\r
+\r
+               int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);\r
+               if (serHandle < 0)\r
+               {\r
+                       close(session);\r
+                       continue;\r
+               }\r
+\r
+               start_profile();\r
+               int actual = 0;\r
+               int actual2 = 0;\r
+               int pos, pos2;\r
+               pos = 0;\r
+               pos2 = 0;\r
+               cur = 0;\r
+               for (;;)\r
+               {\r
+                       fd_set write_fds;\r
+                       fd_set read_fds;\r
+                       FD_ZERO(&write_fds);\r
+                       FD_ZERO(&read_fds);\r
+                       int fd_max = -1;\r
+                       FD_SET(session, &read_fds);\r
+                       fd_max = session;\r
+                       FD_SET(serHandle, &read_fds);\r
+                       if (serHandle > fd_max)\r
+                       {\r
+                               fd_max = serHandle;\r
+                       }\r
+                       /* Wait... */\r
+\r
+                       cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received\r
+                       if ((actual == 0) && (actual2 == 0))\r
+                       {\r
+                               int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);\r
+                               if (retval <= 0)\r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (actual2 <= 0)\r
+                       {\r
+                               memset(backwardBuffer, 's', sizeof(backwardBuffer));\r
+                               actual2=read(serHandle, backwardBuffer, sizeof(backwardBuffer));\r
+                               if (actual2 < 0)\r
+                               {\r
+                                       if (errno != EAGAIN)\r
+                                       {\r
+                                               goto closeSession;\r
+                                       }\r
+                                       actual2 = 0;\r
+                               }\r
+                               pos2 = 0;\r
+                       }\r
+\r
+                       int x = actual2;\r
+                       int y = 0;\r
+                       if (actual2 > 0)\r
+                       {\r
+                               int written = write(session, backwardBuffer + pos2, actual2);\r
+                               if (written <= 0)\r
+                                       goto closeSession;\r
+                               actual2 -= written;\r
+                               pos2 += written;\r
+                               y = written;\r
+                       }\r
+\r
+                       if (FD_ISSET(session, &read_fds)&&(sizeof(forwardBuffer)>actual))\r
+                       {\r
+                               // NB! Here it is important that we empty the TCP/IP read buffer\r
+                               // to make transmission tick right\r
+                               memmove(forwardBuffer, forwardBuffer + pos, actual);\r
+                               pos = 0;\r
+                               int t;\r
+                               // this will block if there is no data at all\r
+                               t=read_socket(session, forwardBuffer+actual, sizeof(forwardBuffer)-actual);\r
+                               if (t <= 0)\r
+                               {\r
+                                       goto closeSession;\r
+                               }\r
+                               actual += t;\r
+                       }\r
+\r
+                       int x2 = actual;\r
+                       int y2 = 0;\r
+                       if (actual > 0)\r
+                       {\r
+                               /* Do not put things into the serial buffer if it has something to send\r
+                                * as that can cause a single byte to be sent at the time.\r
+                                *\r
+                                *\r
+                                */\r
+                               int written = write(serHandle, forwardBuffer + pos, actual);\r
+                               if (written < 0)\r
+                               {\r
+                                       if (errno != EAGAIN)\r
+                                       {\r
+                                               goto closeSession;\r
+                                       }\r
+                                       // The serial buffer is full\r
+                                       written = 0;\r
+                               } else\r
+                               {\r
+                                       actual -= written;\r
+                                       pos += written;\r
+                               }\r
+                               y2 = written;\r
+                       }\r
+                       if (cur < 1024)\r
+                       {\r
+                               tcpipSent[cur].req = x;\r
+                               tcpipSent[cur].actual = y;\r
+                               tcpipSent[cur].req2 = x2;\r
+                               tcpipSent[cur].actual2 = y2;\r
+                               cur++;\r
+                       }\r
+\r
+               }\r
+           closeSession:\r
+           close(session);\r
+               close(serHandle);\r
+\r
+               int i;\r
+               for (i = 0; i < 1024; i++)\r
+               {\r
+               diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual, tcpipSent[i].req2, tcpipSent[i].actual2);\r
+\r
+               }\r
+       }\r
+       close(fd);\r
+\r
+}\r
+\r
+void startUart(void)\r
+{\r
+    cyg_thread_create(1,\r
+                      zylinjtag_uart,\r
+                      (cyg_addrword_t)0,\r
+                      "uart thread",\r
+                      (void *)uart_stack,\r
+                      sizeof(uart_stack),\r
+                      &zylinjtag_uart_thread_handle,\r
+                      &zylinjtag_uart_thread_object);\r
+       cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop\r
+       cyg_thread_resume(zylinjtag_uart_thread_handle);\r
+}\r
+\r
+\r
+\r
+int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
+{\r
+       if (argc != 1)\r
+       {\r
+               command_print(cmd_ctx, "usage: uart <baudrate>");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       int baud = atol(args[0]);\r
+\r
+       switch (baud)\r
+       {\r
+       case 9600:\r
+               baud = CYGNUM_SERIAL_BAUD_9600;\r
+               break;\r
+       case 19200:\r
+               baud = CYGNUM_SERIAL_BAUD_19200;\r
+               break;\r
+       case 38400:\r
+               baud = CYGNUM_SERIAL_BAUD_38400;\r
+               break;\r
+       case 57600:\r
+               baud = CYGNUM_SERIAL_BAUD_57600;\r
+               break;\r
+       case 115200:\r
+               baud = CYGNUM_SERIAL_BAUD_115200;\r
+               break;\r
+       case 230400:\r
+               baud = CYGNUM_SERIAL_BAUD_230400;\r
+               break;\r
+       default:\r
+               command_print(cmd_ctx, "unsupported baudrate");\r
+               return ERROR_INVALID_ARGUMENTS;\r
+       }\r
+\r
+       cyg_serial_info_t buf;\r
+       cyg_uint32 len = 1;\r
+       //get existing serial configuration\r
+       len = sizeof(cyg_serial_info_t);\r
+       int err;\r
+       err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);\r
+       err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);\r
+       if (err != ENOERR)\r
+       {\r
+               command_print(cmd_ctx, "Failed to get serial port settings %d", err);\r
+               return ERROR_OK;\r
+       }\r
+       buf.baud = baud;\r
+\r
+       err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf, &len);\r
+       if (err != ENOERR)\r
+       {\r
+               command_print(cmd_ctx, "Failed to set serial port settings %d", err);\r
+               return ERROR_OK;\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+bool logAllToSerial = false;\r
+\r
+/* boolean parameter stored on config */\r
+bool boolParam(char *var)\r
+{\r
+       bool result = false;\r
+       char *name = alloc_printf(ZYLIN_CONFIG_DIR "/%s", var);\r
+       if (name == NULL)\r
+               return result;\r
+\r
+       void *data;\r
+       int len;\r
+       if (loadFile(name, &data, &len) == ERROR_OK)\r
+       {\r
+               if (len > 1)\r
+                       len = 1;\r
+               result = strncmp((char *) data, "1", len) == 0;\r
+               free(data);\r
+       }\r
+       free(name);\r
+       return result;\r
+}\r
+\r
+command_context_t *setup_command_handler();\r
+\r
+int add_default_dirs(void)\r
+{\r
+       add_script_search_dir(ZYLIN_CONFIG_DIR);\r
+       add_script_search_dir("/rom/lib/openocd");\r
+       add_script_search_dir("/rom");\r
+       return ERROR_OK;\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+       setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);\r
+       setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);\r
+       setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);\r
+\r
+       int err;\r
+       err = cyg_io_lookup("/dev/ser0", &serial_handle);\r
+       if (err != ENOERR)\r
+       {\r
+               diag_printf("/dev/ser0 not found\n");\r
+               reboot();\r
+       }\r
+\r
+       setPower(true); // on by default\r
+\r
+       atexit(keep_webserver);\r
+\r
+       err = mount("", "/ram", "ramfs");\r
+       if (err < 0)\r
+       {\r
+               diag_printf("unable to mount ramfs\n");\r
+       }\r
+       chdir("/ram");\r
+\r
+       char address[16];\r
+       sprintf(address, "%p", &filedata[0]);\r
+       err = mount(address, "/rom", "romfs");\r
+       if (err < 0)\r
+       {\r
+               diag_printf("unable to mount /rom\n");\r
+       }\r
+\r
+       err = mount("", "/log", "logfs");\r
+       if (err < 0)\r
+       {\r
+               diag_printf("unable to mount logfs\n");\r
+       }\r
+\r
+       err = mount("", "/tftp", "tftpfs");\r
+       if (err < 0)\r
+       {\r
+               diag_printf("unable to mount logfs\n");\r
+       }\r
+\r
+       log = fopen("/log/log", "w");\r
+       if (log == NULL)\r
+       {\r
+               diag_printf("Could not open log file /ram/log\n");\r
+               exit(-1);\r
+       }\r
+\r
+       diag_init_putc(_zylinjtag_diag_write_char);\r
+\r
+       // We want this in the log.\r
+       diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");\r
+       diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);\r
+\r
+       copydir("/rom/");\r
+\r
+       err = mount("/dev/flash1", "/config", "jffs2");\r
+       if (err < 0)\r
+       {\r
+               diag_printf("unable to mount jffs\n");\r
+       }\r
+\r
+\r
+       mkdir(ZYLIN_CONFIG_DIR, 0777);\r
+       mkdir(ZYLIN_CONFIG_DIR "/target", 0777);\r
+       mkdir(ZYLIN_CONFIG_DIR "/event", 0777);\r
+\r
+       logAllToSerial = boolParam("logserial");\r
+\r
+       // We need the network & web server in case there is something wrong with\r
+       // the config files that invoke exit()\r
+       zylinjtag_startNetwork();\r
+\r
+       /* we're going to access the jim interpreter from here on... */\r
+       openocd_sleep_postlude();\r
+       startUart();\r
+\r
+       add_default_dirs();\r
+\r
+       /* initialize commandline interface */\r
+       command_context_t *cmd_ctx;\r
+       cmd_ctx = setup_command_handler();\r
+       command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);\r
+       command_context_mode(cmd_ctx, COMMAND_CONFIG);\r
+\r
+\r
+       register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,\r
+                       COMMAND_EXEC, "show zy1000 version numbers");\r
+\r
+       register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,\r
+                       "rm <filname>");\r
+\r
+       register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,\r
+                       "same args as load_image, image stored in memory");\r
+\r
+       register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,\r
+                       "loads active fast load image to current target");\r
+\r
+       register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,\r
+                       "cat <filname>");\r
+\r
+       register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,\r
+                       "trunc <filname>");\r
+\r
+       register_command(cmd_ctx, NULL, "append_file", handle_append_command,\r
+                       COMMAND_ANY, "append <filname>");\r
+\r
+       register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,\r
+                       "power <on/off> - turn power switch to target on/off. No arguments - print status.");\r
+\r
+       register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,\r
+                       COMMAND_ANY, "meminfo");\r
+\r
+       register_command(cmd_ctx, NULL, "cp", handle_cp_command,\r
+                                        COMMAND_ANY, "cp <from> <to>");\r
+\r
+#ifdef CYGPKG_PROFILE_GPROF\r
+       register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,\r
+                       COMMAND_ANY, NULL);\r
+#endif\r
+       register_command(cmd_ctx, NULL, "uart", handle_uart_command,\r
+                                        COMMAND_ANY, "uart <baud>  - forward uart on port 5555");\r
+\r
+\r
+       int errVal;\r
+       errVal = log_init(cmd_ctx);\r
+       if (errVal != ERROR_OK)\r
+       {\r
+               diag_printf("log_init() failed %d\n", errVal);\r
+               exit(-1);\r
+       }\r
+\r
+       set_log_output(cmd_ctx, log);\r
+\r
+       LOG_DEBUG("log init complete");\r
+\r
+       //      diag_printf("Executing config files\n");\r
+\r
+       if (logAllToSerial)\r
+       {\r
+               diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");\r
+               command_run_line(cmd_ctx, "debug_level 3");\r
+       }\r
+\r
+       zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");\r
+\r
+       target_register_timer_callback(sense_handler, 200, 1, cmd_ctx);\r
+\r
+       // FIX!!!  Yuk!\r
+       // diag_printf() is really invoked from many more places than we trust it\r
+       // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).\r
+       //\r
+       // Disabling it here is safe and gives us enough logged debug output for now. Crossing\r
+       // fingers that it doesn't cause any crashes.\r
+       diag_printf("Init complete, GDB & telnet servers launched.\n");\r
+       command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);\r
+       if (!logAllToSerial)\r
+       {\r
+               serialLog = false;\r
+       }\r
+\r
+       /* handle network connections */\r
+       server_loop(cmd_ctx);\r
+       openocd_sleep_prelude();\r
+\r
+       /* shut server down */\r
+       server_quit();\r
+\r
+       /* free commandline interface */\r
+       command_done(cmd_ctx);\r
+       umount("/config");\r
+\r
+       exit(0);\r
+       for (;;);\r
+}\r
+\r
+\r
+\r
+cyg_int32\r
+cyg_httpd_exec_cgi_tcl(char *file_name);\r
+cyg_int32 homeForm(CYG_HTTPD_STATE *p)\r
+{\r
+       cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");\r
+       return 0;\r
+}\r
+\r
+CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);\r
+\r
+CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");\r
+CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");\r
+\r
+#include <pkgconf/system.h>\r
+#include <pkgconf/hal.h>\r
+#include <pkgconf/kernel.h>\r
+#include <pkgconf/io_fileio.h>\r
+#include <pkgconf/fs_rom.h>\r
+\r
+#include <cyg/kernel/ktypes.h>         // base kernel types\r
+#include <cyg/infra/cyg_trac.h>        // tracing macros\r
+#include <cyg/infra/cyg_ass.h>         // assertion macros\r
+#include <unistd.h>\r
+#include <sys/types.h>\r
+#include <fcntl.h>\r
+#include <sys/stat.h>\r
+#include <errno.h>\r
+#include <dirent.h>\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include <cyg/fileio/fileio.h>\r
+\r
+#include <cyg/kernel/kapi.h>\r
+#include <cyg/infra/diag.h>\r
+\r
+//==========================================================================\r
+// Eventually we want to eXecute In Place from the ROM in a protected\r
+// environment, so we'll need executables to be aligned to a boundary\r
+// suitable for MMU protection. A suitable boundary would be the 4k\r
+// boundary in all the CPU architectures I am currently aware of.\r
+\r
+// Forward definitions\r
+\r
+// Filesystem operations\r
+static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);\r
+static int tftpfs_umount(cyg_mtab_entry *mte);\r
+static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
+               int mode, cyg_file *fte);\r
+static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);\r
+static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);\r
+\r
+// File operations\r
+static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);\r
+static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);\r
+static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);\r
+\r
+//==========================================================================\r
+// Filesystem table entries\r
+\r
+// -------------------------------------------------------------------------\r
+// Fstab entry.\r
+// This defines the entry in the filesystem table.\r
+// For simplicity we use _FILESYSTEM synchronization for all accesses since\r
+// we should never block in any filesystem operations.\r
+#if 1\r
+FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,\r
+               CYG_SYNCMODE_NONE,\r
+               tftpfs_mount,\r
+               tftpfs_umount,\r
+               tftpfs_open,\r
+               (cyg_fsop_unlink *)cyg_fileio_erofs,\r
+               (cyg_fsop_mkdir *)cyg_fileio_erofs,\r
+               (cyg_fsop_rmdir *)cyg_fileio_erofs,\r
+               (cyg_fsop_rename *)cyg_fileio_erofs,\r
+               (cyg_fsop_link *)cyg_fileio_erofs,\r
+               (cyg_fsop_opendir *)cyg_fileio_erofs,\r
+               (cyg_fsop_chdir *)cyg_fileio_erofs,\r
+               (cyg_fsop_stat *)cyg_fileio_erofs,\r
+               (cyg_fsop_getinfo *)cyg_fileio_erofs,\r
+               (cyg_fsop_setinfo *)cyg_fileio_erofs);\r
+#endif\r
+\r
+// -------------------------------------------------------------------------\r
+// mtab entry.\r
+// This defines a single ROMFS loaded into ROM at the configured address\r
+//\r
+// MTAB_ENTRY( rom_mte,        // structure name\r
+//             "/rom",         // mount point\r
+//             "romfs",        // FIlesystem type\r
+//             "",             // hardware device\r
+//  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS  // Address in ROM\r
+//           );\r
+\r
+\r
+// -------------------------------------------------------------------------\r
+// File operations.\r
+// This set of file operations are used for normal open files.\r
+\r
+static cyg_fileops tftpfs_fileops =\r
+{\r
+       tftpfs_fo_read,\r
+       tftpfs_fo_write,\r
+       tftpfs_fo_lseek,\r
+       (cyg_fileop_ioctl *)cyg_fileio_erofs,\r
+    cyg_fileio_seltrue,\r
+    tftpfs_fo_fsync,\r
+    tftpfs_fo_close,\r
+               (cyg_fileop_fstat *) cyg_fileio_erofs,\r
+               (cyg_fileop_getinfo *) cyg_fileio_erofs,\r
+       (cyg_fileop_setinfo *)cyg_fileio_erofs,\r
+};\r
+\r
+// -------------------------------------------------------------------------\r
+// tftpfs_mount()\r
+// Process a mount request. This mainly finds root for the\r
+// filesystem.\r
+\r
+static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)\r
+{\r
+       return ENOERR;\r
+}\r
+\r
+static int tftpfs_umount(cyg_mtab_entry *mte)\r
+{\r
+       return ENOERR;\r
+}\r
+\r
+struct Tftp\r
+{\r
+       int write;\r
+       int readFile;\r
+       cyg_uint8 *mem;\r
+       int actual;\r
+       char *server;\r
+       char *file;\r
+};\r
+\r
+static void freeTftp(struct Tftp *t)\r
+{\r
+       if (t == NULL)\r
+               return;\r
+       if (t->mem)\r
+               free(t->mem);\r
+       if (t->server)\r
+               free(t->server);\r
+       if (t->file)\r
+               free(t->file);\r
+       free(t);\r
+}\r
+\r
+static const int tftpMaxSize = 8192 * 1024;\r
+static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
+               int mode, cyg_file *file)\r
+{\r
+       struct Tftp *tftp;\r
+       tftp = malloc(sizeof(struct Tftp));\r
+       if (tftp == NULL)\r
+               return EMFILE;\r
+       memset(tftp, 0, sizeof(struct Tftp));\r
+\r
+       file->f_flag |= mode & CYG_FILE_MODE_MASK;\r
+       file->f_type = CYG_FILE_TYPE_FILE;\r
+       file->f_ops = &tftpfs_fileops;\r
+       file->f_offset = 0;\r
+       file->f_data = 0;\r
+       file->f_xops = 0;\r
+\r
+       tftp->mem = malloc(tftpMaxSize);\r
+       if (tftp->mem == NULL)\r
+       {\r
+               freeTftp(tftp);\r
+               return EMFILE;\r
+       }\r
+\r
+       char *server = strchr(name, '/');\r
+       if (server == NULL)\r
+       {\r
+               freeTftp(tftp);\r
+               return EMFILE;\r
+       }\r
+\r
+       tftp->server = malloc(server - name + 1);\r
+       if (tftp->server == NULL)\r
+       {\r
+               freeTftp(tftp);\r
+               return EMFILE;\r
+       }\r
+       strncpy(tftp->server, name, server - name);\r
+       tftp->server[server - name] = 0;\r
+\r
+       tftp->file = strdup(server + 1);\r
+       if (tftp->file == NULL)\r
+       {\r
+               freeTftp(tftp);\r
+               return EMFILE;\r
+       }\r
+\r
+       file->f_data = (CYG_ADDRWORD) tftp;\r
+\r
+       return ENOERR;\r
+}\r
+\r
+static int fetchTftp(struct Tftp *tftp)\r
+{\r
+       if (!tftp->readFile)\r
+       {\r
+               int err;\r
+           tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize,   TFTP_OCTET, &err);\r
+\r
+               if (tftp->actual < 0)\r
+               {\r
+                       return EMFILE;\r
+               }\r
+               tftp->readFile = 1;\r
+       }\r
+       return ENOERR;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+// tftpfs_fo_write()\r
+// Read data from file.\r
+\r
+static int\r
+tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)\r
+{\r
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
+\r
+       if (fetchTftp(tftp) != ENOERR)\r
+               return EMFILE;\r
+\r
+       int i;\r
+       off_t pos = fp->f_offset;\r
+       int resid = 0;\r
+       for (i = 0; i < uio->uio_iovcnt; i++)\r
+       {\r
+               cyg_iovec *iov = &uio->uio_iov[i];\r
+               char *buf = (char *) iov->iov_base;\r
+               off_t len = iov->iov_len;\r
+\r
+               if (len + pos > tftp->actual)\r
+               {\r
+                       len = tftp->actual - pos;\r
+               }\r
+               resid += iov->iov_len - len;\r
+\r
+               memcpy(buf, tftp->mem + pos, len);\r
+               pos += len;\r
+\r
+       }\r
+       uio->uio_resid = resid;\r
+       fp->f_offset = pos;\r
+\r
+       return ENOERR;\r
+}\r
+\r
+\r
+static int\r
+tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)\r
+{\r
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
+\r
+       int i;\r
+       off_t pos = fp->f_offset;\r
+       int resid = 0;\r
+       for (i = 0; i < uio->uio_iovcnt; i++)\r
+       {\r
+               cyg_iovec *iov = &uio->uio_iov[i];\r
+               char *buf = (char *) iov->iov_base;\r
+               off_t len = iov->iov_len;\r
+\r
+               if (len + pos > tftpMaxSize)\r
+               {\r
+                       len = tftpMaxSize - pos;\r
+               }\r
+               resid += iov->iov_len - len;\r
+\r
+               memcpy(tftp->mem + pos, buf, len);\r
+               pos += len;\r
+\r
+       }\r
+       uio->uio_resid = resid;\r
+       fp->f_offset = pos;\r
+\r
+       tftp->write = 1;\r
+\r
+       return ENOERR;\r
+}\r
+\r
+static int\r
+tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)\r
+{\r
+       int error = ENOERR;\r
+       return error;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+// romfs_fo_close()\r
+// Close a file. We just clear out the data pointer.\r
+\r
+static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)\r
+{\r
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
+       int error = ENOERR;\r
+\r
+       if (tftp->write)\r
+       {\r
+           tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,   TFTP_OCTET, &error);\r
+       }\r
+\r
+       freeTftp(tftp);\r
+       fp->f_data = 0;\r
+       return error;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+// romfs_fo_lseek()\r
+// Seek to a new file position.\r
+\r
+static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)\r
+{\r
+       struct Tftp *tftp = (struct Tftp *) fp->f_data;\r
+       off_t pos = *apos;\r
+\r
+       if (fetchTftp(tftp) != ENOERR)\r
+               return EMFILE;\r
+\r
+       switch (whence)\r
+       {\r
+       case SEEK_SET:\r
+               // Pos is already where we want to be.\r
+               break;\r
+\r
+       case SEEK_CUR:\r
+               // Add pos to current offset.\r
+               pos += fp->f_offset;\r
+               break;\r
+\r
+       case SEEK_END:\r
+               // Add pos to file size.\r
+               pos += tftp->actual;\r
+               break;\r
+\r
+       default:\r
+               return EINVAL;\r
+       }\r
+\r
+       // Check that pos is still within current file size, or at the\r
+       // very end.\r
+       if (pos < 0 || pos > tftp->actual)\r
+               return EINVAL;\r
+\r
+       // All OK, set fp offset and return new position.\r
+       *apos = fp->f_offset = pos;\r
+\r
+       return ENOERR;\r
+}\r
+\r
+void usleep(int us)\r
+{\r
+       if (us > 10000)\r
+               cyg_thread_delay(us / 10000 + 1);\r
+       else\r
+               HAL_DELAY_US(us);\r
+}\r
+\r
+// Chunked version.\r
+cyg_int32\r
+show_log_entry(CYG_HTTPD_STATE *phttpstate)\r
+{\r
+       cyg_httpd_start_chunked("text");\r
+       if (logCount >= logSize)\r
+       {\r
+        cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);\r
+       }\r
+       cyg_httpd_write_chunked(logBuffer, writePtr);\r
+       cyg_httpd_end_chunked();\r
+       return -1;\r
+}\r
+\r
+CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);\r
+\r
+// Filesystem operations\r
+static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);\r
+static int logfs_umount(cyg_mtab_entry *mte);\r
+static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
+               int mode, cyg_file *fte);\r
+static int\r
+logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);\r
+\r
+// File operations\r
+static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);\r
+static int logfs_fo_close(struct CYG_FILE_TAG *fp);\r
+\r
+//==========================================================================\r
+// Filesystem table entries\r
+\r
+// -------------------------------------------------------------------------\r
+// Fstab entry.\r
+// This defines the entry in the filesystem table.\r
+// For simplicity we use _FILESYSTEM synchronization for all accesses since\r
+// we should never block in any filesystem operations.\r
+FSTAB_ENTRY( logfs_fste, "logfs", 0,\r
+               CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,\r
+               logfs_mount,\r
+               logfs_umount,\r
+               logfs_open,\r
+               (cyg_fsop_unlink *)cyg_fileio_erofs,\r
+               (cyg_fsop_mkdir *)cyg_fileio_erofs,\r
+               (cyg_fsop_rmdir *)cyg_fileio_erofs,\r
+               (cyg_fsop_rename *)cyg_fileio_erofs,\r
+               (cyg_fsop_link *)cyg_fileio_erofs,\r
+               (cyg_fsop_opendir *)cyg_fileio_erofs,\r
+               (cyg_fsop_chdir *)cyg_fileio_erofs,\r
+               (cyg_fsop_stat *)cyg_fileio_erofs,\r
+               (cyg_fsop_getinfo *)cyg_fileio_erofs,\r
+               (cyg_fsop_setinfo *)cyg_fileio_erofs);\r
+\r
+// -------------------------------------------------------------------------\r
+// File operations.\r
+// This set of file operations are used for normal open files.\r
+\r
+static cyg_fileops logfs_fileops =\r
+{\r
+       (cyg_fileop_read *)cyg_fileio_erofs,\r
+    (cyg_fileop_write *)logfs_fo_write,\r
+               (cyg_fileop_lseek *) cyg_fileio_erofs,\r
+       (cyg_fileop_ioctl *)cyg_fileio_erofs,\r
+    cyg_fileio_seltrue,\r
+    logfs_fo_fsync,\r
+    logfs_fo_close,\r
+       (cyg_fileop_fstat *)cyg_fileio_erofs,\r
+               (cyg_fileop_getinfo *) cyg_fileio_erofs,\r
+       (cyg_fileop_setinfo *)cyg_fileio_erofs,\r
+};\r
+\r
+// -------------------------------------------------------------------------\r
+// logfs_mount()\r
+// Process a mount request. This mainly finds root for the\r
+// filesystem.\r
+\r
+static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)\r
+{\r
+       return ENOERR;\r
+}\r
+\r
+static int logfs_umount(cyg_mtab_entry *mte)\r
+{\r
+       return ENOERR;\r
+}\r
+\r
+static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,\r
+               int mode, cyg_file *file)\r
+{\r
+       file->f_flag |= mode & CYG_FILE_MODE_MASK;\r
+       file->f_type = CYG_FILE_TYPE_FILE;\r
+       file->f_ops = &logfs_fileops;\r
+       file->f_offset = 0;\r
+       file->f_data = 0;\r
+       file->f_xops = 0;\r
+       return ENOERR;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+// logfs_fo_write()\r
+// Write data to file.\r
+\r
+static int\r
+logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)\r
+{\r
+       int i;\r
+       for (i = 0; i < uio->uio_iovcnt; i++)\r
+       {\r
+               cyg_iovec *iov = &uio->uio_iov[i];\r
+               char *buf = (char *) iov->iov_base;\r
+               off_t len = iov->iov_len;\r
+\r
+               diag_write(buf, len);\r
+       }\r
+       uio->uio_resid = 0;\r
+\r
+       return ENOERR;\r
+}\r
+static int\r
+logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)\r
+{\r
+       return ENOERR;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+// romfs_fo_close()\r
+// Close a file. We just clear out the data pointer.\r
+\r
+static int logfs_fo_close(struct CYG_FILE_TAG *fp)\r
+{\r
+       return ENOERR;\r
+}\r
index 76a3840..b5a3d8a 100644 (file)
@@ -54,7 +54,7 @@ EP93XXFILES =
 endif
 
 if ECOSBOARD
-ECOSBOARDFILES = $(ECOS_SOURCE_FILES)/zy1000.c
+ECOSBOARDFILES = zy1000.c
 else
 ECOSBOARDFILES =
 endif
diff --git a/src/jtag/zy1000.c b/src/jtag/zy1000.c
new file mode 100644 (file)
index 0000000..8c10a9f
--- /dev/null
@@ -0,0 +1,739 @@
+/***************************************************************************\r
+ *   Copyright (C) 2007-2008 by Øyvind Harboe                              *\r
+ *                                                                         *\r
+ *   This program is free software; you can redistribute it and/or modify  *\r
+ *   it under the terms of the GNU General Public License as published by  *\r
+ *   the Free Software Foundation; either version 2 of the License, or     *\r
+ *   (at your option) any later version.                                   *\r
+ *                                                                         *\r
+ *   This program is distributed in the hope that it will be useful,       *\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
+ *   GNU General Public License for more details.                          *\r
+ *                                                                         *\r
+ *   You should have received a copy of the GNU General Public License     *\r
+ *   along with this program; if not, write to the                         *\r
+ *   Free Software Foundation, Inc.,                                       *\r
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
+ ***************************************************************************/\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+\r
+#include "log.h"\r
+#include "jtag.h"\r
+#include "bitbang.h"\r
+#include "../target/embeddedice.h"\r
+\r
+\r
+#include <cyg/hal/hal_io.h>             // low level i/o\r
+#include <cyg/hal/var_io.h>             // common registers\r
+#include <cyg/hal/plf_io.h>             // platform registers\r
+#include <cyg/hal/hal_diag.h>\r
+\r
+#include <stdlib.h>\r
+\r
+\r
+extern int jtag_error;\r
+\r
+/* low level command set\r
+ */\r
+int eCosBoard_read(void);\r
+static void eCosBoard_write(int tck, int tms, int tdi);\r
+void eCosBoard_reset(int trst, int srst);\r
+\r
+\r
+int eCosBoard_speed(int speed);\r
+int eCosBoard_register_commands(struct command_context_s *cmd_ctx);\r
+int eCosBoard_init(void);\r
+int eCosBoard_quit(void);\r
+\r
+/* interface commands */\r
+int eCosBoard_handle_eCosBoard_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
+\r
+static int eCosBoard_khz(int khz, int *jtag_speed)\r
+{\r
+       if (khz==0)\r
+       {\r
+               *jtag_speed=0;\r
+       }\r
+       else\r
+       {\r
+               *jtag_speed=64000/khz;\r
+       }\r
+       return ERROR_OK;\r
+}\r
+\r
+static int eCosBoard_speed_div(int speed, int *khz)\r
+{\r
+       if (speed==0)\r
+       {\r
+               *khz = 0;\r
+       }\r
+       else\r
+       {\r
+               *khz=64000/speed;\r
+       }\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+jtag_interface_t eCosBoard_interface =\r
+{\r
+       .name = "ZY1000",\r
+       .execute_queue = bitbang_execute_queue,\r
+       .speed = eCosBoard_speed,\r
+       .register_commands = eCosBoard_register_commands,\r
+       .init = eCosBoard_init,\r
+       .quit = eCosBoard_quit,\r
+       .khz = eCosBoard_khz,\r
+       .speed_div = eCosBoard_speed_div,\r
+};\r
+\r
+bitbang_interface_t eCosBoard_bitbang =\r
+{\r
+       .read = eCosBoard_read,\r
+       .write = eCosBoard_write,\r
+       .reset = eCosBoard_reset\r
+};\r
+\r
+\r
+\r
+static void eCosBoard_write(int tck, int tms, int tdi)\r
+{\r
+\r
+}\r
+\r
+int eCosBoard_read(void)\r
+{\r
+       return -1;\r
+}\r
+\r
+extern bool readSRST();\r
+\r
+void eCosBoard_reset(int trst, int srst)\r
+{\r
+       LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst);\r
+       if(!srst)\r
+       {\r
+               ZY1000_POKE(0x08000014, 0x00000001);\r
+       }\r
+       else\r
+       {\r
+               /* Danger!!! if clk!=0 when in\r
+                * idle in TAP_RTI, reset halt on str912 will fail.\r
+                */\r
+               ZY1000_POKE(0x08000010, 0x00000001);\r
+       }\r
+\r
+       if(!trst)\r
+       {\r
+               ZY1000_POKE(0x08000014, 0x00000002);\r
+       }\r
+       else\r
+       {\r
+               /* assert reset */\r
+               ZY1000_POKE(0x08000010, 0x00000002);\r
+       }\r
+       \r
+       if (trst||(srst&&(jtag_reset_config & RESET_SRST_PULLS_TRST)))\r
+       {\r
+               waitIdle();\r
+               /* we're now in the TLR state until trst is deasserted */\r
+               ZY1000_POKE(0x08000020, TAP_TLR);\r
+       } else\r
+       {\r
+               /* We'll get RCLK failure when we assert TRST, so clear any false positives here */\r
+               ZY1000_POKE(0x08000014, 0x400);         \r
+       }\r
+\r
+       /* wait for srst to float back up */\r
+       if (!srst)\r
+       {\r
+               int i;\r
+               for (i=0; i<1000; i++)\r
+               {\r
+                       // We don't want to sense our own reset, so we clear here.\r
+                       // There is of course a timing hole where we could loose\r
+                       // a "real" reset.\r
+                       if (!readSRST())\r
+                               break;\r
+\r
+                       /* wait 1ms */\r
+                       alive_sleep(1);\r
+               }\r
+\r
+               if (i==1000)\r
+               {\r
+                       LOG_USER("SRST didn't deassert after %dms", i);\r
+               } else if (i>1)\r
+               {\r
+                       LOG_USER("SRST took %dms to deassert", i);\r
+               }\r
+       }\r
+}\r
+\r
+int eCosBoard_speed(int speed)\r
+{\r
+       if(speed == 0)\r
+       {\r
+               /*0 means RCLK*/\r
+               speed = 0;\r
+               ZY1000_POKE(0x08000010, 0x100);\r
+               LOG_DEBUG("jtag_speed using RCLK");\r
+       }\r
+       else\r
+       {\r
+               if(speed > 8190 || speed < 2)\r
+               {\r
+                       LOG_ERROR("valid ZY1000 jtag_speed=[8190,2]. Divisor is 64MHz / even values between 8190-2, i.e. min 7814Hz, max 32MHz");\r
+                       return ERROR_INVALID_ARGUMENTS;\r
+               }\r
+\r
+               LOG_USER("jtag_speed %d => JTAG clk=%f", speed, 64.0/(float)speed);\r
+               ZY1000_POKE(0x08000014, 0x100);\r
+               ZY1000_POKE(0x0800001c, speed&~1);\r
+       }\r
+       return ERROR_OK;\r
+}\r
+\r
+int eCosBoard_register_commands(struct command_context_s *cmd_ctx)\r
+{\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+int eCosBoard_init(void)\r
+{\r
+       ZY1000_POKE(0x08000010, 0x30); // Turn on LED1 & LED2\r
+\r
+        /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */\r
+       eCosBoard_reset(0, 0);\r
+       eCosBoard_speed(jtag_speed);\r
+\r
+       bitbang_interface = &eCosBoard_bitbang;\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int eCosBoard_quit(void)\r
+{\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+\r
+/* loads a file and returns a pointer to it in memory. The file contains\r
+ * a 0 byte(sentinel) after len bytes - the length of the file. */\r
+int loadFile(const char *fileName, void **data, int *len)\r
+{\r
+       FILE * pFile;\r
+       pFile = fopen (fileName,"rb");\r
+       if (pFile==NULL)\r
+       {\r
+               LOG_ERROR("Can't open %s\n", fileName);\r
+               return ERROR_JTAG_DEVICE_ERROR;\r
+       }\r
+    if (fseek (pFile, 0, SEEK_END)!=0)\r
+    {\r
+               LOG_ERROR("Can't open %s\n", fileName);\r
+               fclose(pFile);\r
+               return ERROR_JTAG_DEVICE_ERROR;\r
+    }\r
+    *len=ftell (pFile);\r
+    if (*len==-1)\r
+    {\r
+               LOG_ERROR("Can't open %s\n", fileName);\r
+               fclose(pFile);\r
+               return ERROR_JTAG_DEVICE_ERROR;\r
+    }\r
+\r
+    if (fseek (pFile, 0, SEEK_SET)!=0)\r
+    {\r
+               LOG_ERROR("Can't open %s\n", fileName);\r
+               fclose(pFile);\r
+               return ERROR_JTAG_DEVICE_ERROR;\r
+    }\r
+    *data=malloc(*len+1);\r
+    if (*data==NULL)\r
+    {\r
+               LOG_ERROR("Can't open %s\n", fileName);\r
+               fclose(pFile);\r
+               return ERROR_JTAG_DEVICE_ERROR;\r
+    }\r
+\r
+    if (fread(*data, 1, *len, pFile)!=*len)\r
+    {\r
+               fclose(pFile);\r
+       free(*data);\r
+               LOG_ERROR("Can't open %s\n", fileName);\r
+               return ERROR_JTAG_DEVICE_ERROR;\r
+    }\r
+    fclose (pFile);\r
+    *(((char *)(*data))+*len)=0; /* sentinel */\r
+\r
+    return ERROR_OK;\r
+\r
+\r
+\r
+}\r
+\r
+\r
+\r
+\r
+int interface_jtag_execute_queue(void)\r
+{\r
+       cyg_uint32 empty;\r
+\r
+       waitIdle();\r
+       ZY1000_PEEK(0x08000010, empty);\r
+       /* clear JTAG error register */\r
+       ZY1000_POKE(0x08000014, 0x400);\r
+\r
+       if ((empty&0x400)!=0)\r
+       {\r
+               LOG_WARNING("RCLK timeout");\r
+               /* the error is informative only as we don't want to break the firmware if there\r
+                * is a false positive.\r
+                */\r
+//             return ERROR_FAIL;\r
+       }\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+static cyg_uint32 getShiftValue()\r
+{\r
+       cyg_uint32 value;\r
+       waitIdle();\r
+       ZY1000_PEEK(0x0800000c, value);\r
+       VERBOSE(LOG_INFO("getShiftValue %08x", value));\r
+       return value;\r
+}\r
+#if 0\r
+static cyg_uint32 getShiftValueFlip()\r
+{\r
+       cyg_uint32 value;\r
+       waitIdle();\r
+       ZY1000_PEEK(0x08000018, value);\r
+       VERBOSE(LOG_INFO("getShiftValue %08x (flipped)", value));\r
+       return value;\r
+}\r
+#endif\r
+\r
+#if 0\r
+static void shiftValueInnerFlip(const enum tap_state state, const enum tap_state endState, int repeat, cyg_uint32 value)\r
+{\r
+       VERBOSE(LOG_INFO("shiftValueInner %s %s %d %08x (flipped)", tap_state_strings[state], tap_state_strings[endState], repeat, value));\r
+       cyg_uint32 a,b;\r
+       a=state;\r
+       b=endState;\r
+       ZY1000_POKE(0x0800000c, value);\r
+       ZY1000_POKE(0x08000008, (1<<15)|(repeat<<8)|(a<<4)|b);\r
+       VERBOSE(getShiftValueFlip());\r
+}\r
+#endif\r
+\r
+extern int jtag_check_value(u8 *captured, void *priv);\r
+\r
+static void gotoEndState()\r
+{\r
+       setCurrentState(cmd_queue_end_state);\r
+}\r
+\r
+static __inline void scanFields(int num_fields, scan_field_t *fields, enum tap_state shiftState, int pause)\r
+{\r
+       int i;\r
+       int j;\r
+       int k;\r
+\r
+       for (i = 0; i < num_fields; i++)\r
+       {\r
+               cyg_uint32 value;\r
+\r
+               static u8 *in_buff=NULL; /* pointer to buffer for scanned data */\r
+               static int in_buff_size=0;\r
+               u8 *inBuffer=NULL;\r
+\r
+\r
+               // figure out where to store the input data\r
+               int num_bits=fields[i].num_bits;\r
+               if (fields[i].in_value!=NULL)\r
+               {\r
+                       inBuffer=fields[i].in_value;\r
+               } else if (fields[i].in_handler!=NULL)\r
+               {\r
+                       if (in_buff_size*8<num_bits)\r
+                       {\r
+                               // we need more space\r
+                               if (in_buff!=NULL)\r
+                                       free(in_buff);\r
+                               in_buff=NULL;\r
+                               in_buff_size=(num_bits+7)/8;\r
+                               in_buff=malloc(in_buff_size);\r
+                               if (in_buff==NULL)\r
+                               {\r
+                                       LOG_ERROR("Out of memory");\r
+                                       jtag_error=ERROR_JTAG_QUEUE_FAILED;\r
+                                       return;\r
+                               }\r
+                       }\r
+                       inBuffer=in_buff;\r
+               }\r
+\r
+               // here we shuffle N bits out/in\r
+               j=0;\r
+               while (j<num_bits)\r
+               {\r
+                       enum tap_state pause_state;\r
+                       int l;\r
+                       k=num_bits-j;\r
+                       pause_state=(shiftState==TAP_SD)?TAP_SD:TAP_SI;\r
+                       if (k>32)\r
+                       {\r
+                               k=32;\r
+                               /* we have more to shift out */\r
+                       } else if (pause&&(i == num_fields-1))\r
+                       {\r
+                               /* this was the last to shift out this time */\r
+                               pause_state=(shiftState==TAP_SD)?TAP_PD:TAP_PI;\r
+                       }\r
+\r
+                       // we have (num_bits+7)/8 bytes of bits to toggle out.\r
+                       // bits are pushed out LSB to MSB\r
+                       value=0;\r
+                       if (fields[i].out_value!=NULL)\r
+                       {\r
+                               for (l=0; l<k; l+=8)\r
+                               {\r
+                                       value|=fields[i].out_value[(j+l)/8]<<l;\r
+                               }\r
+                       }\r
+                       /* mask away unused bits for easier debugging */\r
+                       value&=~(((u32)0xffffffff)<<k);\r
+\r
+                       shiftValueInner(shiftState, pause_state, k, value);\r
+\r
+                       if (inBuffer!=NULL)\r
+                       {\r
+                               // data in, LSB to MSB\r
+                               value=getShiftValue();\r
+                               // we're shifting in data to MSB, shift data to be aligned for returning the value\r
+                               value >>= 32-k;\r
+\r
+                               for (l=0; l<k; l+=8)\r
+                               {\r
+                                       inBuffer[(j+l)/8]=(value>>l)&0xff;\r
+                               }\r
+                       }\r
+                       j+=k;\r
+               }\r
+\r
+               if (fields[i].in_handler!=NULL)\r
+               {\r
+                       // invoke callback\r
+                       int r=fields[i].in_handler(inBuffer, fields[i].in_handler_priv, fields+i);\r
+                       if (r!=ERROR_OK)\r
+                       {\r
+                           /* this will cause jtag_execute_queue() to return an error */\r
+                               jtag_error=r;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+int interface_jtag_add_end_state(enum tap_state state)\r
+{\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+int interface_jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
+{\r
+\r
+       int i, j;\r
+       int scan_size = 0;\r
+       jtag_device_t *device;\r
+\r
+       for (i=0; i < jtag_num_devices; i++)\r
+       {\r
+               int pause=i==(jtag_num_devices-1);\r
+               int found = 0;\r
+               device = jtag_get_device(i);\r
+               scan_size = device->ir_length;\r
+\r
+               /* search the list */\r
+               for (j=0; j < num_fields; j++)\r
+               {\r
+                       if (i == fields[j].device)\r
+                       {\r
+                               found = 1;\r
+\r
+                               if ((jtag_verify_capture_ir)&&(fields[j].in_handler==NULL))\r
+                               {\r
+                                       jtag_set_check_value(fields+j, device->expected, device->expected_mask, NULL);\r
+                               } else if (jtag_verify_capture_ir)\r
+                               {\r
+                                       fields[j].in_check_value = device->expected;\r
+                                       fields[j].in_check_mask = device->expected_mask;\r
+                               }\r
+\r
+                               scanFields(1, fields+j, TAP_SI, pause);\r
+                               /* update device information */\r
+                               buf_cpy(fields[j].out_value, jtag_get_device(i)->cur_instr, scan_size);\r
+\r
+                               device->bypass = 0;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (!found)\r
+               {\r
+                       /* if a device isn't listed, set it to BYPASS */\r
+                       u8 ones[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};\r
+\r
+                       scan_field_t tmp;\r
+                       memset(&tmp, 0, sizeof(tmp));\r
+                       tmp.out_value = ones;\r
+                       tmp.num_bits = scan_size;\r
+                       scanFields(1, &tmp, TAP_SI, pause);\r
+                       /* update device information */\r
+                       buf_cpy(tmp.out_value, jtag_get_device(i)->cur_instr, scan_size);\r
+                       device->bypass = 1;\r
+               }\r
+       }\r
+       gotoEndState();\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+int interface_jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
+{\r
+       scanFields(num_fields, fields, TAP_SI, 1);\r
+       gotoEndState();\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+/*extern jtag_command_t **jtag_get_last_command_p(void);*/\r
+\r
+int interface_jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
+{\r
+       int i, j;\r
+       for (i=0; i < jtag_num_devices; i++)\r
+       {\r
+               int found = 0;\r
+               int pause = (i==(jtag_num_devices-1));\r
+\r
+               for (j=0; j < num_fields; j++)\r
+               {\r
+                       if (i == fields[j].device)\r
+                       {\r
+                               found = 1;\r
+\r
+                               scanFields(1, fields+j, TAP_SD, pause);\r
+                       }\r
+               }\r
+               if (!found)\r
+               {\r
+#ifdef _DEBUG_JTAG_IO_\r
+                       /* if a device isn't listed, the BYPASS register should be selected */\r
+                       if (!jtag_get_device(i)->bypass)\r
+                       {\r
+                               LOG_ERROR("BUG: no scan data for a device not in BYPASS");\r
+                               exit(-1);\r
+                       }\r
+#endif\r
+\r
+                       scan_field_t tmp;\r
+                       /* program the scan field to 1 bit length, and ignore it's value */\r
+                       tmp.num_bits = 1;\r
+                       tmp.out_value = NULL;\r
+                       tmp.out_mask = NULL;\r
+                       tmp.in_value = NULL;\r
+                       tmp.in_check_value = NULL;\r
+                       tmp.in_check_mask = NULL;\r
+                       tmp.in_handler = NULL;\r
+                       tmp.in_handler_priv = NULL;\r
+\r
+                       scanFields(1, &tmp, TAP_SD, pause);\r
+               }\r
+               else\r
+               {\r
+#ifdef _DEBUG_JTAG_IO_\r
+                       /* if a device is listed, the BYPASS register must not be selected */\r
+                       if (jtag_get_device(i)->bypass)\r
+                       {\r
+                               LOG_WARNING("scan data for a device in BYPASS");\r
+                       }\r
+#endif\r
+               }\r
+       }\r
+       gotoEndState();\r
+       return ERROR_OK;\r
+}\r
+\r
+int interface_jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
+{\r
+       scanFields(num_fields, fields, TAP_SD, 1);\r
+       gotoEndState();\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+int interface_jtag_add_tlr()\r
+{\r
+       setCurrentState(TAP_TLR);\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+extern int jtag_nsrst_delay;\r
+extern int jtag_ntrst_delay;\r
+\r
+int interface_jtag_add_reset(int req_trst, int req_srst)\r
+{\r
+       eCosBoard_reset(req_trst, req_srst);\r
+       return ERROR_OK;\r
+}\r
+\r
+int interface_jtag_add_runtest(int num_cycles, enum tap_state state)\r
+{\r
+       /* num_cycles can be 0 */\r
+       setCurrentState(TAP_RTI);\r
+\r
+       /* execute num_cycles, 32 at the time. */\r
+       int i;\r
+       for (i=0; i<num_cycles; i+=32)\r
+       {\r
+               int num;\r
+               num=32;\r
+               if (num_cycles-i<num)\r
+               {\r
+                       num=num_cycles-i;\r
+               }\r
+               shiftValueInner(TAP_RTI, TAP_RTI, num, 0);\r
+       }\r
+\r
+#if !TEST_MANUAL()\r
+       /* finish in end_state */\r
+       setCurrentState(state);\r
+#else\r
+       enum tap_state t=TAP_RTI;\r
+       /* test manual drive code on any target */\r
+       int tms;\r
+       u8 tms_scan = TAP_MOVE(t, state);\r
+       \r
+       for (i = 0; i < 7; i++)\r
+       {\r
+               tms = (tms_scan >> i) & 1;\r
+               waitIdle();\r
+               ZY1000_POKE(0x08000028,  tms);\r
+       }\r
+       waitIdle();\r
+       ZY1000_POKE(0x08000020, state); \r
+#endif\r
+\r
+\r
+       return ERROR_OK;\r
+}\r
+\r
+int interface_jtag_add_sleep(u32 us)\r
+{\r
+       jtag_sleep(us);\r
+       return ERROR_OK;\r
+}\r
+\r
+int interface_jtag_add_pathmove(int num_states, enum tap_state *path)\r
+{\r
+       int state_count;\r
+       int tms = 0;\r
+\r
+       /*wait for the fifo to be empty*/\r
+       waitIdle();\r
+\r
+       state_count = 0;\r
+\r
+       enum tap_state cur_state=cmd_queue_cur_state;\r
+\r
+       while (num_states)\r
+       {\r
+               if (tap_transitions[cur_state].low == path[state_count])\r
+               {\r
+                       tms = 0;\r
+               }\r
+               else if (tap_transitions[cur_state].high == path[state_count])\r
+               {\r
+                       tms = 1;\r
+               }\r
+               else\r
+               {\r
+                       LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[path[state_count]]);\r
+                       exit(-1);\r
+               }\r
+\r
+               waitIdle();\r
+               ZY1000_POKE(0x08000028,  tms);\r
+\r
+               cur_state = path[state_count];\r
+               state_count++;\r
+               num_states--;\r
+       }\r
+\r
+       waitIdle();\r
+       ZY1000_POKE(0x08000020,  cur_state);\r
+       return ERROR_OK;\r
+}\r
+\r
+\r
+\r
+void embeddedice_write_dcc(int chain_pos, int reg_addr, u8 *buffer, int little, int count)\r
+{\r
+//     static int const reg_addr=0x5;\r
+       enum tap_state end_state=cmd_queue_end_state;\r
+       if (jtag_num_devices==1)\r
+       {\r
+               /* better performance via code duplication */\r
+               if (little)\r
+               {\r
+                       int i;\r
+                       for (i = 0; i < count; i++)\r
+                       {\r
+                               shiftValueInner(TAP_SD, TAP_SD, 32, fast_target_buffer_get_u32(buffer, 1));\r
+                               shiftValueInner(TAP_SD, end_state, 6, reg_addr|(1<<5));\r
+                               buffer+=4;\r
+                       }\r
+               } else\r
+               {\r
+                       int i;\r
+                       for (i = 0; i < count; i++)\r
+                       {\r
+                               shiftValueInner(TAP_SD, TAP_SD, 32, fast_target_buffer_get_u32(buffer, 0));\r
+                               shiftValueInner(TAP_SD, end_state, 6, reg_addr|(1<<5));\r
+                               buffer+=4;\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               int i;\r
+               for (i = 0; i < count; i++)\r
+               {\r
+                       embeddedice_write_reg_inner(chain_pos, reg_addr, fast_target_buffer_get_u32(buffer, little));\r
+                       buffer += 4;\r
+               }\r
+       }\r
+}\r
+\r