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 81de281332aa8ecf79772d7c2ab6a02384bf67b9..d04308e5249fa0bb5ac3c96784549a4e700e4eab 100644 (file)
@@ -1,7 +1,7 @@
 bin_PROGRAMS = openocd
 
 if ECOSBOARD
 bin_PROGRAMS = openocd
 
 if ECOSBOARD
-MAINFILE = $(ECOS_SOURCE_FILES)/ecosboard.c
+MAINFILE = ecosboard.c
 else
 MAINFILE = main.c
 endif
 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 76a38409ca502f256f36e2e156f91ec53746d5e1..b5a3d8a6afdc339ad654348773df2640ecd3262b 100644 (file)
@@ -54,7 +54,7 @@ EP93XXFILES =
 endif
 
 if ECOSBOARD
 endif
 
 if ECOSBOARD
-ECOSBOARDFILES = $(ECOS_SOURCE_FILES)/zy1000.c
+ECOSBOARDFILES = zy1000.c
 else
 ECOSBOARDFILES =
 endif
 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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)