--- /dev/null
+/***************************************************************************\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
--- /dev/null
+/***************************************************************************\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