- added svn props for previously added file
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 6 Aug 2008 16:30:59 +0000 (16:30 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 6 Aug 2008 16:30:59 +0000 (16:30 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@894 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/helper/tclapi.c

index 1839ae50bac813653a336eb0c397cd8517c44197..f473517d770deff4de6480a6bbd18101939b1f2b 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *\r
- *   Copyright (C) 2008 Duane Ellis                                        *\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
-#include "replacements.h"\r
-#include "target.h"\r
-#include "target_request.h"\r
-\r
-#include "log.h"\r
-#include "configuration.h"\r
-#include "binarybuffer.h"\r
-#include "jtag.h"\r
-#include "flash.h"\r
-\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <inttypes.h>\r
-\r
-#include <sys/types.h>\r
-#include <sys/stat.h>\r
-#include <unistd.h>\r
-#include <errno.h>\r
-\r
-#include <sys/time.h>\r
-#include <time.h>\r
-\r
-#include <time_support.h>\r
-\r
-#include <fileio.h>\r
-#include <image.h>\r
-\r
-static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)\r
-{\r
-       char *namebuf;\r
-       Jim_Obj *nameObjPtr, *valObjPtr;\r
-       int result;\r
-\r
-       namebuf = alloc_printf("%s(%d)", varname, idx);\r
-       if (!namebuf)\r
-               return JIM_ERR;\r
-\r
-       nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);\r
-       valObjPtr = Jim_NewIntObj(interp, val);\r
-       if (!nameObjPtr || !valObjPtr)\r
-       {\r
-               free(namebuf);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       Jim_IncrRefCount(nameObjPtr);\r
-       Jim_IncrRefCount(valObjPtr);\r
-       result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);\r
-       Jim_DecrRefCount(interp, nameObjPtr);\r
-       Jim_DecrRefCount(interp, valObjPtr);\r
-       free(namebuf);\r
-       /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */\r
-       return result;\r
-}\r
-\r
-static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)\r
-{\r
-       target_t *target;\r
-       command_context_t *context;\r
-       long l;\r
-       u32 width;\r
-       u32 len;\r
-       u32 addr;\r
-       u32 count;\r
-       u32 v;\r
-       const char *varname;\r
-       u8 buffer[4096];\r
-       int  i, n, e, retval;\r
-\r
-       /* argv[1] = name of array to receive the data\r
-        * argv[2] = desired width\r
-        * argv[3] = memory address\r
-        * argv[4] = count of times to read\r
-        */\r
-       if (argc != 5) {\r
-               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");\r
-               return JIM_ERR;\r
-       }\r
-       varname = Jim_GetString(argv[1], &len);\r
-       /* given "foo" get space for worse case "foo(%d)" .. add 20 */\r
-\r
-       e = Jim_GetLong(interp, argv[2], &l);\r
-       width = l;\r
-       if (e != JIM_OK) {\r
-               return e;\r
-       }\r
-\r
-       e = Jim_GetLong(interp, argv[3], &l);\r
-       addr = l;\r
-       if (e != JIM_OK) {\r
-               return e;\r
-       }\r
-       e = Jim_GetLong(interp, argv[4], &l);\r
-       len = l;\r
-       if (e != JIM_OK) {\r
-               return e;\r
-       }\r
-       switch (width) {\r
-               case 8:\r
-                       width = 1;\r
-                       break;\r
-               case 16:\r
-                       width = 2;\r
-                       break;\r
-               case 32:\r
-                       width = 4;\r
-                       break;\r
-               default:\r
-                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-                       Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );\r
-                       return JIM_ERR;\r
-       }\r
-       if (len == 0) {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);\r
-               return JIM_ERR;\r
-       }\r
-       if ((addr + (len * width)) < addr) {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);\r
-               return JIM_ERR;\r
-       }\r
-       /* absurd transfer size? */\r
-       if (len > 65536) {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       if ((width == 1) ||\r
-               ((width == 2) && ((addr & 1) == 0)) ||\r
-               ((width == 4) && ((addr & 3) == 0))) {\r
-               /* all is well */\r
-       } else {\r
-               char buf[100];\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       context = Jim_GetAssocData(interp, "context");\r
-       if (context == NULL)\r
-       {\r
-               LOG_ERROR("mem2array: no command context");\r
-               return JIM_ERR;\r
-       }\r
-       target = get_current_target(context);\r
-       if (target == NULL)\r
-       {\r
-               LOG_ERROR("mem2array: no current target");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       /* Transfer loop */\r
-\r
-       /* index counter */\r
-       n = 0;\r
-       /* assume ok */\r
-       e = JIM_OK;\r
-       while (len) {\r
-               /* Slurp... in buffer size chunks */\r
-\r
-               count = len; /* in objects.. */\r
-               if (count > (sizeof(buffer)/width)) {\r
-                       count = (sizeof(buffer)/width);\r
-               }\r
-\r
-               retval = target->type->read_memory( target, addr, width, count, buffer );\r
-               if (retval != ERROR_OK) {\r
-                       /* BOO !*/\r
-                       LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);\r
-                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-                       Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);\r
-                       e = JIM_ERR;\r
-                       len = 0;\r
-               } else {\r
-                       v = 0; /* shut up gcc */\r
-                       for (i = 0 ;i < count ;i++, n++) {\r
-                               switch (width) {\r
-                                       case 4:\r
-                                               v = target_buffer_get_u32(target, &buffer[i*width]);\r
-                                               break;\r
-                                       case 2:\r
-                                               v = target_buffer_get_u16(target, &buffer[i*width]);\r
-                                               break;\r
-                                       case 1:\r
-                                               v = buffer[i] & 0x0ff;\r
-                                               break;\r
-                               }\r
-                               new_int_array_element(interp, varname, n, v);\r
-                       }\r
-                       len -= count;\r
-               }\r
-       }\r
-\r
-       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)\r
-{\r
-       char *namebuf;\r
-       Jim_Obj *nameObjPtr, *valObjPtr;\r
-       int result;\r
-       long l;\r
-\r
-       namebuf = alloc_printf("%s(%d)", varname, idx);\r
-       if (!namebuf)\r
-               return JIM_ERR;\r
-\r
-       nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);\r
-       if (!nameObjPtr)\r
-       {\r
-               free(namebuf);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       Jim_IncrRefCount(nameObjPtr);\r
-       valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);\r
-       Jim_DecrRefCount(interp, nameObjPtr);\r
-       free(namebuf);\r
-       if (valObjPtr == NULL)\r
-               return JIM_ERR;\r
-\r
-       result = Jim_GetLong(interp, valObjPtr, &l);\r
-       /* printf("%s(%d) => 0%08x\n", varname, idx, val); */\r
-       *val = l;\r
-       return result;\r
-}\r
-\r
-static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)\r
-{\r
-       target_t *target;\r
-       command_context_t *context;\r
-       long l;\r
-       u32 width;\r
-       u32 len;\r
-       u32 addr;\r
-       u32 count;\r
-       u32 v;\r
-       const char *varname;\r
-       u8 buffer[4096];\r
-       int  i, n, e, retval;\r
-\r
-       /* argv[1] = name of array to get the data\r
-        * argv[2] = desired width\r
-        * argv[3] = memory address\r
-        * argv[4] = count to write\r
-        */\r
-       if (argc != 5) {\r
-               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");\r
-               return JIM_ERR;\r
-       }\r
-       varname = Jim_GetString(argv[1], &len);\r
-       /* given "foo" get space for worse case "foo(%d)" .. add 20 */\r
-\r
-       e = Jim_GetLong(interp, argv[2], &l);\r
-       width = l;\r
-       if (e != JIM_OK) {\r
-               return e;\r
-       }\r
-\r
-       e = Jim_GetLong(interp, argv[3], &l);\r
-       addr = l;\r
-       if (e != JIM_OK) {\r
-               return e;\r
-       }\r
-       e = Jim_GetLong(interp, argv[4], &l);\r
-       len = l;\r
-       if (e != JIM_OK) {\r
-               return e;\r
-       }\r
-       switch (width) {\r
-               case 8:\r
-                       width = 1;\r
-                       break;\r
-               case 16:\r
-                       width = 2;\r
-                       break;\r
-               case 32:\r
-                       width = 4;\r
-                       break;\r
-               default:\r
-                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-                       Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );\r
-                       return JIM_ERR;\r
-       }\r
-       if (len == 0) {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);\r
-               return JIM_ERR;\r
-       }\r
-       if ((addr + (len * width)) < addr) {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);\r
-               return JIM_ERR;\r
-       }\r
-       /* absurd transfer size? */\r
-       if (len > 65536) {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       if ((width == 1) ||\r
-               ((width == 2) && ((addr & 1) == 0)) ||\r
-               ((width == 4) && ((addr & 3) == 0))) {\r
-               /* all is well */\r
-       } else {\r
-               char buf[100];\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       context = Jim_GetAssocData(interp, "context");\r
-       if (context == NULL)\r
-       {\r
-               LOG_ERROR("array2mem: no command context");\r
-               return JIM_ERR;\r
-       }\r
-       target = get_current_target(context);\r
-       if (target == NULL)\r
-       {\r
-               LOG_ERROR("array2mem: no current target");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       /* Transfer loop */\r
-\r
-       /* index counter */\r
-       n = 0;\r
-       /* assume ok */\r
-       e = JIM_OK;\r
-       while (len) {\r
-               /* Slurp... in buffer size chunks */\r
-\r
-               count = len; /* in objects.. */\r
-               if (count > (sizeof(buffer)/width)) {\r
-                       count = (sizeof(buffer)/width);\r
-               }\r
-\r
-               v = 0; /* shut up gcc */\r
-               for (i = 0 ;i < count ;i++, n++) {\r
-                       get_int_array_element(interp, varname, n, &v);\r
-                       switch (width) {\r
-                       case 4:\r
-                               target_buffer_set_u32(target, &buffer[i*width], v);\r
-                               break;\r
-                       case 2:\r
-                               target_buffer_set_u16(target, &buffer[i*width], v);\r
-                               break;\r
-                       case 1:\r
-                               buffer[i] = v & 0x0ff;\r
-                               break;\r
-                       }\r
-               }\r
-               len -= count;\r
-\r
-               retval = target->type->write_memory(target, addr, width, count, buffer);\r
-               if (retval != ERROR_OK) {\r
-                       /* BOO !*/\r
-                       LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);\r
-                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-                       Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);\r
-                       e = JIM_ERR;\r
-                       len = 0;\r
-               }\r
-       }\r
-\r
-       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args)\r
-{\r
-       int retval;\r
-       scan_field_t *fields;\r
-       int num_fields;\r
-       int field_count = 0;\r
-       int i, e;\r
-       long device;\r
-\r
-       /* args[1] = device\r
-        * args[2] = num_bits\r
-        * args[3] = hex string\r
-        * ... repeat num bits and hex string ...\r
-        */\r
-       if ((argc < 4) || ((argc % 2)!=0))\r
-       {\r
-               Jim_WrongNumArgs(interp, 1, args, "wrong arguments");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       for (i = 2; i < argc; i+=2)\r
-       {\r
-               long bits;\r
-\r
-               e = Jim_GetLong(interp, args[i], &bits);\r
-               if (e != JIM_OK)\r
-                       return e;\r
-       }\r
-\r
-       e = Jim_GetLong(interp, args[1], &device);\r
-       if (e != JIM_OK)\r
-               return e;\r
-\r
-       num_fields=(argc-2)/2;\r
-       fields = malloc(sizeof(scan_field_t) * num_fields);\r
-       for (i = 2; i < argc; i+=2)\r
-       {\r
-               long bits;\r
-               int len;\r
-               const char *str;\r
-\r
-               Jim_GetLong(interp, args[i], &bits);\r
-               str = Jim_GetString(args[i+1], &len);\r
-\r
-               fields[field_count].device = device;\r
-               fields[field_count].num_bits = bits;\r
-               fields[field_count].out_value = malloc(CEIL(bits, 8));\r
-               str_to_buf(str, len, fields[field_count].out_value, bits, 0);\r
-               fields[field_count].out_mask = NULL;\r
-               fields[field_count].in_value = fields[field_count].out_value;\r
-               fields[field_count].in_check_mask = NULL;\r
-               fields[field_count].in_check_value = NULL;\r
-               fields[field_count].in_handler = NULL;\r
-               fields[field_count++].in_handler_priv = NULL;\r
-       }\r
-\r
-       jtag_add_dr_scan(num_fields, fields, -1);\r
-       retval = jtag_execute_queue();\r
-       if (retval != ERROR_OK)\r
-       {\r
-               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "drscan: jtag execute failed", NULL);\r
-               return JIM_ERR;\r
-       }\r
-\r
-       field_count=0;\r
-       Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);\r
-       for (i = 2; i < argc; i+=2)\r
-       {\r
-               long bits;\r
-               char *str;\r
-\r
-               Jim_GetLong(interp, args[i], &bits);\r
-               str = buf_to_str(fields[field_count].in_value, bits, 16);\r
-               free(fields[field_count].out_value);\r
-\r
-               Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));\r
-               free(str);\r
-               field_count++;\r
-       }\r
-\r
-       Jim_SetResult(interp, list);\r
-\r
-       free(fields);\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-static int jim_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)\r
-{\r
-       flash_bank_t *p;\r
-\r
-       if (argc != 1) {\r
-               Jim_WrongNumArgs(interp, 1, argv, "no arguments to flash_banks command");\r
-               return JIM_ERR;\r
-       }\r
-\r
-       if (!flash_banks)\r
-       {\r
-               return JIM_ERR;\r
-       }\r
-\r
-       Jim_Obj *list=Jim_NewListObj(interp, NULL, 0);\r
-       for (p = flash_banks; p; p = p->next)\r
-       {\r
-               Jim_Obj *elem=Jim_NewListObj(interp, NULL, 0);\r
-\r
-               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));\r
-               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));\r
-\r
-               Jim_ListAppendElement(interp, list, elem);\r
-       }\r
-\r
-       Jim_SetResult(interp, list);\r
-\r
-       return JIM_OK;\r
-}\r
-\r
-\r
-int tclapi_register_commands()\r
-{\r
-       register_jim("ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing");\r
-       register_jim("ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values");\r
-       register_jim("drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");\r
-       register_jim("ocd_flash_banks", jim_flash_banks, "return information about the flash banks");\r
-\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
+ *   Copyright (C) 2008 Duane Ellis                                        *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "target.h"
+#include "target_request.h"
+
+#include "log.h"
+#include "configuration.h"
+#include "binarybuffer.h"
+#include "jtag.h"
+#include "flash.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <time_support.h>
+
+#include <fileio.h>
+#include <image.h>
+
+static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
+{
+       char *namebuf;
+       Jim_Obj *nameObjPtr, *valObjPtr;
+       int result;
+
+       namebuf = alloc_printf("%s(%d)", varname, idx);
+       if (!namebuf)
+               return JIM_ERR;
+
+       nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
+       valObjPtr = Jim_NewIntObj(interp, val);
+       if (!nameObjPtr || !valObjPtr)
+       {
+               free(namebuf);
+               return JIM_ERR;
+       }
+
+       Jim_IncrRefCount(nameObjPtr);
+       Jim_IncrRefCount(valObjPtr);
+       result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
+       Jim_DecrRefCount(interp, nameObjPtr);
+       Jim_DecrRefCount(interp, valObjPtr);
+       free(namebuf);
+       /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
+       return result;
+}
+
+static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       target_t *target;
+       command_context_t *context;
+       long l;
+       u32 width;
+       u32 len;
+       u32 addr;
+       u32 count;
+       u32 v;
+       const char *varname;
+       u8 buffer[4096];
+       int  i, n, e, retval;
+
+       /* argv[1] = name of array to receive the data
+        * argv[2] = desired width
+        * argv[3] = memory address
+        * argv[4] = count of times to read
+        */
+       if (argc != 5) {
+               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+               return JIM_ERR;
+       }
+       varname = Jim_GetString(argv[1], &len);
+       /* given "foo" get space for worse case "foo(%d)" .. add 20 */
+
+       e = Jim_GetLong(interp, argv[2], &l);
+       width = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+
+       e = Jim_GetLong(interp, argv[3], &l);
+       addr = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+       e = Jim_GetLong(interp, argv[4], &l);
+       len = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+       switch (width) {
+               case 8:
+                       width = 1;
+                       break;
+               case 16:
+                       width = 2;
+                       break;
+               case 32:
+                       width = 4;
+                       break;
+               default:
+                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+                       Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
+                       return JIM_ERR;
+       }
+       if (len == 0) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
+               return JIM_ERR;
+       }
+       if ((addr + (len * width)) < addr) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
+               return JIM_ERR;
+       }
+       /* absurd transfer size? */
+       if (len > 65536) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
+               return JIM_ERR;
+       }
+
+       if ((width == 1) ||
+               ((width == 2) && ((addr & 1) == 0)) ||
+               ((width == 4) && ((addr & 3) == 0))) {
+               /* all is well */
+       } else {
+               char buf[100];
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
+               Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
+               return JIM_ERR;
+       }
+
+       context = Jim_GetAssocData(interp, "context");
+       if (context == NULL)
+       {
+               LOG_ERROR("mem2array: no command context");
+               return JIM_ERR;
+       }
+       target = get_current_target(context);
+       if (target == NULL)
+       {
+               LOG_ERROR("mem2array: no current target");
+               return JIM_ERR;
+       }
+
+       /* Transfer loop */
+
+       /* index counter */
+       n = 0;
+       /* assume ok */
+       e = JIM_OK;
+       while (len) {
+               /* Slurp... in buffer size chunks */
+
+               count = len; /* in objects.. */
+               if (count > (sizeof(buffer)/width)) {
+                       count = (sizeof(buffer)/width);
+               }
+
+               retval = target->type->read_memory( target, addr, width, count, buffer );
+               if (retval != ERROR_OK) {
+                       /* BOO !*/
+                       LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
+                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+                       Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
+                       e = JIM_ERR;
+                       len = 0;
+               } else {
+                       v = 0; /* shut up gcc */
+                       for (i = 0 ;i < count ;i++, n++) {
+                               switch (width) {
+                                       case 4:
+                                               v = target_buffer_get_u32(target, &buffer[i*width]);
+                                               break;
+                                       case 2:
+                                               v = target_buffer_get_u16(target, &buffer[i*width]);
+                                               break;
+                                       case 1:
+                                               v = buffer[i] & 0x0ff;
+                                               break;
+                               }
+                               new_int_array_element(interp, varname, n, v);
+                       }
+                       len -= count;
+               }
+       }
+
+       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+
+       return JIM_OK;
+}
+
+static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)
+{
+       char *namebuf;
+       Jim_Obj *nameObjPtr, *valObjPtr;
+       int result;
+       long l;
+
+       namebuf = alloc_printf("%s(%d)", varname, idx);
+       if (!namebuf)
+               return JIM_ERR;
+
+       nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
+       if (!nameObjPtr)
+       {
+               free(namebuf);
+               return JIM_ERR;
+       }
+
+       Jim_IncrRefCount(nameObjPtr);
+       valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
+       Jim_DecrRefCount(interp, nameObjPtr);
+       free(namebuf);
+       if (valObjPtr == NULL)
+               return JIM_ERR;
+
+       result = Jim_GetLong(interp, valObjPtr, &l);
+       /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
+       *val = l;
+       return result;
+}
+
+static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       target_t *target;
+       command_context_t *context;
+       long l;
+       u32 width;
+       u32 len;
+       u32 addr;
+       u32 count;
+       u32 v;
+       const char *varname;
+       u8 buffer[4096];
+       int  i, n, e, retval;
+
+       /* argv[1] = name of array to get the data
+        * argv[2] = desired width
+        * argv[3] = memory address
+        * argv[4] = count to write
+        */
+       if (argc != 5) {
+               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+               return JIM_ERR;
+       }
+       varname = Jim_GetString(argv[1], &len);
+       /* given "foo" get space for worse case "foo(%d)" .. add 20 */
+
+       e = Jim_GetLong(interp, argv[2], &l);
+       width = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+
+       e = Jim_GetLong(interp, argv[3], &l);
+       addr = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+       e = Jim_GetLong(interp, argv[4], &l);
+       len = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+       switch (width) {
+               case 8:
+                       width = 1;
+                       break;
+               case 16:
+                       width = 2;
+                       break;
+               case 32:
+                       width = 4;
+                       break;
+               default:
+                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+                       Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
+                       return JIM_ERR;
+       }
+       if (len == 0) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
+               return JIM_ERR;
+       }
+       if ((addr + (len * width)) < addr) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
+               return JIM_ERR;
+       }
+       /* absurd transfer size? */
+       if (len > 65536) {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
+               return JIM_ERR;
+       }
+
+       if ((width == 1) ||
+               ((width == 2) && ((addr & 1) == 0)) ||
+               ((width == 4) && ((addr & 3) == 0))) {
+               /* all is well */
+       } else {
+               char buf[100];
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);
+               Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
+               return JIM_ERR;
+       }
+
+       context = Jim_GetAssocData(interp, "context");
+       if (context == NULL)
+       {
+               LOG_ERROR("array2mem: no command context");
+               return JIM_ERR;
+       }
+       target = get_current_target(context);
+       if (target == NULL)
+       {
+               LOG_ERROR("array2mem: no current target");
+               return JIM_ERR;
+       }
+
+       /* Transfer loop */
+
+       /* index counter */
+       n = 0;
+       /* assume ok */
+       e = JIM_OK;
+       while (len) {
+               /* Slurp... in buffer size chunks */
+
+               count = len; /* in objects.. */
+               if (count > (sizeof(buffer)/width)) {
+                       count = (sizeof(buffer)/width);
+               }
+
+               v = 0; /* shut up gcc */
+               for (i = 0 ;i < count ;i++, n++) {
+                       get_int_array_element(interp, varname, n, &v);
+                       switch (width) {
+                       case 4:
+                               target_buffer_set_u32(target, &buffer[i*width], v);
+                               break;
+                       case 2:
+                               target_buffer_set_u16(target, &buffer[i*width], v);
+                               break;
+                       case 1:
+                               buffer[i] = v & 0x0ff;
+                               break;
+                       }
+               }
+               len -= count;
+
+               retval = target->type->write_memory(target, addr, width, count, buffer);
+               if (retval != ERROR_OK) {
+                       /* BOO !*/
+                       LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
+                       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+                       Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
+                       e = JIM_ERR;
+                       len = 0;
+               }
+       }
+
+       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+
+       return JIM_OK;
+}
+
+int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args)
+{
+       int retval;
+       scan_field_t *fields;
+       int num_fields;
+       int field_count = 0;
+       int i, e;
+       long device;
+
+       /* args[1] = device
+        * args[2] = num_bits
+        * args[3] = hex string
+        * ... repeat num bits and hex string ...
+        */
+       if ((argc < 4) || ((argc % 2)!=0))
+       {
+               Jim_WrongNumArgs(interp, 1, args, "wrong arguments");
+               return JIM_ERR;
+       }
+
+       for (i = 2; i < argc; i+=2)
+       {
+               long bits;
+
+               e = Jim_GetLong(interp, args[i], &bits);
+               if (e != JIM_OK)
+                       return e;
+       }
+
+       e = Jim_GetLong(interp, args[1], &device);
+       if (e != JIM_OK)
+               return e;
+
+       num_fields=(argc-2)/2;
+       fields = malloc(sizeof(scan_field_t) * num_fields);
+       for (i = 2; i < argc; i+=2)
+       {
+               long bits;
+               int len;
+               const char *str;
+
+               Jim_GetLong(interp, args[i], &bits);
+               str = Jim_GetString(args[i+1], &len);
+
+               fields[field_count].device = device;
+               fields[field_count].num_bits = bits;
+               fields[field_count].out_value = malloc(CEIL(bits, 8));
+               str_to_buf(str, len, fields[field_count].out_value, bits, 0);
+               fields[field_count].out_mask = NULL;
+               fields[field_count].in_value = fields[field_count].out_value;
+               fields[field_count].in_check_mask = NULL;
+               fields[field_count].in_check_value = NULL;
+               fields[field_count].in_handler = NULL;
+               fields[field_count++].in_handler_priv = NULL;
+       }
+
+       jtag_add_dr_scan(num_fields, fields, -1);
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+       {
+               Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+               Jim_AppendStrings(interp, Jim_GetResult(interp), "drscan: jtag execute failed", NULL);
+               return JIM_ERR;
+       }
+
+       field_count=0;
+       Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
+       for (i = 2; i < argc; i+=2)
+       {
+               long bits;
+               char *str;
+
+               Jim_GetLong(interp, args[i], &bits);
+               str = buf_to_str(fields[field_count].in_value, bits, 16);
+               free(fields[field_count].out_value);
+
+               Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));
+               free(str);
+               field_count++;
+       }
+
+       Jim_SetResult(interp, list);
+
+       free(fields);
+
+       return JIM_OK;
+}
+
+static int jim_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       flash_bank_t *p;
+
+       if (argc != 1) {
+               Jim_WrongNumArgs(interp, 1, argv, "no arguments to flash_banks command");
+               return JIM_ERR;
+       }
+
+       if (!flash_banks)
+       {
+               return JIM_ERR;
+       }
+
+       Jim_Obj *list=Jim_NewListObj(interp, NULL, 0);
+       for (p = flash_banks; p; p = p->next)
+       {
+               Jim_Obj *elem=Jim_NewListObj(interp, NULL, 0);
+
+               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
+               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
+               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
+               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
+               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
+               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
+               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
+               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
+               Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
+               Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
+
+               Jim_ListAppendElement(interp, list, elem);
+       }
+
+       Jim_SetResult(interp, list);
+
+       return JIM_OK;
+}
+
+
+int tclapi_register_commands()
+{
+       register_jim("ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing");
+       register_jim("ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values");
+       register_jim("drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
+       register_jim("ocd_flash_banks", jim_flash_banks, "return information about the flash banks");
+
+}