]> git.sur5r.net Git - openocd/commitdiff
- convert all files to unix line-ending
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 25 Feb 2008 17:48:04 +0000 (17:48 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Mon, 25 Feb 2008 17:48:04 +0000 (17:48 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@347 b42882b7-edfa-0310-969c-e2dbd0fdcd60

42 files changed:
src/flash/at91sam7.h
src/flash/cfi.c
src/flash/s3c2440_nand.c
src/flash/str9xpec.c
src/helper/command.c
src/helper/configuration.c
src/helper/log.c
src/helper/log.h
src/helper/options.c
src/helper/replacements.h
src/jtag/bitq.c
src/jtag/ep93xx.c
src/jtag/ft2232.c
src/jtag/jtag.c
src/jtag/usbprog.c
src/openocd.c
src/pld/virtex2.c
src/server/gdb_server.c
src/server/server.c
src/server/telnet_server.c
src/target/arm11.c
src/target/arm11.h
src/target/arm11_dbgtap.c
src/target/arm720t.c
src/target/arm7_9_common.c
src/target/arm7tdmi.c
src/target/arm920t.c
src/target/arm926ejs.c
src/target/arm966e.c
src/target/arm9tdmi.c
src/target/arm_jtag.c
src/target/cortex_swjdp.c
src/target/embeddedice.c
src/target/etb.c
src/target/etb.h
src/target/etm.c
src/target/etm.h
src/target/etm_dummy.h
src/target/oocd_trace.h
src/target/target.c
src/target/xscale.c
src/xsvf/xsvf.c

index 4ef154c97f6516208d07c3208b49061b03af52d6..eb0213c035e86e8611eb8020e1c7c8558af0abfb 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2006 by Magnus Lundin                                   *\r
- *   lundin@mlu.mine.nu                                                    *\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
-#ifndef AT91SAM7_H\r
-#define AT91SAM7_H\r
-\r
-#include "flash.h"\r
-#include "target.h"\r
-\r
-typedef struct at91sam7_flash_bank_s\r
-{\r
-       u32 working_area;\r
-       u32 working_area_size;\r
-\r
-       /* chip id register */\r
-       u32 cidr;\r
-       u16 cidr_ext;\r
-       u16 cidr_nvptyp;\r
-       u16 cidr_arch;\r
-       u16 cidr_sramsiz;\r
-       u16 cidr_nvpsiz;\r
-       u16 cidr_nvpsiz2;\r
-       u16 cidr_eproc;\r
-       u16 cidr_version;\r
-       char * target_name;\r
-\r
-       /* flash geometry */\r
-       u16 num_pages;\r
-       u16 pagesize;\r
-       u16 pages_in_lockregion;\r
-       u8 num_erase_regions;\r
-       u8 num_planes;\r
-       u32 *erase_region_info;\r
-\r
-       /* nv memory bits */\r
-       u16 num_lockbits;\r
-       u16 lockbits[4];\r
-       u16 num_nvmbits;\r
-       u16 nvmbits;\r
-       u8  securitybit;\r
-       u8  flashmode[4];         /* 0: not init, 1: fmcn for nvbits (1uS), 2: fmcn for flash (1.5uS) */\r
-\r
-       /* main clock status */\r
-       u8  mck_valid;\r
-       u32 mck_freq;\r
-       \r
-       int probed;\r
-       \r
-} at91sam7_flash_bank_t;\r
-\r
-/* AT91SAM7 control registers */\r
-#define DBGU_CIDR 0xFFFFF240\r
-#define CKGR_MCFR 0xFFFFFC24\r
-#define CKGR_MCFR_MAINRDY  0x10000\r
-#define CKGR_PLLR 0xFFFFFC2c\r
-#define CKGR_PLLR_DIV 0xff\r
-#define CKGR_PLLR_MUL 0x07ff0000\r
-#define PMC_MCKR  0xFFFFFC30\r
-#define PMC_MCKR_CSS  0x03\r
-#define PMC_MCKR_PRES 0x1c\r
-\r
-/* Flash Controller Commands */\r
-#define  WP   0x01\r
-#define  SLB  0x02\r
-#define  WPL  0x03\r
-#define  CLB  0x04\r
-#define  EA   0x08\r
-#define  SGPB 0x0B\r
-#define  CGPB 0x0D\r
-#define  SSB  0x0F\r
-\r
-/* MC_FSR bit definitions */\r
-#define        MC_FSR_FRDY 1\r
-#define        MC_FSR_EOL 2\r
-\r
-/* AT91SAM7 constants */\r
-#define RC_FREQ  32000\r
-\r
-/*  FLASH_TIMING_MODES */\r
-#define  FMR_TIMING_NONE    0\r
-#define  FMR_TIMING_NVBITS  1\r
-#define  FMR_TIMING_FLASH   2\r
-\r
-#endif /* AT91SAM7_H */\r
+/***************************************************************************
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef AT91SAM7_H
+#define AT91SAM7_H
+
+#include "flash.h"
+#include "target.h"
+
+typedef struct at91sam7_flash_bank_s
+{
+       u32 working_area;
+       u32 working_area_size;
+
+       /* chip id register */
+       u32 cidr;
+       u16 cidr_ext;
+       u16 cidr_nvptyp;
+       u16 cidr_arch;
+       u16 cidr_sramsiz;
+       u16 cidr_nvpsiz;
+       u16 cidr_nvpsiz2;
+       u16 cidr_eproc;
+       u16 cidr_version;
+       char * target_name;
+
+       /* flash geometry */
+       u16 num_pages;
+       u16 pagesize;
+       u16 pages_in_lockregion;
+       u8 num_erase_regions;
+       u8 num_planes;
+       u32 *erase_region_info;
+
+       /* nv memory bits */
+       u16 num_lockbits;
+       u16 lockbits[4];
+       u16 num_nvmbits;
+       u16 nvmbits;
+       u8  securitybit;
+       u8  flashmode[4];         /* 0: not init, 1: fmcn for nvbits (1uS), 2: fmcn for flash (1.5uS) */
+
+       /* main clock status */
+       u8  mck_valid;
+       u32 mck_freq;
+       
+       int probed;
+       
+} at91sam7_flash_bank_t;
+
+/* AT91SAM7 control registers */
+#define DBGU_CIDR 0xFFFFF240
+#define CKGR_MCFR 0xFFFFFC24
+#define CKGR_MCFR_MAINRDY  0x10000
+#define CKGR_PLLR 0xFFFFFC2c
+#define CKGR_PLLR_DIV 0xff
+#define CKGR_PLLR_MUL 0x07ff0000
+#define PMC_MCKR  0xFFFFFC30
+#define PMC_MCKR_CSS  0x03
+#define PMC_MCKR_PRES 0x1c
+
+/* Flash Controller Commands */
+#define  WP   0x01
+#define  SLB  0x02
+#define  WPL  0x03
+#define  CLB  0x04
+#define  EA   0x08
+#define  SGPB 0x0B
+#define  CGPB 0x0D
+#define  SSB  0x0F
+
+/* MC_FSR bit definitions */
+#define        MC_FSR_FRDY 1
+#define        MC_FSR_EOL 2
+
+/* AT91SAM7 constants */
+#define RC_FREQ  32000
+
+/*  FLASH_TIMING_MODES */
+#define  FMR_TIMING_NONE    0
+#define  FMR_TIMING_NVBITS  1
+#define  FMR_TIMING_FLASH   2
+
+#endif /* AT91SAM7_H */
index 82120d8d2e16d7896e0d9b00031c04df27c38505..88e8e63db44a68d12e3f7a382e9cc5a58065072d 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005, 2007 by Dominic Rath                              *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "cfi.h"\r
-\r
-#include "flash.h"\r
-#include "target.h"\r
-#include "log.h"\r
-#include "armv4_5.h"\r
-#include "algorithm.h"\r
-#include "binarybuffer.h"\r
-#include "types.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <unistd.h>\r
-\r
-int cfi_register_commands(struct command_context_s *cmd_ctx);\r
-int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);\r
-int cfi_erase(struct flash_bank_s *bank, int first, int last);\r
-int cfi_protect(struct flash_bank_s *bank, int set, int first, int last);\r
-int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);\r
-int cfi_probe(struct flash_bank_s *bank);\r
-int cfi_auto_probe(struct flash_bank_s *bank);\r
-int cfi_erase_check(struct flash_bank_s *bank);\r
-int cfi_protect_check(struct flash_bank_s *bank);\r
-int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size);\r
-\r
-int cfi_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-#define CFI_MAX_BUS_WIDTH      4\r
-#define CFI_MAX_CHIP_WIDTH     4\r
-\r
-/* defines internal maximum size for code fragment in cfi_intel_write_block() */\r
-#define CFI_MAX_INTEL_CODESIZE 256\r
-\r
-flash_driver_t cfi_flash =\r
-{\r
-       .name = "cfi",\r
-       .register_commands = cfi_register_commands,\r
-       .flash_bank_command = cfi_flash_bank_command,\r
-       .erase = cfi_erase,\r
-       .protect = cfi_protect,\r
-       .write = cfi_write,\r
-       .probe = cfi_probe,\r
-       .auto_probe = cfi_auto_probe,\r
-       .erase_check = cfi_erase_check,\r
-       .protect_check = cfi_protect_check,\r
-       .info = cfi_info\r
-};\r
-\r
-cfi_unlock_addresses_t cfi_unlock_addresses[] =\r
-{\r
-       [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },\r
-       [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },\r
-};\r
-\r
-/* CFI fixups foward declarations */\r
-void cfi_fixup_non_cfi(flash_bank_t *flash, void *param);\r
-void cfi_fixup_0002_erase_regions(flash_bank_t *flash, void *param);\r
-void cfi_fixup_0002_unlock_addresses(flash_bank_t *flash, void *param);\r
-void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);\r
-\r
-/* fixup after identifying JEDEC manufactuer and ID */\r
-cfi_fixup_t cfi_jedec_fixups[] = {\r
-       {CFI_MFR_SST, 0x00D4, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_SST, 0x00D5, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_SST, 0x00D6, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_SST, 0x00D7, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_SST, 0x2780, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_ST, 0x00D5, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_ST, 0x00D6, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_AMD, 0x2223, cfi_fixup_non_cfi, NULL},\r
-       {CFI_MFR_AMD, 0x22ab, cfi_fixup_non_cfi, NULL},\r
-       {0, 0, NULL, NULL}\r
-};\r
-\r
-/* fixup after reading cmdset 0002 primary query table */\r
-cfi_fixup_t cfi_0002_fixups[] = {\r
-       {CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
-       {CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
-       {CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
-       {CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
-       {CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},\r
-       {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_atmel_reversed_erase_regions, NULL},\r
-       {CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL},\r
-       {0, 0, NULL, NULL}\r
-};\r
-\r
-/* fixup after reading cmdset 0001 primary query table */\r
-cfi_fixup_t cfi_0001_fixups[] = {\r
-       {0, 0, NULL, NULL}\r
-};\r
-\r
-void cfi_fixup(flash_bank_t *bank, cfi_fixup_t *fixups)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_fixup_t *f;\r
-\r
-       for (f = fixups; f->fixup; f++)\r
-       {\r
-               if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi_info->manufacturer)) &&\r
-                       ((f->id  == CFI_ID_ANY)  || (f->id  == cfi_info->device_id)))\r
-               {\r
-                       f->fixup(bank, f->param);\r
-               }\r
-       }\r
-}\r
-\r
-inline u32 flash_address(flash_bank_t *bank, int sector, u32 offset)\r
-{\r
-       /* while the sector list isn't built, only accesses to sector 0 work */\r
-       if (sector == 0)\r
-               return bank->base + offset * bank->bus_width;\r
-       else\r
-       {\r
-               if (!bank->sectors)\r
-               {\r
-                       ERROR("BUG: sector list not yet built");\r
-                       exit(-1);\r
-               }\r
-               return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;\r
-       }\r
-\r
-}\r
-\r
-void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)\r
-{\r
-       int i;\r
-\r
-       /* clear whole buffer, to ensure bits that exceed the bus_width\r
-        * are set to zero\r
-        */\r
-       for (i = 0; i < CFI_MAX_BUS_WIDTH; i++)\r
-               cmd_buf[i] = 0;\r
-\r
-       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
-       {\r
-               for (i = bank->bus_width; i > 0; i--)\r
-               {\r
-                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               for (i = 1; i <= bank->bus_width; i++)\r
-               {\r
-                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;\r
-               }\r
-       }\r
-}\r
-\r
-/* read unsigned 8-bit value from the bank\r
- * flash banks are expected to be made of similar chips\r
- * the query result should be the same for all\r
- */\r
-u8 cfi_query_u8(flash_bank_t *bank, int sector, u32 offset)\r
-{\r
-       target_t *target = bank->target;\r
-       u8 data[CFI_MAX_BUS_WIDTH];\r
-\r
-       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);\r
-\r
-       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
-               return data[0];\r
-       else\r
-               return data[bank->bus_width - 1];\r
-}\r
-\r
-/* read unsigned 8-bit value from the bank\r
- * in case of a bank made of multiple chips,\r
- * the individual values are ORed\r
- */\r
-u8 cfi_get_u8(flash_bank_t *bank, int sector, u32 offset)\r
-{\r
-       target_t *target = bank->target;\r
-       u8 data[CFI_MAX_BUS_WIDTH];\r
-       int i;\r
-\r
-       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);\r
-\r
-       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
-       {\r
-               for (i = 0; i < bank->bus_width / bank->chip_width; i++)\r
-                       data[0] |= data[i];\r
-\r
-               return data[0];\r
-       }\r
-       else\r
-       {\r
-               u8 value = 0;\r
-               for (i = 0; i < bank->bus_width / bank->chip_width; i++)\r
-                       value |= data[bank->bus_width - 1 - i];\r
-\r
-               return value;\r
-       }\r
-}\r
-\r
-u16 cfi_query_u16(flash_bank_t *bank, int sector, u32 offset)\r
-{\r
-       target_t *target = bank->target;\r
-       u8 data[CFI_MAX_BUS_WIDTH * 2];\r
-\r
-       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data);\r
-\r
-       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
-               return data[0] | data[bank->bus_width] << 8;\r
-       else\r
-               return data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;\r
-}\r
-\r
-u32 cfi_query_u32(flash_bank_t *bank, int sector, u32 offset)\r
-{\r
-       target_t *target = bank->target;\r
-       u8 data[CFI_MAX_BUS_WIDTH * 4];\r
-\r
-       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data);\r
-\r
-       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)\r
-               return data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;\r
-       else\r
-               return data[bank->bus_width - 1] | data[(2* bank->bus_width) - 1] << 8 |\r
-                               data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;\r
-}\r
-\r
-void cfi_intel_clear_status_register(flash_bank_t *bank)\r
-{\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               ERROR("BUG: attempted to clear status register while target wasn't halted");\r
-               exit(-1);\r
-       }\r
-\r
-       cfi_command(bank, 0x50, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-}\r
-\r
-u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)\r
-{\r
-       u8 status;\r
-\r
-       while ((!((status = cfi_get_u8(bank, 0, 0x0)) & 0x80)) && (timeout-- > 0))\r
-       {\r
-               DEBUG("status: 0x%x", status);\r
-               usleep(1000);\r
-       }\r
-\r
-       /* mask out bit 0 (reserved) */\r
-       status = status & 0xfe;\r
-\r
-       DEBUG("status: 0x%x", status);\r
-\r
-       if ((status & 0x80) != 0x80)\r
-       {\r
-               ERROR("timeout while waiting for WSM to become ready");\r
-       }\r
-       else if (status != 0x80)\r
-       {\r
-               ERROR("status register: 0x%x", status);\r
-               if (status & 0x2)\r
-                       ERROR("Block Lock-Bit Detected, Operation Abort");\r
-               if (status & 0x4)\r
-                       ERROR("Program suspended");\r
-               if (status & 0x8)\r
-                       ERROR("Low Programming Voltage Detected, Operation Aborted");\r
-               if (status & 0x10)\r
-                       ERROR("Program Error / Error in Setting Lock-Bit");\r
-               if (status & 0x20)\r
-                       ERROR("Error in Block Erasure or Clear Lock-Bits");\r
-               if (status & 0x40)\r
-                       ERROR("Block Erase Suspended");\r
-\r
-               cfi_intel_clear_status_register(bank);\r
-       }\r
-\r
-       return status;\r
-}\r
-\r
-int cfi_spansion_wait_status_busy(flash_bank_t *bank, int timeout)\r
-{\r
-       u8 status, oldstatus;\r
-\r
-       oldstatus = cfi_get_u8(bank, 0, 0x0);\r
-\r
-       do {\r
-               status = cfi_get_u8(bank, 0, 0x0);\r
-               if ((status ^ oldstatus) & 0x40) {\r
-                       if (status & 0x20) {\r
-                               oldstatus = cfi_get_u8(bank, 0, 0x0);\r
-                               status = cfi_get_u8(bank, 0, 0x0);\r
-                               if ((status ^ oldstatus) & 0x40) {\r
-                                       ERROR("dq5 timeout, status: 0x%x", status);\r
-                                       return(ERROR_FLASH_OPERATION_FAILED);\r
-                               } else {\r
-                                       DEBUG("status: 0x%x", status);\r
-                                       return(ERROR_OK);\r
-                               }\r
-                       }\r
-               } else {\r
-                       DEBUG("status: 0x%x", status);\r
-                       return(ERROR_OK);\r
-               }\r
-\r
-               oldstatus = status;\r
-               usleep(1000);\r
-       } while (timeout-- > 0);\r
-\r
-       ERROR("timeout, status: 0x%x", status);\r
-\r
-       return(ERROR_FLASH_BUSY);\r
-}\r
-\r
-int cfi_read_intel_pri_ext(flash_bank_t *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_intel_pri_ext_t *pri_ext = malloc(sizeof(cfi_intel_pri_ext_t));\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       cfi_info->pri_ext = pri_ext;\r
-\r
-       pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);\r
-       pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);\r
-       pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);\r
-\r
-       if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))\r
-       {\r
-               cfi_command(bank, 0xf0, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-               cfi_command(bank, 0xff, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);\r
-       pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);\r
-\r
-       DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);\r
-\r
-       pri_ext->feature_support = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5);\r
-       pri_ext->suspend_cmd_support = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);\r
-       pri_ext->blk_status_reg_mask = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa);\r
-\r
-       DEBUG("feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);\r
-\r
-       pri_ext->vcc_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc);\r
-       pri_ext->vpp_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd);\r
-\r
-       DEBUG("Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x",\r
-                 (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,\r
-                 (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);\r
-\r
-       pri_ext->num_protection_fields = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe);\r
-       if (pri_ext->num_protection_fields != 1)\r
-       {\r
-               WARNING("expected one protection register field, but found %i", pri_ext->num_protection_fields);\r
-       }\r
-\r
-       pri_ext->prot_reg_addr = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf);\r
-       pri_ext->fact_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11);\r
-       pri_ext->user_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12);\r
-\r
-       DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_read_spansion_pri_ext(flash_bank_t *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       cfi_info->pri_ext = pri_ext;\r
-\r
-       pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);\r
-       pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);\r
-       pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);\r
-\r
-       if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))\r
-       {\r
-               cfi_command(bank, 0xf0, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);\r
-       pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);\r
-\r
-       DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);\r
-\r
-       pri_ext->SiliconRevision = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);\r
-       pri_ext->EraseSuspend    = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);\r
-       pri_ext->BlkProt         = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);\r
-       pri_ext->TmpBlkUnprotect = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);\r
-       pri_ext->BlkProtUnprot   = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);\r
-       pri_ext->SimultaneousOps = cfi_query_u8(bank, 0, cfi_info->pri_addr + 10);\r
-       pri_ext->BurstMode       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 11);\r
-       pri_ext->PageMode        = cfi_query_u8(bank, 0, cfi_info->pri_addr + 12);\r
-       pri_ext->VppMin          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 13);\r
-       pri_ext->VppMax          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 14);\r
-       pri_ext->TopBottom       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 15);\r
-\r
-       DEBUG("Silicon Revision: 0x%x, Erase Suspend: 0x%x, Block protect: 0x%x", pri_ext->SiliconRevision,\r
-             pri_ext->EraseSuspend, pri_ext->BlkProt);\r
-\r
-       DEBUG("Temporary Unprotect: 0x%x, Block Protect Scheme: 0x%x, Simultaneous Ops: 0x%x", pri_ext->TmpBlkUnprotect,\r
-             pri_ext->BlkProtUnprot, pri_ext->SimultaneousOps);\r
-\r
-       DEBUG("Burst Mode: 0x%x, Page Mode: 0x%x, ", pri_ext->BurstMode, pri_ext->PageMode);\r
-\r
-\r
-       DEBUG("Vpp min: %2.2d.%1.1d, Vpp max: %2.2d.%1.1x",\r
-                 (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,\r
-                 (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);\r
-\r
-       DEBUG("WP# protection 0x%x", pri_ext->TopBottom);\r
-\r
-       /* default values for implementation specific workarounds */\r
-       pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;\r
-       pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;\r
-       pri_ext->_reversed_geometry = 0;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_read_atmel_pri_ext(flash_bank_t *bank)\r
-{\r
-       cfi_atmel_pri_ext_t atmel_pri_ext;\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       /* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion,\r
-        * but a different primary extended query table.\r
-        * We read the atmel table, and prepare a valid AMD/Spansion query table.\r
-        */\r
-\r
-       memset(pri_ext, 0, sizeof(cfi_spansion_pri_ext_t));\r
-\r
-       cfi_info->pri_ext = pri_ext;\r
-\r
-       atmel_pri_ext.pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);\r
-       atmel_pri_ext.pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);\r
-       atmel_pri_ext.pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);\r
-\r
-       if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R') || (atmel_pri_ext.pri[2] != 'I'))\r
-       {\r
-               cfi_command(bank, 0xf0, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       pri_ext->pri[0] = atmel_pri_ext.pri[0];\r
-       pri_ext->pri[1] = atmel_pri_ext.pri[1];\r
-       pri_ext->pri[2] = atmel_pri_ext.pri[2];\r
-\r
-       atmel_pri_ext.major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);\r
-       atmel_pri_ext.minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);\r
-\r
-       DEBUG("pri: '%c%c%c', version: %c.%c", atmel_pri_ext.pri[0], atmel_pri_ext.pri[1], atmel_pri_ext.pri[2], atmel_pri_ext.major_version, atmel_pri_ext.minor_version);\r
-\r
-       pri_ext->major_version = atmel_pri_ext.major_version;\r
-       pri_ext->minor_version = atmel_pri_ext.minor_version;\r
-\r
-       atmel_pri_ext.features = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);\r
-       atmel_pri_ext.bottom_boot = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);\r
-       atmel_pri_ext.burst_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);\r
-       atmel_pri_ext.page_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);\r
-\r
-       DEBUG("features: 0x%2.2x, bottom_boot: 0x%2.2x, burst_mode: 0x%2.2x, page_mode: 0x%2.2x",\r
-               atmel_pri_ext.features, atmel_pri_ext.bottom_boot, atmel_pri_ext.burst_mode, atmel_pri_ext.page_mode);\r
-\r
-       if (atmel_pri_ext.features & 0x02)\r
-               pri_ext->EraseSuspend = 2;\r
-\r
-       if (atmel_pri_ext.bottom_boot)\r
-               pri_ext->TopBottom = 2;\r
-       else\r
-               pri_ext->TopBottom = 3;\r
-\r
-       pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;\r
-       pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_read_0002_pri_ext(flash_bank_t *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       if (cfi_info->manufacturer == CFI_MFR_ATMEL)\r
-       {\r
-               return cfi_read_atmel_pri_ext(bank);\r
-       }\r
-       else\r
-       {\r
-               return cfi_read_spansion_pri_ext(bank);\r
-       }\r
-}\r
-\r
-int cfi_spansion_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
-{\r
-       int printed;\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-\r
-       printed = snprintf(buf, buf_size, "\nSpansion primary algorithm extend information:\n");\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0],\r
-                          pri_ext->pri[1], pri_ext->pri[2],\r
-                          pri_ext->major_version, pri_ext->minor_version);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "Silicon Rev.: 0x%x, Address Sensitive unlock: 0x%x\n",\r
-                          (pri_ext->SiliconRevision) >> 2,\r
-                          (pri_ext->SiliconRevision) & 0x03);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "Erase Suspend: 0x%x, Sector Protect: 0x%x\n",\r
-                          pri_ext->EraseSuspend,\r
-                          pri_ext->BlkProt);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "VppMin: %2.2d.%1.1x, VppMax: %2.2d.%1.1x\n",\r
-               (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,\r
-               (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_intel_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
-{\r
-       int printed;\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-\r
-       printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n");\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x\n",\r
-               (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,\r
-               (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i\n", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       /*command_t *cfi_cmd = */\r
-       register_command(cmd_ctx, NULL, "cfi", NULL, COMMAND_ANY, "flash bank cfi <base> <size> <chip_width> <bus_width> <targetNum> [jedec_probe/x16_as_x8]");\r
-       /*\r
-       register_command(cmd_ctx, cfi_cmd, "part_id", cfi_handle_part_id_command, COMMAND_EXEC,\r
-                                        "print part id of cfi flash bank <num>");\r
-       */\r
-       return ERROR_OK;\r
-}\r
-\r
-/* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]\r
- */\r
-int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info;\r
-       int i;\r
-\r
-       if (argc < 6)\r
-       {\r
-               WARNING("incomplete flash_bank cfi configuration");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       if ((strtoul(args[4], NULL, 0) > CFI_MAX_CHIP_WIDTH)\r
-               || (strtoul(args[3], NULL, 0) > CFI_MAX_BUS_WIDTH))\r
-       {\r
-               ERROR("chip and bus width have to specified in bytes");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-\r
-       cfi_info = malloc(sizeof(cfi_flash_bank_t));\r
-       cfi_info->probed = 0;\r
-       bank->driver_priv = cfi_info;\r
-\r
-       cfi_info->write_algorithm = NULL;\r
-       cfi_info->erase_check_algorithm = NULL;\r
-\r
-       cfi_info->x16_as_x8 = 0;\r
-       cfi_info->jedec_probe = 0;\r
-       cfi_info->not_cfi = 0;\r
-\r
-       for (i = 6; i < argc; i++)\r
-       {\r
-               if (strcmp(args[i], "x16_as_x8") == 0)\r
-               {\r
-                       cfi_info->x16_as_x8 = 1;\r
-               }\r
-               else if (strcmp(args[i], "jedec_probe") == 0)\r
-               {\r
-                       cfi_info->jedec_probe = 1;\r
-               }\r
-       }\r
-\r
-       cfi_info->write_algorithm = NULL;\r
-\r
-       /* bank wasn't probed yet */\r
-       cfi_info->qry[0] = -1;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_intel_erase(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-       int i;\r
-\r
-       cfi_intel_clear_status_register(bank);\r
-\r
-       for (i = first; i <= last; i++)\r
-       {\r
-               cfi_command(bank, 0x20, command);\r
-               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-\r
-               cfi_command(bank, 0xd0, command);\r
-               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-\r
-               if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == 0x80)\r
-                       bank->sectors[i].is_erased = 1;\r
-               else\r
-               {\r
-                       cfi_command(bank, 0xff, command);\r
-                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-                       ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);\r
-                       return ERROR_FLASH_OPERATION_FAILED;\r
-               }\r
-       }\r
-\r
-       cfi_command(bank, 0xff, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_spansion_erase(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-       int i;\r
-\r
-       for (i = first; i <= last; i++)\r
-       {\r
-               cfi_command(bank, 0xaa, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-               cfi_command(bank, 0x55, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
-\r
-               cfi_command(bank, 0x80, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-               cfi_command(bank, 0xaa, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-               cfi_command(bank, 0x55, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
-\r
-               cfi_command(bank, 0x30, command);\r
-               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-\r
-               if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == ERROR_OK)\r
-                       bank->sectors[i].is_erased = 1;\r
-               else\r
-               {\r
-                       cfi_command(bank, 0xf0, command);\r
-                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-                       ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);\r
-                       return ERROR_FLASH_OPERATION_FAILED;\r
-               }\r
-       }\r
-\r
-       cfi_command(bank, 0xf0, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_erase(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       if (bank->target->state != TARGET_HALTED)\r
-       {\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if ((first < 0) || (last < first) || (last >= bank->num_sectors))\r
-       {\r
-               return ERROR_FLASH_SECTOR_INVALID;\r
-       }\r
-\r
-       if (cfi_info->qry[0] != 'Q')\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               case 1:\r
-               case 3:\r
-                       return cfi_intel_erase(bank, first, last);\r
-                       break;\r
-               case 2:\r
-                       return cfi_spansion_erase(bank, first, last);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-       int retry = 0;\r
-       int i;\r
-\r
-       /* if the device supports neither legacy lock/unlock (bit 3) nor\r
-        * instant individual block locking (bit 5).\r
-        */\r
-       if (!(pri_ext->feature_support & 0x28))\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-\r
-       cfi_intel_clear_status_register(bank);\r
-\r
-       for (i = first; i <= last; i++)\r
-       {\r
-               cfi_command(bank, 0x60, command);\r
-               DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));\r
-               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-               if (set)\r
-               {\r
-                       cfi_command(bank, 0x01, command);\r
-                       DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));\r
-                       target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-                       bank->sectors[i].is_protected = 1;\r
-               }\r
-               else\r
-               {\r
-                       cfi_command(bank, 0xd0, command);\r
-                       DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));\r
-                       target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-                       bank->sectors[i].is_protected = 0;\r
-               }\r
-\r
-               /* instant individual block locking doesn't require reading of the status register */\r
-               if (!(pri_ext->feature_support & 0x20))\r
-               {\r
-                       /* Clear lock bits operation may take up to 1.4s */\r
-                       cfi_intel_wait_status_busy(bank, 1400);\r
-               }\r
-               else\r
-               {\r
-                       u8 block_status;\r
-                       /* read block lock bit, to verify status */\r
-                       cfi_command(bank, 0x90, command);\r
-                       target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
-                       block_status = cfi_get_u8(bank, i, 0x2);\r
-\r
-                       if ((block_status & 0x1) != set)\r
-                       {\r
-                               ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status);\r
-                               cfi_command(bank, 0x70, command);\r
-                               target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
-                               cfi_intel_wait_status_busy(bank, 10);\r
-\r
-                               if (retry > 10)\r
-                                       return ERROR_FLASH_OPERATION_FAILED;\r
-                               else\r
-                               {\r
-                                       i--;\r
-                                       retry++;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* if the device doesn't support individual block lock bits set/clear,\r
-        * all blocks have been unlocked in parallel, so we set those that should be protected\r
-        */\r
-       if ((!set) && (!(pri_ext->feature_support & 0x20)))\r
-       {\r
-               for (i = 0; i < bank->num_sectors; i++)\r
-               {\r
-                       if (bank->sectors[i].is_protected == 1)\r
-                       {\r
-                               cfi_intel_clear_status_register(bank);\r
-\r
-                               cfi_command(bank, 0x60, command);\r
-                               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-\r
-                               cfi_command(bank, 0x01, command);\r
-                               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);\r
-\r
-                               cfi_intel_wait_status_busy(bank, 100);\r
-                       }\r
-               }\r
-       }\r
-\r
-       cfi_command(bank, 0xff, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_protect(struct flash_bank_s *bank, int set, int first, int last)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       if (bank->target->state != TARGET_HALTED)\r
-       {\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if ((first < 0) || (last < first) || (last >= bank->num_sectors))\r
-       {\r
-               return ERROR_FLASH_SECTOR_INVALID;\r
-       }\r
-\r
-       if (cfi_info->qry[0] != 'Q')\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               case 1:\r
-               case 3:\r
-                       cfi_intel_protect(bank, set, first, last);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* FIXME Replace this by a simple memcpy() - still unsure about sideeffects */\r
-static void cfi_add_byte(struct flash_bank_s *bank, u8 *word, u8 byte)\r
-{\r
-       //target_t *target = bank->target;\r
-\r
-       int i;\r
-\r
-       // NOTE:\r
-       // The data to flash must not be changed in endian! We write a bytestrem in\r
-       // target byte order already. Only the control and status byte lane of the flash\r
-       // WSM is interpreted by the CPU in different ways, when read a u16 or u32\r
-       // word (data seems to be in the upper or lower byte lane for u16 accesses).\r
-\r
-       //if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-       //{\r
-               /* shift bytes */\r
-               for (i = 0; i < bank->bus_width - 1; i++)\r
-                       word[i] = word[i + 1];\r
-               word[bank->bus_width - 1] = byte;\r
-       //}\r
-       //else\r
-       //{\r
-       //      /* shift bytes */\r
-       //      for (i = bank->bus_width - 1; i > 0; i--)\r
-       //              word[i] = word[i - 1];\r
-       //      word[0] = byte;\r
-       //}\r
-}\r
-\r
-/* Convert code image to target endian */\r
-/* FIXME create general block conversion fcts in target.c?) */ static\r
-void cfi_fix_code_endian(target_t *target, u32 *dest, const u32 *src, u32 count)\r
-{\r
-       u32 i;\r
-       for (i=0; i< count; i++)\r
-       {\r
-               target_buffer_set_u32(target, (u8*)dest, *src);\r
-               dest++;\r
-               src++;\r
-       }\r
-}\r
-\r
-int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       reg_param_t reg_params[7];\r
-       armv4_5_algorithm_t armv4_5_info;\r
-       working_area_t *source;\r
-       u32 buffer_size = 32768;\r
-       u8 write_command_buf[CFI_MAX_BUS_WIDTH];\r
-       u8 busy_pattern_buf[CFI_MAX_BUS_WIDTH];\r
-       u8 error_pattern_buf[CFI_MAX_BUS_WIDTH];\r
-       u32 write_command_val, busy_pattern_val, error_pattern_val;\r
-\r
-       /* algorithm register usage:\r
-        * r0: source address (in RAM)\r
-        * r1: target address (in Flash)\r
-        * r2: count\r
-        * r3: flash write command\r
-        * r4: status byte (returned to host)\r
-        * r5: busy test pattern\r
-        * r6: error test pattern\r
-        */\r
-\r
-       static const u32 word_32_code[] = {\r
-               0xe4904004,   /* loop:  ldr r4, [r0], #4 */\r
-               0xe5813000,   /*                str r3, [r1] */\r
-               0xe5814000,   /*                str r4, [r1] */\r
-               0xe5914000,   /* busy:  ldr r4, [r1] */\r
-               0xe0047005,   /*                and r7, r4, r5 */\r
-               0xe1570005,   /*                cmp r7, r5 */\r
-               0x1afffffb,   /*                bne busy */\r
-               0xe1140006,   /*                tst r4, r6 */\r
-               0x1a000003,   /*                bne done */\r
-               0xe2522001,   /*                subs r2, r2, #1 */\r
-               0x0a000001,   /*                beq done */\r
-               0xe2811004,   /*                add r1, r1 #4 */\r
-               0xeafffff2,   /*                b loop */\r
-               0xeafffffe    /* done:  b -2 */\r
-       };\r
-\r
-       static const u32 word_16_code[] = {\r
-               0xe0d040b2,   /* loop:  ldrh r4, [r0], #2 */\r
-               0xe1c130b0,   /*                strh r3, [r1] */\r
-               0xe1c140b0,   /*                strh r4, [r1] */\r
-               0xe1d140b0,   /* busy   ldrh r4, [r1] */\r
-               0xe0047005,   /*                and r7, r4, r5 */\r
-               0xe1570005,   /*                cmp r7, r5 */\r
-               0x1afffffb,   /*                bne busy */\r
-               0xe1140006,   /*                tst r4, r6 */\r
-               0x1a000003,   /*                bne done */\r
-               0xe2522001,   /*                subs r2, r2, #1 */\r
-               0x0a000001,   /*                beq done */\r
-               0xe2811002,   /*                add r1, r1 #2 */\r
-               0xeafffff2,   /*                b loop */\r
-               0xeafffffe    /* done:  b -2 */\r
-       };\r
-\r
-       static const u32 word_8_code[] = {\r
-               0xe4d04001,   /* loop:  ldrb r4, [r0], #1 */\r
-               0xe5c13000,   /*                strb r3, [r1] */\r
-               0xe5c14000,   /*                strb r4, [r1] */\r
-               0xe5d14000,   /* busy   ldrb r4, [r1] */\r
-               0xe0047005,   /*                and r7, r4, r5 */\r
-               0xe1570005,   /*                cmp r7, r5 */\r
-               0x1afffffb,   /*                bne busy */\r
-               0xe1140006,   /*                tst r4, r6 */\r
-               0x1a000003,   /*                bne done */\r
-               0xe2522001,   /*                subs r2, r2, #1 */\r
-               0x0a000001,   /*                beq done */\r
-               0xe2811001,   /*                add r1, r1 #1 */\r
-               0xeafffff2,   /*                b loop */\r
-               0xeafffffe    /* done:  b -2 */\r
-       };\r
-       u32 target_code[CFI_MAX_INTEL_CODESIZE];\r
-       const u32 *target_code_src;\r
-       int target_code_size;\r
-       int retval = ERROR_OK;\r
-\r
-\r
-       cfi_intel_clear_status_register(bank);\r
-\r
-       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
-       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
-       armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
-\r
-       /* If we are setting up the write_algorith, we need target_code_src */\r
-       /* if not we only need target_code_size.                                                                                                                */\r
-       /*                                                                                                                                                                                                                                                                      */\r
-       /* However, we don't want to create multiple code paths, so we                  */\r
-       /* do the unecessary evaluation of target_code_src, which the                   */\r
-       /* compiler will probably nicely optimize away if not needed                            */\r
-\r
-       /* prepare algorithm code for target endian */\r
-       switch (bank->bus_width)\r
-       {\r
-       case 1 :\r
-               target_code_src = word_8_code;\r
-               target_code_size = sizeof(word_8_code);\r
-               break;\r
-       case 2 :\r
-               target_code_src = word_16_code;\r
-               target_code_size = sizeof(word_16_code);\r
-               break;\r
-       case 4 :\r
-               target_code_src = word_32_code;\r
-               target_code_size = sizeof(word_32_code);\r
-               break;\r
-       default:\r
-               ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);\r
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-       }\r
-\r
-       /* flash write code */\r
-       if (!cfi_info->write_algorithm)\r
-       {\r
-               if ( target_code_size > sizeof(target_code) )\r
-               {\r
-                       WARNING("Internal error - target code buffer to small. Increase CFI_MAX_INTEL_CODESIZE and recompile.");\r
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-               }\r
-               cfi_fix_code_endian(target, target_code, target_code_src, target_code_size);\r
-\r
-               /* Get memory for block write handler */\r
-               retval = target_alloc_working_area(target, target_code_size, &cfi_info->write_algorithm);\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       WARNING("No working area available, can't do block memory writes");\r
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-               };\r
-\r
-               /* write algorithm code to working area */\r
-               retval = target_write_buffer(target, cfi_info->write_algorithm->address, target_code_size, (u8*)target_code);\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       ERROR("Unable to write block write code to target");\r
-                       goto cleanup;\r
-               }\r
-       }\r
-\r
-       /* Get a workspace buffer for the data to flash starting with 32k size.\r
-          Half size until buffer would be smaller 256 Bytem then fail back */\r
-       /* FIXME Why 256 bytes, why not 32 bytes (smallest flash write page */\r
-       while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)\r
-       {\r
-               buffer_size /= 2;\r
-               if (buffer_size <= 256)\r
-               {\r
-                       WARNING("no large enough working area available, can't do block memory writes");\r
-                       retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-                       goto cleanup;\r
-               }\r
-       };\r
-\r
-       /* setup algo registers */\r
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);\r
-       init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);\r
-\r
-       /* prepare command and status register patterns */\r
-       cfi_command(bank, 0x40, write_command_buf);\r
-       cfi_command(bank, 0x80, busy_pattern_buf);\r
-       cfi_command(bank, 0x7e, error_pattern_buf);\r
-\r
-       switch (bank->bus_width)\r
-       {\r
-       case 1 :\r
-               write_command_val = write_command_buf[0];\r
-               busy_pattern_val = busy_pattern_buf[0];\r
-               error_pattern_val = error_pattern_buf[0];\r
-               break;\r
-       case 2 :\r
-               write_command_val = target_buffer_get_u16(target, write_command_buf);\r
-               busy_pattern_val = target_buffer_get_u16(target, busy_pattern_buf);\r
-               error_pattern_val = target_buffer_get_u16(target, error_pattern_buf);\r
-               break;\r
-       case 4 :\r
-               write_command_val = target_buffer_get_u32(target, write_command_buf);\r
-               busy_pattern_val = target_buffer_get_u32(target, busy_pattern_buf);\r
-               error_pattern_val = target_buffer_get_u32(target, error_pattern_buf);\r
-               break;\r
-       default :\r
-               ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);\r
-               retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-               goto cleanup;\r
-       }\r
-\r
-       INFO("Using target buffer at 0x%08x and of size 0x%04x", source->address, buffer_size );\r
-\r
-       /* Programming main loop */\r
-       while (count > 0)\r
-       {\r
-               u32 thisrun_count = (count > buffer_size) ? buffer_size : count;\r
-               u32 wsm_error;\r
-\r
-               target_write_buffer(target, source->address, thisrun_count, buffer);\r
-\r
-               buf_set_u32(reg_params[0].value, 0, 32, source->address);\r
-               buf_set_u32(reg_params[1].value, 0, 32, address);\r
-               buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);\r
-\r
-               buf_set_u32(reg_params[3].value, 0, 32, write_command_val);\r
-               buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val);\r
-               buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val);\r
-\r
-               INFO("Write 0x%04x bytes to flash at 0x%08x", thisrun_count, address );\r
-\r
-               /* Execute algorithm, assume breakpoint for last instruction */\r
-               retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params,\r
-                       cfi_info->write_algorithm->address,\r
-                       cfi_info->write_algorithm->address + target_code_size - sizeof(u32),\r
-                       10000, /* 10s should be enough for max. 32k of data */\r
-                       &armv4_5_info);\r
-\r
-               /* On failure try a fall back to direct word writes */\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       cfi_intel_clear_status_register(bank);\r
-                       ERROR("Execution of flash algorythm failed. Can't fall back. Please report.");\r
-                       retval = ERROR_FLASH_OPERATION_FAILED;\r
-                       //retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-                       // FIXME To allow fall back or recovery, we must save the actual status\r
-                       //       somewhere, so that a higher level code can start recovery.\r
-                       goto cleanup;\r
-               }\r
-\r
-               /* Check return value from algo code */\r
-               wsm_error = buf_get_u32(reg_params[4].value, 0, 32) & error_pattern_val;\r
-               if (wsm_error)\r
-               {\r
-                       /* read status register (outputs debug inforation) */\r
-                       cfi_intel_wait_status_busy(bank, 100);\r
-                       cfi_intel_clear_status_register(bank);\r
-                       retval = ERROR_FLASH_OPERATION_FAILED;\r
-                       goto cleanup;\r
-               }\r
-\r
-               buffer += thisrun_count;\r
-               address += thisrun_count;\r
-               count -= thisrun_count;\r
-       }\r
-\r
-       /* free up resources */\r
-cleanup:\r
-       if (source)\r
-               target_free_working_area(target, source);\r
-\r
-       if (cfi_info->write_algorithm)\r
-       {\r
-               target_free_working_area(target, cfi_info->write_algorithm);\r
-               cfi_info->write_algorithm = NULL;\r
-       }\r
-\r
-       destroy_reg_param(&reg_params[0]);\r
-       destroy_reg_param(&reg_params[1]);\r
-       destroy_reg_param(&reg_params[2]);\r
-       destroy_reg_param(&reg_params[3]);\r
-       destroy_reg_param(&reg_params[4]);\r
-       destroy_reg_param(&reg_params[5]);\r
-       destroy_reg_param(&reg_params[6]);\r
-\r
-       return retval;\r
-}\r
-\r
-int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       target_t *target = bank->target;\r
-       reg_param_t reg_params[10];\r
-       armv4_5_algorithm_t armv4_5_info;\r
-       working_area_t *source;\r
-       u32 buffer_size = 32768;\r
-       u8 write_command[CFI_MAX_BUS_WIDTH];\r
-       u32 status;\r
-       int i;\r
-       int retval;\r
-       int exit_code = ERROR_OK;\r
-\r
-       /* input parameters - */\r
-       /*      R0 = source address */\r
-       /*      R1 = destination address */\r
-       /*      R2 = number of writes */\r
-       /*      R3 = flash write command */\r
-       /*      R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */\r
-       /* output parameters - */\r
-       /*      R5 = 0x80 ok 0x00 bad */\r
-       /* temp registers - */\r
-       /*      R6 = value read from flash to test status */\r
-       /*      R7 = holding register */\r
-       /* unlock registers - */\r
-       /*  R8 = unlock1_addr */\r
-       /*  R9 = unlock1_cmd */\r
-       /*  R10 = unlock2_addr */\r
-       /*  R11 = unlock2_cmd */\r
-\r
-       u32 word_32_code[] = {\r
-                                               /* 00008100 <sp_32_code>:               */\r
-               0xe4905004,             /* ldr  r5, [r0], #4                    */\r
-               0xe5889000,     /* str  r9, [r8]                                */\r
-               0xe58ab000,     /* str  r11, [r10]                              */\r
-               0xe5883000,     /* str  r3, [r8]                                */\r
-               0xe5815000,     /* str  r5, [r1]                                */\r
-               0xe1a00000,     /* nop                                                  */\r
-                                               /*                                                              */\r
-                                               /* 00008110 <sp_32_busy>:               */\r
-               0xe5916000,     /* ldr  r6, [r1]                                */\r
-               0xe0257006,     /* eor  r7, r5, r6                              */\r
-               0xe0147007,     /* ands r7, r4, r7                              */\r
-               0x0a000007,     /* beq  8140 <sp_32_cont> ; b if DQ7 == Data7 */\r
-               0xe0166124,     /* ands r6, r6, r4, lsr #2              */\r
-               0x0afffff9,     /* beq  8110 <sp_32_busy> ;     b if DQ5 low */\r
-               0xe5916000,     /* ldr  r6, [r1]                                */\r
-               0xe0257006,     /* eor  r7, r5, r6                              */\r
-               0xe0147007,     /* ands r7, r4, r7                              */\r
-               0x0a000001,     /* beq  8140 <sp_32_cont> ; b if DQ7 == Data7 */\r
-               0xe3a05000,     /* mov  r5, #0  ; 0x0 - return 0x00, error */\r
-               0x1a000004,     /* bne  8154 <sp_32_done>               */\r
-                                               /*                                                              */\r
-                               /* 00008140 <sp_32_cont>:                               */\r
-               0xe2522001,     /* subs r2, r2, #1      ; 0x1           */\r
-               0x03a05080,     /* moveq        r5, #128        ; 0x80  */\r
-               0x0a000001,     /* beq  8154 <sp_32_done>               */\r
-               0xe2811004,     /* add  r1, r1, #4      ; 0x4           */\r
-               0xeaffffe8,     /* b    8100 <sp_32_code>               */\r
-                                               /*                                                              */\r
-                                               /* 00008154 <sp_32_done>:               */\r
-               0xeafffffe              /* b    8154 <sp_32_done>               */\r
-               };\r
-\r
-               u32 word_16_code[] = {\r
-                               /* 00008158 <sp_16_code>:              */\r
-               0xe0d050b2,     /* ldrh r5, [r0], #2               */\r
-               0xe1c890b0,     /* strh r9, [r8]                                */\r
-               0xe1cab0b0,     /* strh r11, [r10]                              */\r
-               0xe1c830b0,     /* strh r3, [r8]                                */\r
-               0xe1c150b0,     /* strh r5, [r1]                       */\r
-               0xe1a00000,     /* nop                  (mov r0,r0)    */\r
-                               /*                                     */\r
-                               /* 00008168 <sp_16_busy>:              */\r
-               0xe1d160b0,     /* ldrh r6, [r1]                       */\r
-               0xe0257006,     /* eor  r7, r5, r6                     */\r
-               0xe0147007,     /* ands r7, r4, r7                     */\r
-               0x0a000007,     /* beq  8198 <sp_16_cont>              */\r
-               0xe0166124,     /* ands r6, r6, r4, lsr #2             */\r
-               0x0afffff9,     /* beq  8168 <sp_16_busy>              */\r
-               0xe1d160b0,     /* ldrh r6, [r1]                       */\r
-               0xe0257006,     /* eor  r7, r5, r6                     */\r
-               0xe0147007,     /* ands r7, r4, r7                     */\r
-               0x0a000001,     /* beq  8198 <sp_16_cont>              */\r
-               0xe3a05000,     /* mov  r5, #0  ; 0x0                  */\r
-               0x1a000004,     /* bne  81ac <sp_16_done>              */\r
-                               /*                                     */\r
-                               /* 00008198 <sp_16_cont>:              */\r
-               0xe2522001,     /* subs r2, r2, #1      ; 0x1          */\r
-               0x03a05080,     /* moveq        r5, #128        ; 0x80 */\r
-               0x0a000001,     /* beq  81ac <sp_16_done>              */\r
-               0xe2811002,     /* add  r1, r1, #2      ; 0x2          */\r
-               0xeaffffe8,     /* b    8158 <sp_16_code>              */\r
-                               /*                                     */\r
-                               /* 000081ac <sp_16_done>:              */\r
-               0xeafffffe      /* b    81ac <sp_16_done>              */\r
-               };\r
-\r
-               u32 word_8_code[] = {\r
-                               /* 000081b0 <sp_16_code_end>:          */\r
-               0xe4d05001,     /* ldrb r5, [r0], #1                   */\r
-               0xe5c89000,     /* strb r9, [r8]                                */\r
-               0xe5cab000,     /* strb r11, [r10]                              */\r
-               0xe5c83000,     /* strb r3, [r8]                                */\r
-               0xe5c15000,     /* strb r5, [r1]                       */\r
-               0xe1a00000,     /* nop                  (mov r0,r0)    */\r
-                               /*                                     */\r
-                               /* 000081c0 <sp_8_busy>:               */\r
-               0xe5d16000,     /* ldrb r6, [r1]                       */\r
-               0xe0257006,     /* eor  r7, r5, r6                     */\r
-               0xe0147007,     /* ands r7, r4, r7                     */\r
-               0x0a000007,     /* beq  81f0 <sp_8_cont>               */\r
-               0xe0166124,     /* ands r6, r6, r4, lsr #2             */\r
-               0x0afffff9,     /* beq  81c0 <sp_8_busy>               */\r
-               0xe5d16000,     /* ldrb r6, [r1]                       */\r
-               0xe0257006,     /* eor  r7, r5, r6                     */\r
-               0xe0147007,     /* ands r7, r4, r7                     */\r
-               0x0a000001,     /* beq  81f0 <sp_8_cont>               */\r
-               0xe3a05000,     /* mov  r5, #0  ; 0x0                  */\r
-               0x1a000004,     /* bne  8204 <sp_8_done>               */\r
-                               /*                                     */\r
-                               /* 000081f0 <sp_8_cont>:               */\r
-               0xe2522001,     /* subs r2, r2, #1      ; 0x1          */\r
-               0x03a05080,     /* moveq        r5, #128        ; 0x80 */\r
-               0x0a000001,     /* beq  8204 <sp_8_done>               */\r
-               0xe2811001,     /* add  r1, r1, #1      ; 0x1          */\r
-               0xeaffffe8,     /* b    81b0 <sp_16_code_end>          */\r
-                               /*                                     */\r
-                               /* 00008204 <sp_8_done>:               */\r
-               0xeafffffe      /* b    8204 <sp_8_done>               */\r
-       };\r
-\r
-       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
-       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
-       armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
-\r
-       /* flash write code */\r
-       if (!cfi_info->write_algorithm)\r
-       {\r
-               u8 *code_p;\r
-\r
-               /* convert bus-width dependent algorithm code to correct endiannes */\r
-               if (bank->bus_width == 1)\r
-               {\r
-                       code_p = malloc(24 * 4);\r
-\r
-                       for (i = 0; i < 24; i++)\r
-                               target_buffer_set_u32(target, code_p + (i*4), word_8_code[i]);\r
-               }\r
-               else if (bank->bus_width == 2)\r
-               {\r
-                       code_p = malloc(24 * 4);\r
-\r
-                       for (i = 0; i < 24; i++)\r
-                               target_buffer_set_u32(target, code_p + (i*4), word_16_code[i]);\r
-               }\r
-               else if (bank->bus_width == 4)\r
-               {\r
-                       code_p = malloc(24 * 4);\r
-\r
-                       for (i = 0; i < 24; i++)\r
-                               target_buffer_set_u32(target, code_p + (i*4), word_32_code[i]);\r
-               }\r
-               else\r
-               {\r
-                       return ERROR_FLASH_OPERATION_FAILED;\r
-               }\r
-\r
-               /* allocate working area */\r
-               retval=target_alloc_working_area(target, 24 * 4,\r
-                               &cfi_info->write_algorithm);\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       return retval;\r
-               }\r
-\r
-               /* write algorithm code to working area */\r
-               target_write_buffer(target, cfi_info->write_algorithm->address, 24 * 4, code_p);\r
-\r
-               free(code_p);\r
-       }\r
-\r
-       while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)\r
-       {\r
-               buffer_size /= 2;\r
-               if (buffer_size <= 256)\r
-               {\r
-                       /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */\r
-                       if (cfi_info->write_algorithm)\r
-                               target_free_working_area(target, cfi_info->write_algorithm);\r
-\r
-                       WARNING("not enough working area available, can't do block memory writes");\r
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-               }\r
-       };\r
-\r
-       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);\r
-       init_reg_param(&reg_params[6], "r8", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[7], "r9", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[8], "r10", 32, PARAM_OUT);\r
-       init_reg_param(&reg_params[9], "r11", 32, PARAM_OUT);\r
-\r
-       while (count > 0)\r
-       {\r
-               u32 thisrun_count = (count > buffer_size) ? buffer_size : count;\r
-\r
-               target_write_buffer(target, source->address, thisrun_count, buffer);\r
-\r
-               buf_set_u32(reg_params[0].value, 0, 32, source->address);\r
-               buf_set_u32(reg_params[1].value, 0, 32, address);\r
-               buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);\r
-               cfi_command(bank, 0xA0, write_command);\r
-               buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32));\r
-               cfi_command(bank, 0x80, write_command);\r
-               buf_set_u32(reg_params[4].value, 0, 32, buf_get_u32(write_command, 0, 32));\r
-               buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1));\r
-               buf_set_u32(reg_params[7].value, 0, 32, 0xaa);\r
-               buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2));\r
-               buf_set_u32(reg_params[9].value, 0, 32, 0x55);\r
-\r
-               retval = target->type->run_algorithm(target, 0, NULL, 10, reg_params,\r
-                                                    cfi_info->write_algorithm->address,\r
-                                                    cfi_info->write_algorithm->address + ((24 * 4) - 4),\r
-                                                    10000, &armv4_5_info);\r
-\r
-               status = buf_get_u32(reg_params[5].value, 0, 32);\r
-\r
-               if ((retval != ERROR_OK) || status != 0x80)\r
-               {\r
-                       DEBUG("status: 0x%x", status);\r
-                       exit_code = ERROR_FLASH_OPERATION_FAILED;\r
-                       break;\r
-               }\r
-\r
-               buffer += thisrun_count;\r
-               address += thisrun_count;\r
-               count -= thisrun_count;\r
-       }\r
-\r
-       target_free_working_area(target, source);\r
-\r
-       destroy_reg_param(&reg_params[0]);\r
-       destroy_reg_param(&reg_params[1]);\r
-       destroy_reg_param(&reg_params[2]);\r
-       destroy_reg_param(&reg_params[3]);\r
-       destroy_reg_param(&reg_params[4]);\r
-       destroy_reg_param(&reg_params[5]);\r
-       destroy_reg_param(&reg_params[6]);\r
-       destroy_reg_param(&reg_params[7]);\r
-       destroy_reg_param(&reg_params[8]);\r
-       destroy_reg_param(&reg_params[9]);\r
-\r
-       return exit_code;\r
-}\r
-\r
-int cfi_intel_write_word(struct flash_bank_s *bank, u8 *word, u32 address)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       cfi_intel_clear_status_register(bank);\r
-       cfi_command(bank, 0x40, command);\r
-       target->type->write_memory(target, address, bank->bus_width, 1, command);\r
-\r
-       target->type->write_memory(target, address, bank->bus_width, 1, word);\r
-\r
-       if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != 0x80)\r
-       {\r
-               cfi_command(bank, 0xff, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-               ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_intel_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       /* Calculate buffer size and boundary mask */\r
-       u32 buffersize = 1UL << cfi_info->max_buf_write_size;\r
-       u32 buffermask = buffersize-1;\r
-       u32 bufferwsize;\r
-\r
-       /* Check for valid range */\r
-       if (address & buffermask)\r
-       {\r
-               ERROR("Write address at base 0x%x, address %x not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-       switch(bank->chip_width)\r
-       {\r
-       case 4 : bufferwsize = buffersize / 4; break;\r
-       case 2 : bufferwsize = buffersize / 2; break;\r
-       case 1 : bufferwsize = buffersize; break;\r
-       default:\r
-               ERROR("Unsupported chip width %d", bank->chip_width);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       /* Check for valid size */\r
-       if (wordcount > bufferwsize)\r
-       {\r
-               ERROR("Number of data words %d exceeds available buffersize %d", wordcount, buffersize);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       /* Write to flash buffer */\r
-       cfi_intel_clear_status_register(bank);\r
-\r
-       /* Initiate buffer operation _*/\r
-       cfi_command(bank, 0xE8, command);\r
-       target->type->write_memory(target, address, bank->bus_width, 1, command);\r
-       if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->buf_write_timeout_max)) != 0x80)\r
-       {\r
-               cfi_command(bank, 0xff, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-               ERROR("couldn't start buffer write operation at base 0x%x, address %x", bank->base, address);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       /* Write buffer wordcount-1 and data words */\r
-       cfi_command(bank, bufferwsize-1, command);\r
-       target->type->write_memory(target, address, bank->bus_width, 1, command);\r
-\r
-       target->type->write_memory(target, address, bank->bus_width, bufferwsize, word);\r
-\r
-       /* Commit write operation */\r
-       cfi_command(bank, 0xd0, command);\r
-       target->type->write_memory(target, address, bank->bus_width, 1, command);\r
-       if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->buf_write_timeout_max)) != 0x80)\r
-       {\r
-               cfi_command(bank, 0xff, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-               ERROR("Buffer write at base 0x%x, address %x failed.", bank->base, address);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_spansion_write_word(struct flash_bank_s *bank, u8 *word, u32 address)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-\r
-       cfi_command(bank, 0xaa, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-       cfi_command(bank, 0x55, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
-\r
-       cfi_command(bank, 0xa0, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-       target->type->write_memory(target, address, bank->bus_width, 1, word);\r
-\r
-       if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != ERROR_OK)\r
-       {\r
-               cfi_command(bank, 0xf0, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-               ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_write_word(struct flash_bank_s *bank, u8 *word, u32 address)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               case 1:\r
-               case 3:\r
-                       return cfi_intel_write_word(bank, word, address);\r
-                       break;\r
-               case 2:\r
-                       return cfi_spansion_write_word(bank, word, address);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       return ERROR_FLASH_OPERATION_FAILED;\r
-}\r
-\r
-int cfi_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               case 1:\r
-               case 3:\r
-                       return cfi_intel_write_words(bank, word, wordcount, address);\r
-                       break;\r
-               case 2:\r
-                       //return cfi_spansion_write_words(bank, word, address);\r
-                       ERROR("cfi primary command set %i unimplemented - FIXME", cfi_info->pri_id);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       return ERROR_FLASH_OPERATION_FAILED;\r
-}\r
-\r
-int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       u32 address = bank->base + offset;      /* address of first byte to be programmed */\r
-       u32 write_p, copy_p;\r
-       int align;      /* number of unaligned bytes */\r
-       int blk_count; /* number of bus_width bytes for block copy */\r
-       u8 current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being programmed */\r
-       int i;\r
-       int retval;\r
-\r
-       if (offset + count > bank->size)\r
-               return ERROR_FLASH_DST_OUT_OF_BANK;\r
-\r
-       if (cfi_info->qry[0] != 'Q')\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-\r
-       /* start at the first byte of the first word (bus_width size) */\r
-       write_p = address & ~(bank->bus_width - 1);\r
-       if ((align = address - write_p) != 0)\r
-       {\r
-               INFO("Fixup %d unaligned head bytes", align );\r
-\r
-               for (i = 0; i < bank->bus_width; i++)\r
-                       current_word[i] = 0;\r
-               copy_p = write_p;\r
-\r
-               /* copy bytes before the first write address */\r
-               for (i = 0; i < align; ++i, ++copy_p)\r
-               {\r
-                       u8 byte;\r
-                       target->type->read_memory(target, copy_p, 1, 1, &byte);\r
-                       cfi_add_byte(bank, current_word, byte);\r
-               }\r
-\r
-               /* add bytes from the buffer */\r
-               for (; (i < bank->bus_width) && (count > 0); i++)\r
-               {\r
-                       cfi_add_byte(bank, current_word, *buffer++);\r
-                       count--;\r
-                       copy_p++;\r
-               }\r
-\r
-               /* if the buffer is already finished, copy bytes after the last write address */\r
-               for (; (count == 0) && (i < bank->bus_width); ++i, ++copy_p)\r
-               {\r
-                       u8 byte;\r
-                       target->type->read_memory(target, copy_p, 1, 1, &byte);\r
-                       cfi_add_byte(bank, current_word, byte);\r
-               }\r
-\r
-               retval = cfi_write_word(bank, current_word, write_p);\r
-               if (retval != ERROR_OK)\r
-                       return retval;\r
-               write_p = copy_p;\r
-       }\r
-\r
-       /* handle blocks of bus_size aligned bytes */\r
-       blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               /* try block writes (fails without working area) */\r
-               case 1:\r
-               case 3:\r
-                       retval = cfi_intel_write_block(bank, buffer, write_p, blk_count);\r
-                       break;\r
-               case 2:\r
-                       retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       retval = ERROR_FLASH_OPERATION_FAILED;\r
-                       break;\r
-       }\r
-       if (retval == ERROR_OK)\r
-       {\r
-               /* Increment pointers and decrease count on succesful block write */\r
-               buffer += blk_count;\r
-               write_p += blk_count;\r
-               count -= blk_count;\r
-       }\r
-       else\r
-       {\r
-               if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)\r
-               {\r
-                       u32 buffersize = 1UL << cfi_info->max_buf_write_size;\r
-                       u32 buffermask = buffersize-1;\r
-                       u32 bufferwsize;\r
-\r
-                       switch(bank->chip_width)\r
-                       {\r
-                       case 4 : bufferwsize = buffersize / 4; break;\r
-                       case 2 : bufferwsize = buffersize / 2; break;\r
-                       case 1 : bufferwsize = buffersize; break;\r
-                       default:\r
-                               ERROR("Unsupported chip width %d", bank->chip_width);\r
-                               return ERROR_FLASH_OPERATION_FAILED;\r
-                       }\r
-\r
-                       /* fall back to memory writes */\r
-                       while (count > bank->bus_width)\r
-                       {\r
-                               if ((write_p & 0xff) == 0)\r
-                               {\r
-                                       INFO("Programming at %08x, count %08x bytes remaining", write_p, count);\r
-                               }\r
-#if 0\r
-                               /* NB! this is broken for spansion! */\r
-                               if ((count > bufferwsize) && !(write_p & buffermask))\r
-                               {\r
-                                       retval = cfi_write_words(bank, buffer, bufferwsize, write_p);\r
-                                       if (retval != ERROR_OK)\r
-                                               return retval;\r
-\r
-                                       buffer += buffersize;\r
-                                       write_p += buffersize;\r
-                                       count -= buffersize;\r
-                               }\r
-                               else\r
-#endif\r
-                               {\r
-                                       for (i = 0; i < bank->bus_width; i++)\r
-                                               current_word[i] = 0;\r
-\r
-                                       for (i = 0; i < bank->bus_width; i++)\r
-                                       {\r
-                                               cfi_add_byte(bank, current_word, *buffer++);\r
-                                       }\r
-\r
-                                       retval = cfi_write_word(bank, current_word, write_p);\r
-                                       if (retval != ERROR_OK)\r
-                                               return retval;\r
-\r
-                                       write_p += bank->bus_width;\r
-                                       count -= bank->bus_width;\r
-                               }\r
-                       }\r
-               }\r
-               else\r
-                       return retval;\r
-       }\r
-\r
-       /* return to read array mode, so we can read from flash again for padding */\r
-       cfi_command(bank, 0xf0, current_word);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
-       cfi_command(bank, 0xff, current_word);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
-\r
-       /* handle unaligned tail bytes */\r
-       if (count > 0)\r
-       {\r
-               INFO("Fixup %d unaligned tail bytes", count );\r
-\r
-               copy_p = write_p;\r
-               for (i = 0; i < bank->bus_width; i++)\r
-                       current_word[i] = 0;\r
-\r
-               for (i = 0; (i < bank->bus_width) && (count > 0); ++i, ++copy_p)\r
-               {\r
-                       cfi_add_byte(bank, current_word, *buffer++);\r
-                       count--;\r
-               }\r
-               for (; i < bank->bus_width; ++i, ++copy_p)\r
-               {\r
-                       u8 byte;\r
-                       target->type->read_memory(target, copy_p, 1, 1, &byte);\r
-                       cfi_add_byte(bank, current_word, byte);\r
-               }\r
-               retval = cfi_write_word(bank, current_word, write_p);\r
-               if (retval != ERROR_OK)\r
-                       return retval;\r
-       }\r
-\r
-       /* return to read array mode */\r
-       cfi_command(bank, 0xf0, current_word);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
-       cfi_command(bank, 0xff, current_word);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *bank, void *param)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-\r
-       pri_ext->_reversed_geometry = 1;\r
-}\r
-\r
-void cfi_fixup_0002_erase_regions(flash_bank_t *bank, void *param)\r
-{\r
-       int i;\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-\r
-       if ((pri_ext->_reversed_geometry) || (pri_ext->TopBottom == 3))\r
-       {\r
-               DEBUG("swapping reversed erase region information on cmdset 0002 device");\r
-\r
-               for (i = 0; i < cfi_info->num_erase_regions / 2; i++)\r
-               {\r
-                       int j = (cfi_info->num_erase_regions - 1) - i;\r
-                       u32 swap;\r
-\r
-                       swap = cfi_info->erase_region_info[i];\r
-                       cfi_info->erase_region_info[i] = cfi_info->erase_region_info[j];\r
-                       cfi_info->erase_region_info[j] = swap;\r
-               }\r
-       }\r
-}\r
-\r
-void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       cfi_unlock_addresses_t *unlock_addresses = param;\r
-\r
-       pri_ext->_unlock1 = unlock_addresses->unlock1;\r
-       pri_ext->_unlock2 = unlock_addresses->unlock2;\r
-}\r
-\r
-int cfi_probe(struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-       int num_sectors = 0;\r
-       int i;\r
-       int sector = 0;\r
-       u32 offset = 0;\r
-       u32 unlock1 = 0x555;\r
-       u32 unlock2 = 0x2aa;\r
-\r
-       cfi_info->probed = 0;\r
-\r
-       /* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses,\r
-        * while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa\r
-        */\r
-       if (cfi_info->jedec_probe)\r
-       {\r
-               unlock1 = 0x5555;\r
-               unlock2 = 0x2aaa;\r
-       }\r
-\r
-       /* switch to read identifier codes mode ("AUTOSELECT") */\r
-       cfi_command(bank, 0xaa, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);\r
-       cfi_command(bank, 0x55, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, unlock2), bank->bus_width, 1, command);\r
-       cfi_command(bank, 0x90, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);\r
-\r
-       if (bank->chip_width == 1)\r
-       {\r
-               u8 manufacturer, device_id;\r
-               target_read_u8(target, bank->base + 0x0, &manufacturer);\r
-               target_read_u8(target, bank->base + 0x1, &device_id);\r
-               cfi_info->manufacturer = manufacturer;\r
-               cfi_info->device_id = device_id;\r
-       }\r
-       else if (bank->chip_width == 2)\r
-       {\r
-               target_read_u16(target, bank->base + 0x0, &cfi_info->manufacturer);\r
-               target_read_u16(target, bank->base + 0x2, &cfi_info->device_id);\r
-       }\r
-\r
-       /* switch back to read array mode */\r
-       cfi_command(bank, 0xf0, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, command);\r
-       cfi_command(bank, 0xff, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, command);\r
-\r
-       cfi_fixup(bank, cfi_jedec_fixups);\r
-\r
-       /* query only if this is a CFI compatible flash,\r
-        * otherwise the relevant info has already been filled in\r
-        */\r
-       if (cfi_info->not_cfi == 0)\r
-       {\r
-               /* enter CFI query mode\r
-                * according to JEDEC Standard No. 68.01,\r
-                * a single bus sequence with address = 0x55, data = 0x98 should put\r
-                * the device into CFI query mode.\r
-                *\r
-                * SST flashes clearly violate this, and we will consider them incompatbile for now\r
-                */\r
-               cfi_command(bank, 0x98, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
-\r
-               cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);\r
-               cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);\r
-               cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);\r
-\r
-               DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);\r
-\r
-               if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))\r
-               {\r
-                       cfi_command(bank, 0xf0, command);\r
-                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-                       cfi_command(bank, 0xff, command);\r
-                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-                       return ERROR_FLASH_BANK_INVALID;\r
-               }\r
-\r
-               cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);\r
-               cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);\r
-               cfi_info->alt_id = cfi_query_u16(bank, 0, 0x17);\r
-               cfi_info->alt_addr = cfi_query_u16(bank, 0, 0x19);\r
-\r
-               DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);\r
-\r
-               cfi_info->vcc_min = cfi_query_u8(bank, 0, 0x1b);\r
-               cfi_info->vcc_max = cfi_query_u8(bank, 0, 0x1c);\r
-               cfi_info->vpp_min = cfi_query_u8(bank, 0, 0x1d);\r
-               cfi_info->vpp_max = cfi_query_u8(bank, 0, 0x1e);\r
-               cfi_info->word_write_timeout_typ = cfi_query_u8(bank, 0, 0x1f);\r
-               cfi_info->buf_write_timeout_typ = cfi_query_u8(bank, 0, 0x20);\r
-               cfi_info->block_erase_timeout_typ = cfi_query_u8(bank, 0, 0x21);\r
-               cfi_info->chip_erase_timeout_typ = cfi_query_u8(bank, 0, 0x22);\r
-               cfi_info->word_write_timeout_max = cfi_query_u8(bank, 0, 0x23);\r
-               cfi_info->buf_write_timeout_max = cfi_query_u8(bank, 0, 0x24);\r
-               cfi_info->block_erase_timeout_max = cfi_query_u8(bank, 0, 0x25);\r
-               cfi_info->chip_erase_timeout_max = cfi_query_u8(bank, 0, 0x26);\r
-\r
-               DEBUG("Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x",\r
-                       (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,\r
-                       (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,\r
-                       (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,\r
-                       (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);\r
-               DEBUG("typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,\r
-                       1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);\r
-               DEBUG("max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),\r
-                       (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),\r
-                       (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),\r
-                       (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));\r
-\r
-               cfi_info->dev_size = cfi_query_u8(bank, 0, 0x27);\r
-               cfi_info->interface_desc = cfi_query_u16(bank, 0, 0x28);\r
-               cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);\r
-               cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);\r
-\r
-               DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));\r
-\r
-               if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)\r
-               {\r
-                       WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);\r
-               }\r
-\r
-               if (cfi_info->num_erase_regions)\r
-               {\r
-                       cfi_info->erase_region_info = malloc(4 * cfi_info->num_erase_regions);\r
-                       for (i = 0; i < cfi_info->num_erase_regions; i++)\r
-                       {\r
-                               cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));\r
-                               DEBUG("erase region[%i]: %i blocks of size 0x%x", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       cfi_info->erase_region_info = NULL;\r
-               }\r
-\r
-               /* We need to read the primary algorithm extended query table before calculating\r
-                * the sector layout to be able to apply fixups\r
-                */\r
-               switch(cfi_info->pri_id)\r
-               {\r
-                       /* Intel command set (standard and extended) */\r
-                       case 0x0001:\r
-                       case 0x0003:\r
-                               cfi_read_intel_pri_ext(bank);\r
-                               break;\r
-                       /* AMD/Spansion, Atmel, ... command set */\r
-                       case 0x0002:\r
-                               cfi_read_0002_pri_ext(bank);\r
-                               break;\r
-                       default:\r
-                               ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                               break;\r
-               }\r
-\r
-               /* return to read array mode\r
-                * we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command\r
-                */\r
-               cfi_command(bank, 0xf0, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-               cfi_command(bank, 0xff, command);\r
-               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-       }\r
-\r
-       /* apply fixups depending on the primary command set */\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               /* Intel command set (standard and extended) */\r
-               case 0x0001:\r
-               case 0x0003:\r
-                       cfi_fixup(bank, cfi_0001_fixups);\r
-                       break;\r
-               /* AMD/Spansion, Atmel, ... command set */\r
-               case 0x0002:\r
-                       cfi_fixup(bank, cfi_0002_fixups);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       if (cfi_info->num_erase_regions == 0)\r
-       {\r
-               /* a device might have only one erase block, spanning the whole device */\r
-               bank->num_sectors = 1;\r
-               bank->sectors = malloc(sizeof(flash_sector_t));\r
-\r
-               bank->sectors[sector].offset = 0x0;\r
-               bank->sectors[sector].size = bank->size;\r
-               bank->sectors[sector].is_erased = -1;\r
-               bank->sectors[sector].is_protected = -1;\r
-       }\r
-       else\r
-       {\r
-               for (i = 0; i < cfi_info->num_erase_regions; i++)\r
-               {\r
-                       num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;\r
-               }\r
-\r
-               bank->num_sectors = num_sectors;\r
-               bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);\r
-\r
-               for (i = 0; i < cfi_info->num_erase_regions; i++)\r
-               {\r
-                       int j;\r
-                       for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++)\r
-                       {\r
-                               bank->sectors[sector].offset = offset;\r
-                               bank->sectors[sector].size = ((cfi_info->erase_region_info[i] >> 16) * 256) * bank->bus_width / bank->chip_width;\r
-                               offset += bank->sectors[sector].size;\r
-                               bank->sectors[sector].is_erased = -1;\r
-                               bank->sectors[sector].is_protected = -1;\r
-                               sector++;\r
-                       }\r
-               }\r
-       }\r
-       \r
-       cfi_info->probed = 1;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_auto_probe(struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       if (cfi_info->probed)\r
-               return ERROR_OK;\r
-       return cfi_probe(bank);\r
-}\r
-\r
-int cfi_erase_check(struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       target_t *target = bank->target;\r
-       int i;\r
-       int retval;\r
-\r
-       if (!cfi_info->erase_check_algorithm)\r
-       {\r
-               u32 erase_check_code[] =\r
-               {\r
-                       0xe4d03001,     /* ldrb r3, [r0], #1    */\r
-                       0xe0022003, /* and r2, r2, r3           */\r
-                       0xe2511001, /* subs r1, r1, #1          */\r
-                       0x1afffffb,     /* b -4                                 */\r
-                       0xeafffffe      /* b 0                                  */\r
-               };\r
-\r
-               /* make sure we have a working area */\r
-               if (target_alloc_working_area(target, 20, &cfi_info->erase_check_algorithm) != ERROR_OK)\r
-               {\r
-                       WARNING("no working area available, falling back to slow memory reads");\r
-               }\r
-               else\r
-               {\r
-                       u8 erase_check_code_buf[5 * 4];\r
-\r
-                       for (i = 0; i < 5; i++)\r
-                               target_buffer_set_u32(target, erase_check_code_buf + (i*4), erase_check_code[i]);\r
-\r
-                       /* write algorithm code to working area */\r
-                       target->type->write_memory(target, cfi_info->erase_check_algorithm->address, 4, 5, erase_check_code_buf);\r
-               }\r
-       }\r
-\r
-       if (!cfi_info->erase_check_algorithm)\r
-       {\r
-               u32 *buffer = malloc(4096);\r
-\r
-               for (i = 0; i < bank->num_sectors; i++)\r
-               {\r
-                       u32 address = bank->base + bank->sectors[i].offset;\r
-                       u32 size = bank->sectors[i].size;\r
-                       u32 check = 0xffffffffU;\r
-                       int erased = 1;\r
-\r
-                       while (size > 0)\r
-                       {\r
-                               u32 thisrun_size = (size > 4096) ? 4096 : size;\r
-                               int j;\r
-\r
-                               target->type->read_memory(target, address, 4, thisrun_size / 4, (u8*)buffer);\r
-\r
-                               for (j = 0; j < thisrun_size / 4; j++)\r
-                                       check &= buffer[j];\r
-\r
-                               if (check != 0xffffffff)\r
-                               {\r
-                                       erased = 0;\r
-                                       break;\r
-                               }\r
-\r
-                               size -= thisrun_size;\r
-                               address += thisrun_size;\r
-                       }\r
-\r
-                       bank->sectors[i].is_erased = erased;\r
-               }\r
-\r
-               free(buffer);\r
-       }\r
-       else\r
-       {\r
-               for (i = 0; i < bank->num_sectors; i++)\r
-               {\r
-                       u32 address = bank->base + bank->sectors[i].offset;\r
-                       u32 size = bank->sectors[i].size;\r
-\r
-                       reg_param_t reg_params[3];\r
-                       armv4_5_algorithm_t armv4_5_info;\r
-\r
-                       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;\r
-                       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;\r
-                       armv4_5_info.core_state = ARMV4_5_STATE_ARM;\r
-\r
-                       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);\r
-                       buf_set_u32(reg_params[0].value, 0, 32, address);\r
-\r
-                       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);\r
-                       buf_set_u32(reg_params[1].value, 0, 32, size);\r
-\r
-                       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);\r
-                       buf_set_u32(reg_params[2].value, 0, 32, 0xff);\r
-\r
-                       if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, cfi_info->erase_check_algorithm->address, cfi_info->erase_check_algorithm->address + 0x10, 10000, &armv4_5_info)) != ERROR_OK)\r
-                               return ERROR_FLASH_OPERATION_FAILED;\r
-\r
-                       if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)\r
-                               bank->sectors[i].is_erased = 1;\r
-                       else\r
-                               bank->sectors[i].is_erased = 0;\r
-\r
-                       destroy_reg_param(&reg_params[0]);\r
-                       destroy_reg_param(&reg_params[1]);\r
-                       destroy_reg_param(&reg_params[2]);\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_intel_protect_check(struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       target_t *target = bank->target;\r
-       u8 command[CFI_MAX_BUS_WIDTH];\r
-       int i;\r
-\r
-       /* check if block lock bits are supported on this device */\r
-       if (!(pri_ext->blk_status_reg_mask & 0x1))\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-\r
-       cfi_command(bank, 0x90, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);\r
-\r
-       for (i = 0; i < bank->num_sectors; i++)\r
-       {\r
-               u8 block_status = cfi_get_u8(bank, i, 0x2);\r
-\r
-               if (block_status & 1)\r
-                       bank->sectors[i].is_protected = 1;\r
-               else\r
-                       bank->sectors[i].is_protected = 0;\r
-       }\r
-\r
-       cfi_command(bank, 0xff, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_spansion_protect_check(struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;\r
-       target_t *target = bank->target;\r
-       u8 command[8];\r
-       int i;\r
-\r
-       cfi_command(bank, 0xaa, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-       cfi_command(bank, 0x55, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);\r
-\r
-       cfi_command(bank, 0x90, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);\r
-\r
-       for (i = 0; i < bank->num_sectors; i++)\r
-       {\r
-               u8 block_status = cfi_get_u8(bank, i, 0x2);\r
-\r
-               if (block_status & 1)\r
-                       bank->sectors[i].is_protected = 1;\r
-               else\r
-                       bank->sectors[i].is_protected = 0;\r
-       }\r
-\r
-       cfi_command(bank, 0xf0, command);\r
-       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_protect_check(struct flash_bank_s *bank)\r
-{\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       if (cfi_info->qry[0] != 'Q')\r
-               return ERROR_FLASH_BANK_NOT_PROBED;\r
-\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               case 1:\r
-               case 3:\r
-                       return cfi_intel_protect_check(bank);\r
-                       break;\r
-               case 2:\r
-                       return cfi_spansion_protect_check(bank);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
-{\r
-       int printed;\r
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;\r
-\r
-       if (cfi_info->qry[0] == (char)-1)\r
-       {\r
-               printed = snprintf(buf, buf_size, "\ncfi flash bank not probed yet\n");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       printed = snprintf(buf, buf_size, "\ncfi information:\n");\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "\nmfr: 0x%4.4x, id:0x%4.4x\n",\r
-               cfi_info->manufacturer, cfi_info->device_id);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x\n", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x\n", (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,\r
-       (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,\r
-       (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,\r
-       (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u\n", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,\r
-                 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u\n", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),\r
-                 (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),\r
-                 (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),\r
-                 (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       printed = snprintf(buf, buf_size, "size: 0x%x, interface desc: %i, max buffer write size: %x\n", 1 << cfi_info->dev_size, cfi_info->interface_desc, cfi_info->max_buf_write_size);\r
-       buf += printed;\r
-       buf_size -= printed;\r
-\r
-       switch(cfi_info->pri_id)\r
-       {\r
-               case 1:\r
-               case 3:\r
-                       cfi_intel_info(bank, buf, buf_size);\r
-                       break;\r
-               case 2:\r
-                       cfi_spansion_info(bank, buf, buf_size);\r
-                       break;\r
-               default:\r
-                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005, 2007 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "cfi.h"
+
+#include "flash.h"
+#include "target.h"
+#include "log.h"
+#include "armv4_5.h"
+#include "algorithm.h"
+#include "binarybuffer.h"
+#include "types.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int cfi_register_commands(struct command_context_s *cmd_ctx);
+int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
+int cfi_erase(struct flash_bank_s *bank, int first, int last);
+int cfi_protect(struct flash_bank_s *bank, int set, int first, int last);
+int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
+int cfi_probe(struct flash_bank_s *bank);
+int cfi_auto_probe(struct flash_bank_s *bank);
+int cfi_erase_check(struct flash_bank_s *bank);
+int cfi_protect_check(struct flash_bank_s *bank);
+int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size);
+
+int cfi_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+#define CFI_MAX_BUS_WIDTH      4
+#define CFI_MAX_CHIP_WIDTH     4
+
+/* defines internal maximum size for code fragment in cfi_intel_write_block() */
+#define CFI_MAX_INTEL_CODESIZE 256
+
+flash_driver_t cfi_flash =
+{
+       .name = "cfi",
+       .register_commands = cfi_register_commands,
+       .flash_bank_command = cfi_flash_bank_command,
+       .erase = cfi_erase,
+       .protect = cfi_protect,
+       .write = cfi_write,
+       .probe = cfi_probe,
+       .auto_probe = cfi_auto_probe,
+       .erase_check = cfi_erase_check,
+       .protect_check = cfi_protect_check,
+       .info = cfi_info
+};
+
+cfi_unlock_addresses_t cfi_unlock_addresses[] =
+{
+       [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },
+       [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },
+};
+
+/* CFI fixups foward declarations */
+void cfi_fixup_non_cfi(flash_bank_t *flash, void *param);
+void cfi_fixup_0002_erase_regions(flash_bank_t *flash, void *param);
+void cfi_fixup_0002_unlock_addresses(flash_bank_t *flash, void *param);
+void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);
+
+/* fixup after identifying JEDEC manufactuer and ID */
+cfi_fixup_t cfi_jedec_fixups[] = {
+       {CFI_MFR_SST, 0x00D4, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_SST, 0x00D5, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_SST, 0x00D6, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_SST, 0x00D7, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_SST, 0x2780, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_ST, 0x00D5, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_ST, 0x00D6, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_AMD, 0x2223, cfi_fixup_non_cfi, NULL},
+       {CFI_MFR_AMD, 0x22ab, cfi_fixup_non_cfi, NULL},
+       {0, 0, NULL, NULL}
+};
+
+/* fixup after reading cmdset 0002 primary query table */
+cfi_fixup_t cfi_0002_fixups[] = {
+       {CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
+       {CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
+       {CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
+       {CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
+       {CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
+       {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_atmel_reversed_erase_regions, NULL},
+       {CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL},
+       {0, 0, NULL, NULL}
+};
+
+/* fixup after reading cmdset 0001 primary query table */
+cfi_fixup_t cfi_0001_fixups[] = {
+       {0, 0, NULL, NULL}
+};
+
+void cfi_fixup(flash_bank_t *bank, cfi_fixup_t *fixups)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_fixup_t *f;
+
+       for (f = fixups; f->fixup; f++)
+       {
+               if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi_info->manufacturer)) &&
+                       ((f->id  == CFI_ID_ANY)  || (f->id  == cfi_info->device_id)))
+               {
+                       f->fixup(bank, f->param);
+               }
+       }
+}
+
+inline u32 flash_address(flash_bank_t *bank, int sector, u32 offset)
+{
+       /* while the sector list isn't built, only accesses to sector 0 work */
+       if (sector == 0)
+               return bank->base + offset * bank->bus_width;
+       else
+       {
+               if (!bank->sectors)
+               {
+                       ERROR("BUG: sector list not yet built");
+                       exit(-1);
+               }
+               return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;
+       }
+
+}
+
+void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
+{
+       int i;
+
+       /* clear whole buffer, to ensure bits that exceed the bus_width
+        * are set to zero
+        */
+       for (i = 0; i < CFI_MAX_BUS_WIDTH; i++)
+               cmd_buf[i] = 0;
+
+       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
+       {
+               for (i = bank->bus_width; i > 0; i--)
+               {
+                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
+               }
+       }
+       else
+       {
+               for (i = 1; i <= bank->bus_width; i++)
+               {
+                       *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
+               }
+       }
+}
+
+/* read unsigned 8-bit value from the bank
+ * flash banks are expected to be made of similar chips
+ * the query result should be the same for all
+ */
+u8 cfi_query_u8(flash_bank_t *bank, int sector, u32 offset)
+{
+       target_t *target = bank->target;
+       u8 data[CFI_MAX_BUS_WIDTH];
+
+       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);
+
+       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
+               return data[0];
+       else
+               return data[bank->bus_width - 1];
+}
+
+/* read unsigned 8-bit value from the bank
+ * in case of a bank made of multiple chips,
+ * the individual values are ORed
+ */
+u8 cfi_get_u8(flash_bank_t *bank, int sector, u32 offset)
+{
+       target_t *target = bank->target;
+       u8 data[CFI_MAX_BUS_WIDTH];
+       int i;
+
+       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);
+
+       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
+       {
+               for (i = 0; i < bank->bus_width / bank->chip_width; i++)
+                       data[0] |= data[i];
+
+               return data[0];
+       }
+       else
+       {
+               u8 value = 0;
+               for (i = 0; i < bank->bus_width / bank->chip_width; i++)
+                       value |= data[bank->bus_width - 1 - i];
+
+               return value;
+       }
+}
+
+u16 cfi_query_u16(flash_bank_t *bank, int sector, u32 offset)
+{
+       target_t *target = bank->target;
+       u8 data[CFI_MAX_BUS_WIDTH * 2];
+
+       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data);
+
+       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
+               return data[0] | data[bank->bus_width] << 8;
+       else
+               return data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;
+}
+
+u32 cfi_query_u32(flash_bank_t *bank, int sector, u32 offset)
+{
+       target_t *target = bank->target;
+       u8 data[CFI_MAX_BUS_WIDTH * 4];
+
+       target->type->read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data);
+
+       if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
+               return data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;
+       else
+               return data[bank->bus_width - 1] | data[(2* bank->bus_width) - 1] << 8 |
+                               data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;
+}
+
+void cfi_intel_clear_status_register(flash_bank_t *bank)
+{
+       target_t *target = bank->target;
+       u8 command[8];
+
+       if (target->state != TARGET_HALTED)
+       {
+               ERROR("BUG: attempted to clear status register while target wasn't halted");
+               exit(-1);
+       }
+
+       cfi_command(bank, 0x50, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+}
+
+u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)
+{
+       u8 status;
+
+       while ((!((status = cfi_get_u8(bank, 0, 0x0)) & 0x80)) && (timeout-- > 0))
+       {
+               DEBUG("status: 0x%x", status);
+               usleep(1000);
+       }
+
+       /* mask out bit 0 (reserved) */
+       status = status & 0xfe;
+
+       DEBUG("status: 0x%x", status);
+
+       if ((status & 0x80) != 0x80)
+       {
+               ERROR("timeout while waiting for WSM to become ready");
+       }
+       else if (status != 0x80)
+       {
+               ERROR("status register: 0x%x", status);
+               if (status & 0x2)
+                       ERROR("Block Lock-Bit Detected, Operation Abort");
+               if (status & 0x4)
+                       ERROR("Program suspended");
+               if (status & 0x8)
+                       ERROR("Low Programming Voltage Detected, Operation Aborted");
+               if (status & 0x10)
+                       ERROR("Program Error / Error in Setting Lock-Bit");
+               if (status & 0x20)
+                       ERROR("Error in Block Erasure or Clear Lock-Bits");
+               if (status & 0x40)
+                       ERROR("Block Erase Suspended");
+
+               cfi_intel_clear_status_register(bank);
+       }
+
+       return status;
+}
+
+int cfi_spansion_wait_status_busy(flash_bank_t *bank, int timeout)
+{
+       u8 status, oldstatus;
+
+       oldstatus = cfi_get_u8(bank, 0, 0x0);
+
+       do {
+               status = cfi_get_u8(bank, 0, 0x0);
+               if ((status ^ oldstatus) & 0x40) {
+                       if (status & 0x20) {
+                               oldstatus = cfi_get_u8(bank, 0, 0x0);
+                               status = cfi_get_u8(bank, 0, 0x0);
+                               if ((status ^ oldstatus) & 0x40) {
+                                       ERROR("dq5 timeout, status: 0x%x", status);
+                                       return(ERROR_FLASH_OPERATION_FAILED);
+                               } else {
+                                       DEBUG("status: 0x%x", status);
+                                       return(ERROR_OK);
+                               }
+                       }
+               } else {
+                       DEBUG("status: 0x%x", status);
+                       return(ERROR_OK);
+               }
+
+               oldstatus = status;
+               usleep(1000);
+       } while (timeout-- > 0);
+
+       ERROR("timeout, status: 0x%x", status);
+
+       return(ERROR_FLASH_BUSY);
+}
+
+int cfi_read_intel_pri_ext(flash_bank_t *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_intel_pri_ext_t *pri_ext = malloc(sizeof(cfi_intel_pri_ext_t));
+       target_t *target = bank->target;
+       u8 command[8];
+
+       cfi_info->pri_ext = pri_ext;
+
+       pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
+       pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
+       pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);
+
+       if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
+       {
+               cfi_command(bank, 0xf0, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+               cfi_command(bank, 0xff, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
+       pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);
+
+       DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
+
+       pri_ext->feature_support = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5);
+       pri_ext->suspend_cmd_support = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);
+       pri_ext->blk_status_reg_mask = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa);
+
+       DEBUG("feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);
+
+       pri_ext->vcc_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc);
+       pri_ext->vpp_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd);
+
+       DEBUG("Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x",
+                 (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
+                 (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
+
+       pri_ext->num_protection_fields = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe);
+       if (pri_ext->num_protection_fields != 1)
+       {
+               WARNING("expected one protection register field, but found %i", pri_ext->num_protection_fields);
+       }
+
+       pri_ext->prot_reg_addr = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf);
+       pri_ext->fact_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11);
+       pri_ext->user_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12);
+
+       DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
+
+       return ERROR_OK;
+}
+
+int cfi_read_spansion_pri_ext(flash_bank_t *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));
+       target_t *target = bank->target;
+       u8 command[8];
+
+       cfi_info->pri_ext = pri_ext;
+
+       pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
+       pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
+       pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);
+
+       if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
+       {
+               cfi_command(bank, 0xf0, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
+       pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);
+
+       DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
+
+       pri_ext->SiliconRevision = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);
+       pri_ext->EraseSuspend    = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);
+       pri_ext->BlkProt         = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);
+       pri_ext->TmpBlkUnprotect = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);
+       pri_ext->BlkProtUnprot   = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);
+       pri_ext->SimultaneousOps = cfi_query_u8(bank, 0, cfi_info->pri_addr + 10);
+       pri_ext->BurstMode       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 11);
+       pri_ext->PageMode        = cfi_query_u8(bank, 0, cfi_info->pri_addr + 12);
+       pri_ext->VppMin          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 13);
+       pri_ext->VppMax          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 14);
+       pri_ext->TopBottom       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 15);
+
+       DEBUG("Silicon Revision: 0x%x, Erase Suspend: 0x%x, Block protect: 0x%x", pri_ext->SiliconRevision,
+             pri_ext->EraseSuspend, pri_ext->BlkProt);
+
+       DEBUG("Temporary Unprotect: 0x%x, Block Protect Scheme: 0x%x, Simultaneous Ops: 0x%x", pri_ext->TmpBlkUnprotect,
+             pri_ext->BlkProtUnprot, pri_ext->SimultaneousOps);
+
+       DEBUG("Burst Mode: 0x%x, Page Mode: 0x%x, ", pri_ext->BurstMode, pri_ext->PageMode);
+
+
+       DEBUG("Vpp min: %2.2d.%1.1d, Vpp max: %2.2d.%1.1x",
+                 (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,
+                 (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);
+
+       DEBUG("WP# protection 0x%x", pri_ext->TopBottom);
+
+       /* default values for implementation specific workarounds */
+       pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
+       pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
+       pri_ext->_reversed_geometry = 0;
+
+       return ERROR_OK;
+}
+
+int cfi_read_atmel_pri_ext(flash_bank_t *bank)
+{
+       cfi_atmel_pri_ext_t atmel_pri_ext;
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = malloc(sizeof(cfi_spansion_pri_ext_t));
+       target_t *target = bank->target;
+       u8 command[8];
+
+       /* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion,
+        * but a different primary extended query table.
+        * We read the atmel table, and prepare a valid AMD/Spansion query table.
+        */
+
+       memset(pri_ext, 0, sizeof(cfi_spansion_pri_ext_t));
+
+       cfi_info->pri_ext = pri_ext;
+
+       atmel_pri_ext.pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
+       atmel_pri_ext.pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
+       atmel_pri_ext.pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);
+
+       if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R') || (atmel_pri_ext.pri[2] != 'I'))
+       {
+               cfi_command(bank, 0xf0, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       pri_ext->pri[0] = atmel_pri_ext.pri[0];
+       pri_ext->pri[1] = atmel_pri_ext.pri[1];
+       pri_ext->pri[2] = atmel_pri_ext.pri[2];
+
+       atmel_pri_ext.major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
+       atmel_pri_ext.minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);
+
+       DEBUG("pri: '%c%c%c', version: %c.%c", atmel_pri_ext.pri[0], atmel_pri_ext.pri[1], atmel_pri_ext.pri[2], atmel_pri_ext.major_version, atmel_pri_ext.minor_version);
+
+       pri_ext->major_version = atmel_pri_ext.major_version;
+       pri_ext->minor_version = atmel_pri_ext.minor_version;
+
+       atmel_pri_ext.features = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);
+       atmel_pri_ext.bottom_boot = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);
+       atmel_pri_ext.burst_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);
+       atmel_pri_ext.page_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);
+
+       DEBUG("features: 0x%2.2x, bottom_boot: 0x%2.2x, burst_mode: 0x%2.2x, page_mode: 0x%2.2x",
+               atmel_pri_ext.features, atmel_pri_ext.bottom_boot, atmel_pri_ext.burst_mode, atmel_pri_ext.page_mode);
+
+       if (atmel_pri_ext.features & 0x02)
+               pri_ext->EraseSuspend = 2;
+
+       if (atmel_pri_ext.bottom_boot)
+               pri_ext->TopBottom = 2;
+       else
+               pri_ext->TopBottom = 3;
+
+       pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
+       pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
+
+       return ERROR_OK;
+}
+
+int cfi_read_0002_pri_ext(flash_bank_t *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       if (cfi_info->manufacturer == CFI_MFR_ATMEL)
+       {
+               return cfi_read_atmel_pri_ext(bank);
+       }
+       else
+       {
+               return cfi_read_spansion_pri_ext(bank);
+       }
+}
+
+int cfi_spansion_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       int printed;
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+
+       printed = snprintf(buf, buf_size, "\nSpansion primary algorithm extend information:\n");
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0],
+                          pri_ext->pri[1], pri_ext->pri[2],
+                          pri_ext->major_version, pri_ext->minor_version);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "Silicon Rev.: 0x%x, Address Sensitive unlock: 0x%x\n",
+                          (pri_ext->SiliconRevision) >> 2,
+                          (pri_ext->SiliconRevision) & 0x03);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "Erase Suspend: 0x%x, Sector Protect: 0x%x\n",
+                          pri_ext->EraseSuspend,
+                          pri_ext->BlkProt);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "VppMin: %2.2d.%1.1x, VppMax: %2.2d.%1.1x\n",
+               (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,
+               (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);
+
+       return ERROR_OK;
+}
+
+int cfi_intel_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       int printed;
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
+
+       printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n");
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "feature_support: 0x%x, suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x\n",
+               (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
+               (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i\n", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
+
+       return ERROR_OK;
+}
+
+int cfi_register_commands(struct command_context_s *cmd_ctx)
+{
+       /*command_t *cfi_cmd = */
+       register_command(cmd_ctx, NULL, "cfi", NULL, COMMAND_ANY, "flash bank cfi <base> <size> <chip_width> <bus_width> <targetNum> [jedec_probe/x16_as_x8]");
+       /*
+       register_command(cmd_ctx, cfi_cmd, "part_id", cfi_handle_part_id_command, COMMAND_EXEC,
+                                        "print part id of cfi flash bank <num>");
+       */
+       return ERROR_OK;
+}
+
+/* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]
+ */
+int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info;
+       int i;
+
+       if (argc < 6)
+       {
+               WARNING("incomplete flash_bank cfi configuration");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       if ((strtoul(args[4], NULL, 0) > CFI_MAX_CHIP_WIDTH)
+               || (strtoul(args[3], NULL, 0) > CFI_MAX_BUS_WIDTH))
+       {
+               ERROR("chip and bus width have to specified in bytes");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+
+       cfi_info = malloc(sizeof(cfi_flash_bank_t));
+       cfi_info->probed = 0;
+       bank->driver_priv = cfi_info;
+
+       cfi_info->write_algorithm = NULL;
+       cfi_info->erase_check_algorithm = NULL;
+
+       cfi_info->x16_as_x8 = 0;
+       cfi_info->jedec_probe = 0;
+       cfi_info->not_cfi = 0;
+
+       for (i = 6; i < argc; i++)
+       {
+               if (strcmp(args[i], "x16_as_x8") == 0)
+               {
+                       cfi_info->x16_as_x8 = 1;
+               }
+               else if (strcmp(args[i], "jedec_probe") == 0)
+               {
+                       cfi_info->jedec_probe = 1;
+               }
+       }
+
+       cfi_info->write_algorithm = NULL;
+
+       /* bank wasn't probed yet */
+       cfi_info->qry[0] = -1;
+
+       return ERROR_OK;
+}
+
+int cfi_intel_erase(struct flash_bank_s *bank, int first, int last)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       u8 command[8];
+       int i;
+
+       cfi_intel_clear_status_register(bank);
+
+       for (i = first; i <= last; i++)
+       {
+               cfi_command(bank, 0x20, command);
+               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+
+               cfi_command(bank, 0xd0, command);
+               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+
+               if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == 0x80)
+                       bank->sectors[i].is_erased = 1;
+               else
+               {
+                       cfi_command(bank, 0xff, command);
+                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+                       ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);
+                       return ERROR_FLASH_OPERATION_FAILED;
+               }
+       }
+
+       cfi_command(bank, 0xff, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+       return ERROR_OK;
+}
+
+int cfi_spansion_erase(struct flash_bank_s *bank, int first, int last)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       target_t *target = bank->target;
+       u8 command[8];
+       int i;
+
+       for (i = first; i <= last; i++)
+       {
+               cfi_command(bank, 0xaa, command);
+               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+               cfi_command(bank, 0x55, command);
+               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
+
+               cfi_command(bank, 0x80, command);
+               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+               cfi_command(bank, 0xaa, command);
+               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+               cfi_command(bank, 0x55, command);
+               target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
+
+               cfi_command(bank, 0x30, command);
+               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+
+               if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == ERROR_OK)
+                       bank->sectors[i].is_erased = 1;
+               else
+               {
+                       cfi_command(bank, 0xf0, command);
+                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+                       ERROR("couldn't erase block %i of flash bank at base 0x%x", i, bank->base);
+                       return ERROR_FLASH_OPERATION_FAILED;
+               }
+       }
+
+       cfi_command(bank, 0xf0, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+       return ERROR_OK;
+}
+
+int cfi_erase(struct flash_bank_s *bank, int first, int last)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       if (bank->target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if ((first < 0) || (last < first) || (last >= bank->num_sectors))
+       {
+               return ERROR_FLASH_SECTOR_INVALID;
+       }
+
+       if (cfi_info->qry[0] != 'Q')
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       switch(cfi_info->pri_id)
+       {
+               case 1:
+               case 3:
+                       return cfi_intel_erase(bank, first, last);
+                       break;
+               case 2:
+                       return cfi_spansion_erase(bank, first, last);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       target_t *target = bank->target;
+       u8 command[8];
+       int retry = 0;
+       int i;
+
+       /* if the device supports neither legacy lock/unlock (bit 3) nor
+        * instant individual block locking (bit 5).
+        */
+       if (!(pri_ext->feature_support & 0x28))
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       cfi_intel_clear_status_register(bank);
+
+       for (i = first; i <= last; i++)
+       {
+               cfi_command(bank, 0x60, command);
+               DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));
+               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+               if (set)
+               {
+                       cfi_command(bank, 0x01, command);
+                       DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));
+                       target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+                       bank->sectors[i].is_protected = 1;
+               }
+               else
+               {
+                       cfi_command(bank, 0xd0, command);
+                       DEBUG("address: 0x%4.4x, command: 0x%4.4x", flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));
+                       target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+                       bank->sectors[i].is_protected = 0;
+               }
+
+               /* instant individual block locking doesn't require reading of the status register */
+               if (!(pri_ext->feature_support & 0x20))
+               {
+                       /* Clear lock bits operation may take up to 1.4s */
+                       cfi_intel_wait_status_busy(bank, 1400);
+               }
+               else
+               {
+                       u8 block_status;
+                       /* read block lock bit, to verify status */
+                       cfi_command(bank, 0x90, command);
+                       target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
+                       block_status = cfi_get_u8(bank, i, 0x2);
+
+                       if ((block_status & 0x1) != set)
+                       {
+                               ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status);
+                               cfi_command(bank, 0x70, command);
+                               target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
+                               cfi_intel_wait_status_busy(bank, 10);
+
+                               if (retry > 10)
+                                       return ERROR_FLASH_OPERATION_FAILED;
+                               else
+                               {
+                                       i--;
+                                       retry++;
+                               }
+                       }
+               }
+       }
+
+       /* if the device doesn't support individual block lock bits set/clear,
+        * all blocks have been unlocked in parallel, so we set those that should be protected
+        */
+       if ((!set) && (!(pri_ext->feature_support & 0x20)))
+       {
+               for (i = 0; i < bank->num_sectors; i++)
+               {
+                       if (bank->sectors[i].is_protected == 1)
+                       {
+                               cfi_intel_clear_status_register(bank);
+
+                               cfi_command(bank, 0x60, command);
+                               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+
+                               cfi_command(bank, 0x01, command);
+                               target->type->write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command);
+
+                               cfi_intel_wait_status_busy(bank, 100);
+                       }
+               }
+       }
+
+       cfi_command(bank, 0xff, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+       return ERROR_OK;
+}
+
+int cfi_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       if (bank->target->state != TARGET_HALTED)
+       {
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if ((first < 0) || (last < first) || (last >= bank->num_sectors))
+       {
+               return ERROR_FLASH_SECTOR_INVALID;
+       }
+
+       if (cfi_info->qry[0] != 'Q')
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       switch(cfi_info->pri_id)
+       {
+               case 1:
+               case 3:
+                       cfi_intel_protect(bank, set, first, last);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+/* FIXME Replace this by a simple memcpy() - still unsure about sideeffects */
+static void cfi_add_byte(struct flash_bank_s *bank, u8 *word, u8 byte)
+{
+       //target_t *target = bank->target;
+
+       int i;
+
+       // NOTE:
+       // The data to flash must not be changed in endian! We write a bytestrem in
+       // target byte order already. Only the control and status byte lane of the flash
+       // WSM is interpreted by the CPU in different ways, when read a u16 or u32
+       // word (data seems to be in the upper or lower byte lane for u16 accesses).
+
+       //if (target->endianness == TARGET_LITTLE_ENDIAN)
+       //{
+               /* shift bytes */
+               for (i = 0; i < bank->bus_width - 1; i++)
+                       word[i] = word[i + 1];
+               word[bank->bus_width - 1] = byte;
+       //}
+       //else
+       //{
+       //      /* shift bytes */
+       //      for (i = bank->bus_width - 1; i > 0; i--)
+       //              word[i] = word[i - 1];
+       //      word[0] = byte;
+       //}
+}
+
+/* Convert code image to target endian */
+/* FIXME create general block conversion fcts in target.c?) */ static
+void cfi_fix_code_endian(target_t *target, u32 *dest, const u32 *src, u32 count)
+{
+       u32 i;
+       for (i=0; i< count; i++)
+       {
+               target_buffer_set_u32(target, (u8*)dest, *src);
+               dest++;
+               src++;
+       }
+}
+
+int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       reg_param_t reg_params[7];
+       armv4_5_algorithm_t armv4_5_info;
+       working_area_t *source;
+       u32 buffer_size = 32768;
+       u8 write_command_buf[CFI_MAX_BUS_WIDTH];
+       u8 busy_pattern_buf[CFI_MAX_BUS_WIDTH];
+       u8 error_pattern_buf[CFI_MAX_BUS_WIDTH];
+       u32 write_command_val, busy_pattern_val, error_pattern_val;
+
+       /* algorithm register usage:
+        * r0: source address (in RAM)
+        * r1: target address (in Flash)
+        * r2: count
+        * r3: flash write command
+        * r4: status byte (returned to host)
+        * r5: busy test pattern
+        * r6: error test pattern
+        */
+
+       static const u32 word_32_code[] = {
+               0xe4904004,   /* loop:  ldr r4, [r0], #4 */
+               0xe5813000,   /*                str r3, [r1] */
+               0xe5814000,   /*                str r4, [r1] */
+               0xe5914000,   /* busy:  ldr r4, [r1] */
+               0xe0047005,   /*                and r7, r4, r5 */
+               0xe1570005,   /*                cmp r7, r5 */
+               0x1afffffb,   /*                bne busy */
+               0xe1140006,   /*                tst r4, r6 */
+               0x1a000003,   /*                bne done */
+               0xe2522001,   /*                subs r2, r2, #1 */
+               0x0a000001,   /*                beq done */
+               0xe2811004,   /*                add r1, r1 #4 */
+               0xeafffff2,   /*                b loop */
+               0xeafffffe    /* done:  b -2 */
+       };
+
+       static const u32 word_16_code[] = {
+               0xe0d040b2,   /* loop:  ldrh r4, [r0], #2 */
+               0xe1c130b0,   /*                strh r3, [r1] */
+               0xe1c140b0,   /*                strh r4, [r1] */
+               0xe1d140b0,   /* busy   ldrh r4, [r1] */
+               0xe0047005,   /*                and r7, r4, r5 */
+               0xe1570005,   /*                cmp r7, r5 */
+               0x1afffffb,   /*                bne busy */
+               0xe1140006,   /*                tst r4, r6 */
+               0x1a000003,   /*                bne done */
+               0xe2522001,   /*                subs r2, r2, #1 */
+               0x0a000001,   /*                beq done */
+               0xe2811002,   /*                add r1, r1 #2 */
+               0xeafffff2,   /*                b loop */
+               0xeafffffe    /* done:  b -2 */
+       };
+
+       static const u32 word_8_code[] = {
+               0xe4d04001,   /* loop:  ldrb r4, [r0], #1 */
+               0xe5c13000,   /*                strb r3, [r1] */
+               0xe5c14000,   /*                strb r4, [r1] */
+               0xe5d14000,   /* busy   ldrb r4, [r1] */
+               0xe0047005,   /*                and r7, r4, r5 */
+               0xe1570005,   /*                cmp r7, r5 */
+               0x1afffffb,   /*                bne busy */
+               0xe1140006,   /*                tst r4, r6 */
+               0x1a000003,   /*                bne done */
+               0xe2522001,   /*                subs r2, r2, #1 */
+               0x0a000001,   /*                beq done */
+               0xe2811001,   /*                add r1, r1 #1 */
+               0xeafffff2,   /*                b loop */
+               0xeafffffe    /* done:  b -2 */
+       };
+       u32 target_code[CFI_MAX_INTEL_CODESIZE];
+       const u32 *target_code_src;
+       int target_code_size;
+       int retval = ERROR_OK;
+
+
+       cfi_intel_clear_status_register(bank);
+
+       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+
+       /* If we are setting up the write_algorith, we need target_code_src */
+       /* if not we only need target_code_size.                                                                                                                */
+       /*                                                                                                                                                                                                                                                                      */
+       /* However, we don't want to create multiple code paths, so we                  */
+       /* do the unecessary evaluation of target_code_src, which the                   */
+       /* compiler will probably nicely optimize away if not needed                            */
+
+       /* prepare algorithm code for target endian */
+       switch (bank->bus_width)
+       {
+       case 1 :
+               target_code_src = word_8_code;
+               target_code_size = sizeof(word_8_code);
+               break;
+       case 2 :
+               target_code_src = word_16_code;
+               target_code_size = sizeof(word_16_code);
+               break;
+       case 4 :
+               target_code_src = word_32_code;
+               target_code_size = sizeof(word_32_code);
+               break;
+       default:
+               ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       /* flash write code */
+       if (!cfi_info->write_algorithm)
+       {
+               if ( target_code_size > sizeof(target_code) )
+               {
+                       WARNING("Internal error - target code buffer to small. Increase CFI_MAX_INTEL_CODESIZE and recompile.");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+               cfi_fix_code_endian(target, target_code, target_code_src, target_code_size);
+
+               /* Get memory for block write handler */
+               retval = target_alloc_working_area(target, target_code_size, &cfi_info->write_algorithm);
+               if (retval != ERROR_OK)
+               {
+                       WARNING("No working area available, can't do block memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               };
+
+               /* write algorithm code to working area */
+               retval = target_write_buffer(target, cfi_info->write_algorithm->address, target_code_size, (u8*)target_code);
+               if (retval != ERROR_OK)
+               {
+                       ERROR("Unable to write block write code to target");
+                       goto cleanup;
+               }
+       }
+
+       /* Get a workspace buffer for the data to flash starting with 32k size.
+          Half size until buffer would be smaller 256 Bytem then fail back */
+       /* FIXME Why 256 bytes, why not 32 bytes (smallest flash write page */
+       while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
+       {
+               buffer_size /= 2;
+               if (buffer_size <= 256)
+               {
+                       WARNING("no large enough working area available, can't do block memory writes");
+                       retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+                       goto cleanup;
+               }
+       };
+
+       /* setup algo registers */
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
+       init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
+       init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
+       init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
+
+       /* prepare command and status register patterns */
+       cfi_command(bank, 0x40, write_command_buf);
+       cfi_command(bank, 0x80, busy_pattern_buf);
+       cfi_command(bank, 0x7e, error_pattern_buf);
+
+       switch (bank->bus_width)
+       {
+       case 1 :
+               write_command_val = write_command_buf[0];
+               busy_pattern_val = busy_pattern_buf[0];
+               error_pattern_val = error_pattern_buf[0];
+               break;
+       case 2 :
+               write_command_val = target_buffer_get_u16(target, write_command_buf);
+               busy_pattern_val = target_buffer_get_u16(target, busy_pattern_buf);
+               error_pattern_val = target_buffer_get_u16(target, error_pattern_buf);
+               break;
+       case 4 :
+               write_command_val = target_buffer_get_u32(target, write_command_buf);
+               busy_pattern_val = target_buffer_get_u32(target, busy_pattern_buf);
+               error_pattern_val = target_buffer_get_u32(target, error_pattern_buf);
+               break;
+       default :
+               ERROR("Unsupported bank buswidth %d, can't do block memory writes", bank->bus_width);
+               retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               goto cleanup;
+       }
+
+       INFO("Using target buffer at 0x%08x and of size 0x%04x", source->address, buffer_size );
+
+       /* Programming main loop */
+       while (count > 0)
+       {
+               u32 thisrun_count = (count > buffer_size) ? buffer_size : count;
+               u32 wsm_error;
+
+               target_write_buffer(target, source->address, thisrun_count, buffer);
+
+               buf_set_u32(reg_params[0].value, 0, 32, source->address);
+               buf_set_u32(reg_params[1].value, 0, 32, address);
+               buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
+
+               buf_set_u32(reg_params[3].value, 0, 32, write_command_val);
+               buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val);
+               buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val);
+
+               INFO("Write 0x%04x bytes to flash at 0x%08x", thisrun_count, address );
+
+               /* Execute algorithm, assume breakpoint for last instruction */
+               retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params,
+                       cfi_info->write_algorithm->address,
+                       cfi_info->write_algorithm->address + target_code_size - sizeof(u32),
+                       10000, /* 10s should be enough for max. 32k of data */
+                       &armv4_5_info);
+
+               /* On failure try a fall back to direct word writes */
+               if (retval != ERROR_OK)
+               {
+                       cfi_intel_clear_status_register(bank);
+                       ERROR("Execution of flash algorythm failed. Can't fall back. Please report.");
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       //retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+                       // FIXME To allow fall back or recovery, we must save the actual status
+                       //       somewhere, so that a higher level code can start recovery.
+                       goto cleanup;
+               }
+
+               /* Check return value from algo code */
+               wsm_error = buf_get_u32(reg_params[4].value, 0, 32) & error_pattern_val;
+               if (wsm_error)
+               {
+                       /* read status register (outputs debug inforation) */
+                       cfi_intel_wait_status_busy(bank, 100);
+                       cfi_intel_clear_status_register(bank);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       goto cleanup;
+               }
+
+               buffer += thisrun_count;
+               address += thisrun_count;
+               count -= thisrun_count;
+       }
+
+       /* free up resources */
+cleanup:
+       if (source)
+               target_free_working_area(target, source);
+
+       if (cfi_info->write_algorithm)
+       {
+               target_free_working_area(target, cfi_info->write_algorithm);
+               cfi_info->write_algorithm = NULL;
+       }
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+       destroy_reg_param(&reg_params[4]);
+       destroy_reg_param(&reg_params[5]);
+       destroy_reg_param(&reg_params[6]);
+
+       return retval;
+}
+
+int cfi_spansion_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u32 count)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       target_t *target = bank->target;
+       reg_param_t reg_params[10];
+       armv4_5_algorithm_t armv4_5_info;
+       working_area_t *source;
+       u32 buffer_size = 32768;
+       u8 write_command[CFI_MAX_BUS_WIDTH];
+       u32 status;
+       int i;
+       int retval;
+       int exit_code = ERROR_OK;
+
+       /* input parameters - */
+       /*      R0 = source address */
+       /*      R1 = destination address */
+       /*      R2 = number of writes */
+       /*      R3 = flash write command */
+       /*      R4 = constant to mask DQ7 bits (also used for Dq5 with shift) */
+       /* output parameters - */
+       /*      R5 = 0x80 ok 0x00 bad */
+       /* temp registers - */
+       /*      R6 = value read from flash to test status */
+       /*      R7 = holding register */
+       /* unlock registers - */
+       /*  R8 = unlock1_addr */
+       /*  R9 = unlock1_cmd */
+       /*  R10 = unlock2_addr */
+       /*  R11 = unlock2_cmd */
+
+       u32 word_32_code[] = {
+                                               /* 00008100 <sp_32_code>:               */
+               0xe4905004,             /* ldr  r5, [r0], #4                    */
+               0xe5889000,     /* str  r9, [r8]                                */
+               0xe58ab000,     /* str  r11, [r10]                              */
+               0xe5883000,     /* str  r3, [r8]                                */
+               0xe5815000,     /* str  r5, [r1]                                */
+               0xe1a00000,     /* nop                                                  */
+                                               /*                                                              */
+                                               /* 00008110 <sp_32_busy>:               */
+               0xe5916000,     /* ldr  r6, [r1]                                */
+               0xe0257006,     /* eor  r7, r5, r6                              */
+               0xe0147007,     /* ands r7, r4, r7                              */
+               0x0a000007,     /* beq  8140 <sp_32_cont> ; b if DQ7 == Data7 */
+               0xe0166124,     /* ands r6, r6, r4, lsr #2              */
+               0x0afffff9,     /* beq  8110 <sp_32_busy> ;     b if DQ5 low */
+               0xe5916000,     /* ldr  r6, [r1]                                */
+               0xe0257006,     /* eor  r7, r5, r6                              */
+               0xe0147007,     /* ands r7, r4, r7                              */
+               0x0a000001,     /* beq  8140 <sp_32_cont> ; b if DQ7 == Data7 */
+               0xe3a05000,     /* mov  r5, #0  ; 0x0 - return 0x00, error */
+               0x1a000004,     /* bne  8154 <sp_32_done>               */
+                                               /*                                                              */
+                               /* 00008140 <sp_32_cont>:                               */
+               0xe2522001,     /* subs r2, r2, #1      ; 0x1           */
+               0x03a05080,     /* moveq        r5, #128        ; 0x80  */
+               0x0a000001,     /* beq  8154 <sp_32_done>               */
+               0xe2811004,     /* add  r1, r1, #4      ; 0x4           */
+               0xeaffffe8,     /* b    8100 <sp_32_code>               */
+                                               /*                                                              */
+                                               /* 00008154 <sp_32_done>:               */
+               0xeafffffe              /* b    8154 <sp_32_done>               */
+               };
+
+               u32 word_16_code[] = {
+                               /* 00008158 <sp_16_code>:              */
+               0xe0d050b2,     /* ldrh r5, [r0], #2               */
+               0xe1c890b0,     /* strh r9, [r8]                                */
+               0xe1cab0b0,     /* strh r11, [r10]                              */
+               0xe1c830b0,     /* strh r3, [r8]                                */
+               0xe1c150b0,     /* strh r5, [r1]                       */
+               0xe1a00000,     /* nop                  (mov r0,r0)    */
+                               /*                                     */
+                               /* 00008168 <sp_16_busy>:              */
+               0xe1d160b0,     /* ldrh r6, [r1]                       */
+               0xe0257006,     /* eor  r7, r5, r6                     */
+               0xe0147007,     /* ands r7, r4, r7                     */
+               0x0a000007,     /* beq  8198 <sp_16_cont>              */
+               0xe0166124,     /* ands r6, r6, r4, lsr #2             */
+               0x0afffff9,     /* beq  8168 <sp_16_busy>              */
+               0xe1d160b0,     /* ldrh r6, [r1]                       */
+               0xe0257006,     /* eor  r7, r5, r6                     */
+               0xe0147007,     /* ands r7, r4, r7                     */
+               0x0a000001,     /* beq  8198 <sp_16_cont>              */
+               0xe3a05000,     /* mov  r5, #0  ; 0x0                  */
+               0x1a000004,     /* bne  81ac <sp_16_done>              */
+                               /*                                     */
+                               /* 00008198 <sp_16_cont>:              */
+               0xe2522001,     /* subs r2, r2, #1      ; 0x1          */
+               0x03a05080,     /* moveq        r5, #128        ; 0x80 */
+               0x0a000001,     /* beq  81ac <sp_16_done>              */
+               0xe2811002,     /* add  r1, r1, #2      ; 0x2          */
+               0xeaffffe8,     /* b    8158 <sp_16_code>              */
+                               /*                                     */
+                               /* 000081ac <sp_16_done>:              */
+               0xeafffffe      /* b    81ac <sp_16_done>              */
+               };
+
+               u32 word_8_code[] = {
+                               /* 000081b0 <sp_16_code_end>:          */
+               0xe4d05001,     /* ldrb r5, [r0], #1                   */
+               0xe5c89000,     /* strb r9, [r8]                                */
+               0xe5cab000,     /* strb r11, [r10]                              */
+               0xe5c83000,     /* strb r3, [r8]                                */
+               0xe5c15000,     /* strb r5, [r1]                       */
+               0xe1a00000,     /* nop                  (mov r0,r0)    */
+                               /*                                     */
+                               /* 000081c0 <sp_8_busy>:               */
+               0xe5d16000,     /* ldrb r6, [r1]                       */
+               0xe0257006,     /* eor  r7, r5, r6                     */
+               0xe0147007,     /* ands r7, r4, r7                     */
+               0x0a000007,     /* beq  81f0 <sp_8_cont>               */
+               0xe0166124,     /* ands r6, r6, r4, lsr #2             */
+               0x0afffff9,     /* beq  81c0 <sp_8_busy>               */
+               0xe5d16000,     /* ldrb r6, [r1]                       */
+               0xe0257006,     /* eor  r7, r5, r6                     */
+               0xe0147007,     /* ands r7, r4, r7                     */
+               0x0a000001,     /* beq  81f0 <sp_8_cont>               */
+               0xe3a05000,     /* mov  r5, #0  ; 0x0                  */
+               0x1a000004,     /* bne  8204 <sp_8_done>               */
+                               /*                                     */
+                               /* 000081f0 <sp_8_cont>:               */
+               0xe2522001,     /* subs r2, r2, #1      ; 0x1          */
+               0x03a05080,     /* moveq        r5, #128        ; 0x80 */
+               0x0a000001,     /* beq  8204 <sp_8_done>               */
+               0xe2811001,     /* add  r1, r1, #1      ; 0x1          */
+               0xeaffffe8,     /* b    81b0 <sp_16_code_end>          */
+                               /*                                     */
+                               /* 00008204 <sp_8_done>:               */
+               0xeafffffe      /* b    8204 <sp_8_done>               */
+       };
+
+       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+
+       /* flash write code */
+       if (!cfi_info->write_algorithm)
+       {
+               u8 *code_p;
+
+               /* convert bus-width dependent algorithm code to correct endiannes */
+               if (bank->bus_width == 1)
+               {
+                       code_p = malloc(24 * 4);
+
+                       for (i = 0; i < 24; i++)
+                               target_buffer_set_u32(target, code_p + (i*4), word_8_code[i]);
+               }
+               else if (bank->bus_width == 2)
+               {
+                       code_p = malloc(24 * 4);
+
+                       for (i = 0; i < 24; i++)
+                               target_buffer_set_u32(target, code_p + (i*4), word_16_code[i]);
+               }
+               else if (bank->bus_width == 4)
+               {
+                       code_p = malloc(24 * 4);
+
+                       for (i = 0; i < 24; i++)
+                               target_buffer_set_u32(target, code_p + (i*4), word_32_code[i]);
+               }
+               else
+               {
+                       return ERROR_FLASH_OPERATION_FAILED;
+               }
+
+               /* allocate working area */
+               retval=target_alloc_working_area(target, 24 * 4,
+                               &cfi_info->write_algorithm);
+               if (retval != ERROR_OK)
+               {
+                       return retval;
+               }
+
+               /* write algorithm code to working area */
+               target_write_buffer(target, cfi_info->write_algorithm->address, 24 * 4, code_p);
+
+               free(code_p);
+       }
+
+       while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
+       {
+               buffer_size /= 2;
+               if (buffer_size <= 256)
+               {
+                       /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
+                       if (cfi_info->write_algorithm)
+                               target_free_working_area(target, cfi_info->write_algorithm);
+
+                       WARNING("not enough working area available, can't do block memory writes");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+       };
+
+       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+       init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
+       init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
+       init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
+       init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);
+       init_reg_param(&reg_params[6], "r8", 32, PARAM_OUT);
+       init_reg_param(&reg_params[7], "r9", 32, PARAM_OUT);
+       init_reg_param(&reg_params[8], "r10", 32, PARAM_OUT);
+       init_reg_param(&reg_params[9], "r11", 32, PARAM_OUT);
+
+       while (count > 0)
+       {
+               u32 thisrun_count = (count > buffer_size) ? buffer_size : count;
+
+               target_write_buffer(target, source->address, thisrun_count, buffer);
+
+               buf_set_u32(reg_params[0].value, 0, 32, source->address);
+               buf_set_u32(reg_params[1].value, 0, 32, address);
+               buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
+               cfi_command(bank, 0xA0, write_command);
+               buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32));
+               cfi_command(bank, 0x80, write_command);
+               buf_set_u32(reg_params[4].value, 0, 32, buf_get_u32(write_command, 0, 32));
+               buf_set_u32(reg_params[6].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock1));
+               buf_set_u32(reg_params[7].value, 0, 32, 0xaa);
+               buf_set_u32(reg_params[8].value, 0, 32, flash_address(bank, 0, pri_ext->_unlock2));
+               buf_set_u32(reg_params[9].value, 0, 32, 0x55);
+
+               retval = target->type->run_algorithm(target, 0, NULL, 10, reg_params,
+                                                    cfi_info->write_algorithm->address,
+                                                    cfi_info->write_algorithm->address + ((24 * 4) - 4),
+                                                    10000, &armv4_5_info);
+
+               status = buf_get_u32(reg_params[5].value, 0, 32);
+
+               if ((retval != ERROR_OK) || status != 0x80)
+               {
+                       DEBUG("status: 0x%x", status);
+                       exit_code = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+
+               buffer += thisrun_count;
+               address += thisrun_count;
+               count -= thisrun_count;
+       }
+
+       target_free_working_area(target, source);
+
+       destroy_reg_param(&reg_params[0]);
+       destroy_reg_param(&reg_params[1]);
+       destroy_reg_param(&reg_params[2]);
+       destroy_reg_param(&reg_params[3]);
+       destroy_reg_param(&reg_params[4]);
+       destroy_reg_param(&reg_params[5]);
+       destroy_reg_param(&reg_params[6]);
+       destroy_reg_param(&reg_params[7]);
+       destroy_reg_param(&reg_params[8]);
+       destroy_reg_param(&reg_params[9]);
+
+       return exit_code;
+}
+
+int cfi_intel_write_word(struct flash_bank_s *bank, u8 *word, u32 address)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       u8 command[8];
+
+       cfi_intel_clear_status_register(bank);
+       cfi_command(bank, 0x40, command);
+       target->type->write_memory(target, address, bank->bus_width, 1, command);
+
+       target->type->write_memory(target, address, bank->bus_width, 1, word);
+
+       if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != 0x80)
+       {
+               cfi_command(bank, 0xff, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+               ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+int cfi_intel_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       u8 command[8];
+
+       /* Calculate buffer size and boundary mask */
+       u32 buffersize = 1UL << cfi_info->max_buf_write_size;
+       u32 buffermask = buffersize-1;
+       u32 bufferwsize;
+
+       /* Check for valid range */
+       if (address & buffermask)
+       {
+               ERROR("Write address at base 0x%x, address %x not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+       switch(bank->chip_width)
+       {
+       case 4 : bufferwsize = buffersize / 4; break;
+       case 2 : bufferwsize = buffersize / 2; break;
+       case 1 : bufferwsize = buffersize; break;
+       default:
+               ERROR("Unsupported chip width %d", bank->chip_width);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       /* Check for valid size */
+       if (wordcount > bufferwsize)
+       {
+               ERROR("Number of data words %d exceeds available buffersize %d", wordcount, buffersize);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       /* Write to flash buffer */
+       cfi_intel_clear_status_register(bank);
+
+       /* Initiate buffer operation _*/
+       cfi_command(bank, 0xE8, command);
+       target->type->write_memory(target, address, bank->bus_width, 1, command);
+       if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->buf_write_timeout_max)) != 0x80)
+       {
+               cfi_command(bank, 0xff, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+               ERROR("couldn't start buffer write operation at base 0x%x, address %x", bank->base, address);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       /* Write buffer wordcount-1 and data words */
+       cfi_command(bank, bufferwsize-1, command);
+       target->type->write_memory(target, address, bank->bus_width, 1, command);
+
+       target->type->write_memory(target, address, bank->bus_width, bufferwsize, word);
+
+       /* Commit write operation */
+       cfi_command(bank, 0xd0, command);
+       target->type->write_memory(target, address, bank->bus_width, 1, command);
+       if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->buf_write_timeout_max)) != 0x80)
+       {
+               cfi_command(bank, 0xff, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+               ERROR("Buffer write at base 0x%x, address %x failed.", bank->base, address);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+int cfi_spansion_write_word(struct flash_bank_s *bank, u8 *word, u32 address)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       target_t *target = bank->target;
+       u8 command[8];
+
+       cfi_command(bank, 0xaa, command);
+       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+       cfi_command(bank, 0x55, command);
+       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
+
+       cfi_command(bank, 0xa0, command);
+       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+       target->type->write_memory(target, address, bank->bus_width, 1, word);
+
+       if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != ERROR_OK)
+       {
+               cfi_command(bank, 0xf0, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+               ERROR("couldn't write word at base 0x%x, address %x", bank->base, address);
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+int cfi_write_word(struct flash_bank_s *bank, u8 *word, u32 address)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       switch(cfi_info->pri_id)
+       {
+               case 1:
+               case 3:
+                       return cfi_intel_write_word(bank, word, address);
+                       break;
+               case 2:
+                       return cfi_spansion_write_word(bank, word, address);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       return ERROR_FLASH_OPERATION_FAILED;
+}
+
+int cfi_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       switch(cfi_info->pri_id)
+       {
+               case 1:
+               case 3:
+                       return cfi_intel_write_words(bank, word, wordcount, address);
+                       break;
+               case 2:
+                       //return cfi_spansion_write_words(bank, word, address);
+                       ERROR("cfi primary command set %i unimplemented - FIXME", cfi_info->pri_id);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       return ERROR_FLASH_OPERATION_FAILED;
+}
+
+int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       u32 address = bank->base + offset;      /* address of first byte to be programmed */
+       u32 write_p, copy_p;
+       int align;      /* number of unaligned bytes */
+       int blk_count; /* number of bus_width bytes for block copy */
+       u8 current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being programmed */
+       int i;
+       int retval;
+
+       if (offset + count > bank->size)
+               return ERROR_FLASH_DST_OUT_OF_BANK;
+
+       if (cfi_info->qry[0] != 'Q')
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       /* start at the first byte of the first word (bus_width size) */
+       write_p = address & ~(bank->bus_width - 1);
+       if ((align = address - write_p) != 0)
+       {
+               INFO("Fixup %d unaligned head bytes", align );
+
+               for (i = 0; i < bank->bus_width; i++)
+                       current_word[i] = 0;
+               copy_p = write_p;
+
+               /* copy bytes before the first write address */
+               for (i = 0; i < align; ++i, ++copy_p)
+               {
+                       u8 byte;
+                       target->type->read_memory(target, copy_p, 1, 1, &byte);
+                       cfi_add_byte(bank, current_word, byte);
+               }
+
+               /* add bytes from the buffer */
+               for (; (i < bank->bus_width) && (count > 0); i++)
+               {
+                       cfi_add_byte(bank, current_word, *buffer++);
+                       count--;
+                       copy_p++;
+               }
+
+               /* if the buffer is already finished, copy bytes after the last write address */
+               for (; (count == 0) && (i < bank->bus_width); ++i, ++copy_p)
+               {
+                       u8 byte;
+                       target->type->read_memory(target, copy_p, 1, 1, &byte);
+                       cfi_add_byte(bank, current_word, byte);
+               }
+
+               retval = cfi_write_word(bank, current_word, write_p);
+               if (retval != ERROR_OK)
+                       return retval;
+               write_p = copy_p;
+       }
+
+       /* handle blocks of bus_size aligned bytes */
+       blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */
+       switch(cfi_info->pri_id)
+       {
+               /* try block writes (fails without working area) */
+               case 1:
+               case 3:
+                       retval = cfi_intel_write_block(bank, buffer, write_p, blk_count);
+                       break;
+               case 2:
+                       retval = cfi_spansion_write_block(bank, buffer, write_p, blk_count);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+       }
+       if (retval == ERROR_OK)
+       {
+               /* Increment pointers and decrease count on succesful block write */
+               buffer += blk_count;
+               write_p += blk_count;
+               count -= blk_count;
+       }
+       else
+       {
+               if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+               {
+                       u32 buffersize = 1UL << cfi_info->max_buf_write_size;
+                       u32 buffermask = buffersize-1;
+                       u32 bufferwsize;
+
+                       switch(bank->chip_width)
+                       {
+                       case 4 : bufferwsize = buffersize / 4; break;
+                       case 2 : bufferwsize = buffersize / 2; break;
+                       case 1 : bufferwsize = buffersize; break;
+                       default:
+                               ERROR("Unsupported chip width %d", bank->chip_width);
+                               return ERROR_FLASH_OPERATION_FAILED;
+                       }
+
+                       /* fall back to memory writes */
+                       while (count > bank->bus_width)
+                       {
+                               if ((write_p & 0xff) == 0)
+                               {
+                                       INFO("Programming at %08x, count %08x bytes remaining", write_p, count);
+                               }
+#if 0
+                               /* NB! this is broken for spansion! */
+                               if ((count > bufferwsize) && !(write_p & buffermask))
+                               {
+                                       retval = cfi_write_words(bank, buffer, bufferwsize, write_p);
+                                       if (retval != ERROR_OK)
+                                               return retval;
+
+                                       buffer += buffersize;
+                                       write_p += buffersize;
+                                       count -= buffersize;
+                               }
+                               else
+#endif
+                               {
+                                       for (i = 0; i < bank->bus_width; i++)
+                                               current_word[i] = 0;
+
+                                       for (i = 0; i < bank->bus_width; i++)
+                                       {
+                                               cfi_add_byte(bank, current_word, *buffer++);
+                                       }
+
+                                       retval = cfi_write_word(bank, current_word, write_p);
+                                       if (retval != ERROR_OK)
+                                               return retval;
+
+                                       write_p += bank->bus_width;
+                                       count -= bank->bus_width;
+                               }
+                       }
+               }
+               else
+                       return retval;
+       }
+
+       /* return to read array mode, so we can read from flash again for padding */
+       cfi_command(bank, 0xf0, current_word);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);
+       cfi_command(bank, 0xff, current_word);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);
+
+       /* handle unaligned tail bytes */
+       if (count > 0)
+       {
+               INFO("Fixup %d unaligned tail bytes", count );
+
+               copy_p = write_p;
+               for (i = 0; i < bank->bus_width; i++)
+                       current_word[i] = 0;
+
+               for (i = 0; (i < bank->bus_width) && (count > 0); ++i, ++copy_p)
+               {
+                       cfi_add_byte(bank, current_word, *buffer++);
+                       count--;
+               }
+               for (; i < bank->bus_width; ++i, ++copy_p)
+               {
+                       u8 byte;
+                       target->type->read_memory(target, copy_p, 1, 1, &byte);
+                       cfi_add_byte(bank, current_word, byte);
+               }
+               retval = cfi_write_word(bank, current_word, write_p);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       /* return to read array mode */
+       cfi_command(bank, 0xf0, current_word);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);
+       cfi_command(bank, 0xff, current_word);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, current_word);
+
+       return ERROR_OK;
+}
+
+void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *bank, void *param)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+
+       pri_ext->_reversed_geometry = 1;
+}
+
+void cfi_fixup_0002_erase_regions(flash_bank_t *bank, void *param)
+{
+       int i;
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+
+       if ((pri_ext->_reversed_geometry) || (pri_ext->TopBottom == 3))
+       {
+               DEBUG("swapping reversed erase region information on cmdset 0002 device");
+
+               for (i = 0; i < cfi_info->num_erase_regions / 2; i++)
+               {
+                       int j = (cfi_info->num_erase_regions - 1) - i;
+                       u32 swap;
+
+                       swap = cfi_info->erase_region_info[i];
+                       cfi_info->erase_region_info[i] = cfi_info->erase_region_info[j];
+                       cfi_info->erase_region_info[j] = swap;
+               }
+       }
+}
+
+void cfi_fixup_0002_unlock_addresses(flash_bank_t *bank, void *param)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       cfi_unlock_addresses_t *unlock_addresses = param;
+
+       pri_ext->_unlock1 = unlock_addresses->unlock1;
+       pri_ext->_unlock2 = unlock_addresses->unlock2;
+}
+
+int cfi_probe(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       u8 command[8];
+       int num_sectors = 0;
+       int i;
+       int sector = 0;
+       u32 offset = 0;
+       u32 unlock1 = 0x555;
+       u32 unlock2 = 0x2aa;
+
+       cfi_info->probed = 0;
+
+       /* JEDEC standard JESD21C uses 0x5555 and 0x2aaa as unlock addresses,
+        * while CFI compatible AMD/Spansion flashes use 0x555 and 0x2aa
+        */
+       if (cfi_info->jedec_probe)
+       {
+               unlock1 = 0x5555;
+               unlock2 = 0x2aaa;
+       }
+
+       /* switch to read identifier codes mode ("AUTOSELECT") */
+       cfi_command(bank, 0xaa, command);
+       target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);
+       cfi_command(bank, 0x55, command);
+       target->type->write_memory(target, flash_address(bank, 0, unlock2), bank->bus_width, 1, command);
+       cfi_command(bank, 0x90, command);
+       target->type->write_memory(target, flash_address(bank, 0, unlock1), bank->bus_width, 1, command);
+
+       if (bank->chip_width == 1)
+       {
+               u8 manufacturer, device_id;
+               target_read_u8(target, bank->base + 0x0, &manufacturer);
+               target_read_u8(target, bank->base + 0x1, &device_id);
+               cfi_info->manufacturer = manufacturer;
+               cfi_info->device_id = device_id;
+       }
+       else if (bank->chip_width == 2)
+       {
+               target_read_u16(target, bank->base + 0x0, &cfi_info->manufacturer);
+               target_read_u16(target, bank->base + 0x2, &cfi_info->device_id);
+       }
+
+       /* switch back to read array mode */
+       cfi_command(bank, 0xf0, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, command);
+       cfi_command(bank, 0xff, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x00), bank->bus_width, 1, command);
+
+       cfi_fixup(bank, cfi_jedec_fixups);
+
+       /* query only if this is a CFI compatible flash,
+        * otherwise the relevant info has already been filled in
+        */
+       if (cfi_info->not_cfi == 0)
+       {
+               /* enter CFI query mode
+                * according to JEDEC Standard No. 68.01,
+                * a single bus sequence with address = 0x55, data = 0x98 should put
+                * the device into CFI query mode.
+                *
+                * SST flashes clearly violate this, and we will consider them incompatbile for now
+                */
+               cfi_command(bank, 0x98, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
+
+               cfi_info->qry[0] = cfi_query_u8(bank, 0, 0x10);
+               cfi_info->qry[1] = cfi_query_u8(bank, 0, 0x11);
+               cfi_info->qry[2] = cfi_query_u8(bank, 0, 0x12);
+
+               DEBUG("CFI qry returned: 0x%2.2x 0x%2.2x 0x%2.2x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2]);
+
+               if ((cfi_info->qry[0] != 'Q') || (cfi_info->qry[1] != 'R') || (cfi_info->qry[2] != 'Y'))
+               {
+                       cfi_command(bank, 0xf0, command);
+                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+                       cfi_command(bank, 0xff, command);
+                       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+                       return ERROR_FLASH_BANK_INVALID;
+               }
+
+               cfi_info->pri_id = cfi_query_u16(bank, 0, 0x13);
+               cfi_info->pri_addr = cfi_query_u16(bank, 0, 0x15);
+               cfi_info->alt_id = cfi_query_u16(bank, 0, 0x17);
+               cfi_info->alt_addr = cfi_query_u16(bank, 0, 0x19);
+
+               DEBUG("qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
+
+               cfi_info->vcc_min = cfi_query_u8(bank, 0, 0x1b);
+               cfi_info->vcc_max = cfi_query_u8(bank, 0, 0x1c);
+               cfi_info->vpp_min = cfi_query_u8(bank, 0, 0x1d);
+               cfi_info->vpp_max = cfi_query_u8(bank, 0, 0x1e);
+               cfi_info->word_write_timeout_typ = cfi_query_u8(bank, 0, 0x1f);
+               cfi_info->buf_write_timeout_typ = cfi_query_u8(bank, 0, 0x20);
+               cfi_info->block_erase_timeout_typ = cfi_query_u8(bank, 0, 0x21);
+               cfi_info->chip_erase_timeout_typ = cfi_query_u8(bank, 0, 0x22);
+               cfi_info->word_write_timeout_max = cfi_query_u8(bank, 0, 0x23);
+               cfi_info->buf_write_timeout_max = cfi_query_u8(bank, 0, 0x24);
+               cfi_info->block_erase_timeout_max = cfi_query_u8(bank, 0, 0x25);
+               cfi_info->chip_erase_timeout_max = cfi_query_u8(bank, 0, 0x26);
+
+               DEBUG("Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x",
+                       (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
+                       (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
+                       (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
+                       (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
+               DEBUG("typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
+                       1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
+               DEBUG("max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
+                       (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
+                       (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
+                       (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
+
+               cfi_info->dev_size = cfi_query_u8(bank, 0, 0x27);
+               cfi_info->interface_desc = cfi_query_u16(bank, 0, 0x28);
+               cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);
+               cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);
+
+               DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));
+
+               if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)
+               {
+                       WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);
+               }
+
+               if (cfi_info->num_erase_regions)
+               {
+                       cfi_info->erase_region_info = malloc(4 * cfi_info->num_erase_regions);
+                       for (i = 0; i < cfi_info->num_erase_regions; i++)
+                       {
+                               cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));
+                               DEBUG("erase region[%i]: %i blocks of size 0x%x", i, (cfi_info->erase_region_info[i] & 0xffff) + 1, (cfi_info->erase_region_info[i] >> 16) * 256);
+                       }
+               }
+               else
+               {
+                       cfi_info->erase_region_info = NULL;
+               }
+
+               /* We need to read the primary algorithm extended query table before calculating
+                * the sector layout to be able to apply fixups
+                */
+               switch(cfi_info->pri_id)
+               {
+                       /* Intel command set (standard and extended) */
+                       case 0x0001:
+                       case 0x0003:
+                               cfi_read_intel_pri_ext(bank);
+                               break;
+                       /* AMD/Spansion, Atmel, ... command set */
+                       case 0x0002:
+                               cfi_read_0002_pri_ext(bank);
+                               break;
+                       default:
+                               ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                               break;
+               }
+
+               /* return to read array mode
+                * we use both reset commands, as some Intel flashes fail to recognize the 0xF0 command
+                */
+               cfi_command(bank, 0xf0, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+               cfi_command(bank, 0xff, command);
+               target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+       }
+
+       /* apply fixups depending on the primary command set */
+       switch(cfi_info->pri_id)
+       {
+               /* Intel command set (standard and extended) */
+               case 0x0001:
+               case 0x0003:
+                       cfi_fixup(bank, cfi_0001_fixups);
+                       break;
+               /* AMD/Spansion, Atmel, ... command set */
+               case 0x0002:
+                       cfi_fixup(bank, cfi_0002_fixups);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       if (cfi_info->num_erase_regions == 0)
+       {
+               /* a device might have only one erase block, spanning the whole device */
+               bank->num_sectors = 1;
+               bank->sectors = malloc(sizeof(flash_sector_t));
+
+               bank->sectors[sector].offset = 0x0;
+               bank->sectors[sector].size = bank->size;
+               bank->sectors[sector].is_erased = -1;
+               bank->sectors[sector].is_protected = -1;
+       }
+       else
+       {
+               for (i = 0; i < cfi_info->num_erase_regions; i++)
+               {
+                       num_sectors += (cfi_info->erase_region_info[i] & 0xffff) + 1;
+               }
+
+               bank->num_sectors = num_sectors;
+               bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
+
+               for (i = 0; i < cfi_info->num_erase_regions; i++)
+               {
+                       int j;
+                       for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++)
+                       {
+                               bank->sectors[sector].offset = offset;
+                               bank->sectors[sector].size = ((cfi_info->erase_region_info[i] >> 16) * 256) * bank->bus_width / bank->chip_width;
+                               offset += bank->sectors[sector].size;
+                               bank->sectors[sector].is_erased = -1;
+                               bank->sectors[sector].is_protected = -1;
+                               sector++;
+                       }
+               }
+       }
+       
+       cfi_info->probed = 1;
+
+       return ERROR_OK;
+}
+
+int cfi_auto_probe(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       if (cfi_info->probed)
+               return ERROR_OK;
+       return cfi_probe(bank);
+}
+
+int cfi_erase_check(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       target_t *target = bank->target;
+       int i;
+       int retval;
+
+       if (!cfi_info->erase_check_algorithm)
+       {
+               u32 erase_check_code[] =
+               {
+                       0xe4d03001,     /* ldrb r3, [r0], #1    */
+                       0xe0022003, /* and r2, r2, r3           */
+                       0xe2511001, /* subs r1, r1, #1          */
+                       0x1afffffb,     /* b -4                                 */
+                       0xeafffffe      /* b 0                                  */
+               };
+
+               /* make sure we have a working area */
+               if (target_alloc_working_area(target, 20, &cfi_info->erase_check_algorithm) != ERROR_OK)
+               {
+                       WARNING("no working area available, falling back to slow memory reads");
+               }
+               else
+               {
+                       u8 erase_check_code_buf[5 * 4];
+
+                       for (i = 0; i < 5; i++)
+                               target_buffer_set_u32(target, erase_check_code_buf + (i*4), erase_check_code[i]);
+
+                       /* write algorithm code to working area */
+                       target->type->write_memory(target, cfi_info->erase_check_algorithm->address, 4, 5, erase_check_code_buf);
+               }
+       }
+
+       if (!cfi_info->erase_check_algorithm)
+       {
+               u32 *buffer = malloc(4096);
+
+               for (i = 0; i < bank->num_sectors; i++)
+               {
+                       u32 address = bank->base + bank->sectors[i].offset;
+                       u32 size = bank->sectors[i].size;
+                       u32 check = 0xffffffffU;
+                       int erased = 1;
+
+                       while (size > 0)
+                       {
+                               u32 thisrun_size = (size > 4096) ? 4096 : size;
+                               int j;
+
+                               target->type->read_memory(target, address, 4, thisrun_size / 4, (u8*)buffer);
+
+                               for (j = 0; j < thisrun_size / 4; j++)
+                                       check &= buffer[j];
+
+                               if (check != 0xffffffff)
+                               {
+                                       erased = 0;
+                                       break;
+                               }
+
+                               size -= thisrun_size;
+                               address += thisrun_size;
+                       }
+
+                       bank->sectors[i].is_erased = erased;
+               }
+
+               free(buffer);
+       }
+       else
+       {
+               for (i = 0; i < bank->num_sectors; i++)
+               {
+                       u32 address = bank->base + bank->sectors[i].offset;
+                       u32 size = bank->sectors[i].size;
+
+                       reg_param_t reg_params[3];
+                       armv4_5_algorithm_t armv4_5_info;
+
+                       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+                       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+                       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+
+                       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+                       buf_set_u32(reg_params[0].value, 0, 32, address);
+
+                       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+                       buf_set_u32(reg_params[1].value, 0, 32, size);
+
+                       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
+                       buf_set_u32(reg_params[2].value, 0, 32, 0xff);
+
+                       if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, cfi_info->erase_check_algorithm->address, cfi_info->erase_check_algorithm->address + 0x10, 10000, &armv4_5_info)) != ERROR_OK)
+                               return ERROR_FLASH_OPERATION_FAILED;
+
+                       if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)
+                               bank->sectors[i].is_erased = 1;
+                       else
+                               bank->sectors[i].is_erased = 0;
+
+                       destroy_reg_param(&reg_params[0]);
+                       destroy_reg_param(&reg_params[1]);
+                       destroy_reg_param(&reg_params[2]);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int cfi_intel_protect_check(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       target_t *target = bank->target;
+       u8 command[CFI_MAX_BUS_WIDTH];
+       int i;
+
+       /* check if block lock bits are supported on this device */
+       if (!(pri_ext->blk_status_reg_mask & 0x1))
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       cfi_command(bank, 0x90, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command);
+
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               u8 block_status = cfi_get_u8(bank, i, 0x2);
+
+               if (block_status & 1)
+                       bank->sectors[i].is_protected = 1;
+               else
+                       bank->sectors[i].is_protected = 0;
+       }
+
+       cfi_command(bank, 0xff, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+       return ERROR_OK;
+}
+
+int cfi_spansion_protect_check(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+       cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+       target_t *target = bank->target;
+       u8 command[8];
+       int i;
+
+       cfi_command(bank, 0xaa, command);
+       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+       cfi_command(bank, 0x55, command);
+       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command);
+
+       cfi_command(bank, 0x90, command);
+       target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command);
+
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               u8 block_status = cfi_get_u8(bank, i, 0x2);
+
+               if (block_status & 1)
+                       bank->sectors[i].is_protected = 1;
+               else
+                       bank->sectors[i].is_protected = 0;
+       }
+
+       cfi_command(bank, 0xf0, command);
+       target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
+
+       return ERROR_OK;
+}
+
+int cfi_protect_check(struct flash_bank_s *bank)
+{
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       if (cfi_info->qry[0] != 'Q')
+               return ERROR_FLASH_BANK_NOT_PROBED;
+
+       switch(cfi_info->pri_id)
+       {
+               case 1:
+               case 3:
+                       return cfi_intel_protect_check(bank);
+                       break;
+               case 2:
+                       return cfi_spansion_protect_check(bank);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       int printed;
+       cfi_flash_bank_t *cfi_info = bank->driver_priv;
+
+       if (cfi_info->qry[0] == (char)-1)
+       {
+               printed = snprintf(buf, buf_size, "\ncfi flash bank not probed yet\n");
+               return ERROR_OK;
+       }
+
+       printed = snprintf(buf, buf_size, "\ncfi information:\n");
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "\nmfr: 0x%4.4x, id:0x%4.4x\n",
+               cfi_info->manufacturer, cfi_info->device_id);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "qry: '%c%c%c', pri_id: 0x%4.4x, pri_addr: 0x%4.4x, alt_id: 0x%4.4x, alt_addr: 0x%4.4x\n", cfi_info->qry[0], cfi_info->qry[1], cfi_info->qry[2], cfi_info->pri_id, cfi_info->pri_addr, cfi_info->alt_id, cfi_info->alt_addr);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "Vcc min: %1.1x.%1.1x, Vcc max: %1.1x.%1.1x, Vpp min: %1.1x.%1.1x, Vpp max: %1.1x.%1.1x\n", (cfi_info->vcc_min & 0xf0) >> 4, cfi_info->vcc_min & 0x0f,
+       (cfi_info->vcc_max & 0xf0) >> 4, cfi_info->vcc_max & 0x0f,
+       (cfi_info->vpp_min & 0xf0) >> 4, cfi_info->vpp_min & 0x0f,
+       (cfi_info->vpp_max & 0xf0) >> 4, cfi_info->vpp_max & 0x0f);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "typ. word write timeout: %u, typ. buf write timeout: %u, typ. block erase timeout: %u, typ. chip erase timeout: %u\n", 1 << cfi_info->word_write_timeout_typ, 1 << cfi_info->buf_write_timeout_typ,
+                 1 << cfi_info->block_erase_timeout_typ, 1 << cfi_info->chip_erase_timeout_typ);
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "max. word write timeout: %u, max. buf write timeout: %u, max. block erase timeout: %u, max. chip erase timeout: %u\n", (1 << cfi_info->word_write_timeout_max) * (1 << cfi_info->word_write_timeout_typ),
+                 (1 << cfi_info->buf_write_timeout_max) * (1 << cfi_info->buf_write_timeout_typ),
+                 (1 << cfi_info->block_erase_timeout_max) * (1 << cfi_info->block_erase_timeout_typ),
+                 (1 << cfi_info->chip_erase_timeout_max) * (1 << cfi_info->chip_erase_timeout_typ));
+       buf += printed;
+       buf_size -= printed;
+
+       printed = snprintf(buf, buf_size, "size: 0x%x, interface desc: %i, max buffer write size: %x\n", 1 << cfi_info->dev_size, cfi_info->interface_desc, cfi_info->max_buf_write_size);
+       buf += printed;
+       buf_size -= printed;
+
+       switch(cfi_info->pri_id)
+       {
+               case 1:
+               case 3:
+                       cfi_intel_info(bank, buf, buf_size);
+                       break;
+               case 2:
+                       cfi_spansion_info(bank, buf, buf_size);
+                       break;
+               default:
+                       ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
+                       break;
+       }
+
+       return ERROR_OK;
+}
index 1390a3fb7a7c7de92081bcf4f33247887f5448a1..4e3234f8a430d627688e90ec2a6a9655a1308a7e 100644 (file)
-/* src/flash/s3c2440_nand.c\r
- *\r
- * S3C2440 OpenOCD NAND Flash controller support.\r
- *\r
- * Copyright 2007,2008 Ben Dooks <ben@fluff.org>\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
- * Many thanks to Simtec Electronics for sponsoring this work.\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "replacements.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#include "nand.h"\r
-#include "s3c24xx_nand.h"\r
-#include "target.h"\r
-\r
-int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);\r
-int s3c2440_init(struct nand_device_s *device);\r
-int s3c2440_nand_ready(struct nand_device_s *device, int timeout);\r
-\r
-nand_flash_controller_t s3c2440_nand_controller =\r
-{\r
-       .name                   = "s3c2440",\r
-       .nand_device_command    = s3c2440_nand_device_command,\r
-       .register_commands      = s3c24xx_register_commands,\r
-       .init                   = s3c2440_init,\r
-       .reset                  = s3c24xx_reset,\r
-       .command                = s3c24xx_command,\r
-       .address                = s3c24xx_address,\r
-       .write_data             = s3c24xx_write_data,\r
-       .read_data              = s3c24xx_read_data,\r
-       .write_page             = s3c24xx_write_page,\r
-       .read_page              = s3c24xx_read_page,\r
-       .write_block_data       = s3c2440_write_block_data,\r
-       .read_block_data        = s3c2440_read_block_data,\r
-       .controller_ready       = s3c24xx_controller_ready,\r
-       .nand_ready             = s3c2440_nand_ready,\r
-};\r
-\r
-int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,\r
-                               char **args, int argc,\r
-                               struct nand_device_s *device)\r
-{\r
-       s3c24xx_nand_controller_t *info;\r
-       \r
-       info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);\r
-       if (info == NULL) {\r
-               return ERROR_NAND_DEVICE_INVALID;\r
-       }\r
-\r
-       /* fill in the address fields for the core device */\r
-       info->cmd = S3C2440_NFCMD;\r
-       info->addr = S3C2440_NFADDR;\r
-       info->data = S3C2440_NFDATA;\r
-       info->nfstat = S3C2440_NFSTAT;\r
-               \r
-       return ERROR_OK;\r
-}\r
-\r
-int s3c2440_init(struct nand_device_s *device)\r
-{\r
-       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;\r
-       target_t *target = s3c24xx_info->target;\r
-       u32 version;\r
-\r
-       target_write_u32(target, S3C2410_NFCONF,\r
-                        S3C2440_NFCONF_TACLS(3) |\r
-                        S3C2440_NFCONF_TWRPH0(7) |\r
-                        S3C2440_NFCONF_TWRPH1(7));\r
-\r
-       target_write_u32(target, S3C2440_NFCONT,\r
-                        S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int s3c2440_nand_ready(struct nand_device_s *device, int timeout)\r
-{\r
-       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;\r
-       target_t *target = s3c24xx_info->target;\r
-       u8 status;\r
-\r
-       if (target->state != TARGET_HALTED) {\r
-               ERROR("target must be halted to use S3C24XX NAND flash controller");\r
-               return ERROR_NAND_OPERATION_FAILED;\r
-       }\r
-       \r
-       do {            \r
-               target_read_u8(target, s3c24xx_info->nfstat, &status);\r
-               \r
-               if (status & S3C2440_NFSTAT_READY)\r
-                       return 1;\r
-\r
-               usleep(1000);\r
-       } while (timeout-- > 0);\r
-\r
-\r
-       return 0;\r
-}\r
-\r
-/* use the fact we can read/write 4 bytes in one go via a single 32bit op */\r
-\r
-int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size)\r
-{\r
-       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;\r
-       target_t *target = s3c24xx_info->target;\r
-       u32 nfdata = s3c24xx_info->data;\r
-       u32 tmp;\r
-\r
-       INFO("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size);\r
-\r
-       if (target->state != TARGET_HALTED) {\r
-               ERROR("target must be halted to use S3C24XX NAND flash controller");\r
-               return ERROR_NAND_OPERATION_FAILED;\r
-       }\r
-\r
-       while (data_size >= 4) {          \r
-               target_read_u32(target, nfdata, &tmp);\r
-\r
-               data[0] = tmp;\r
-               data[1] = tmp >> 8;\r
-               data[2] = tmp >> 16;\r
-               data[3] = tmp >> 24;\r
-\r
-               data_size -= 4;\r
-               data += 4;\r
-       }\r
-\r
-       while (data_size > 0) {\r
-               target_read_u8(target, nfdata, data);\r
-\r
-               data_size -= 1;\r
-               data += 1;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size)\r
-{\r
-       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;\r
-       target_t *target = s3c24xx_info->target;\r
-       u32 nfdata = s3c24xx_info->data;\r
-       u32 tmp;\r
-\r
-       if (target->state != TARGET_HALTED) {\r
-               ERROR("target must be halted to use S3C24XX NAND flash controller");\r
-               return ERROR_NAND_OPERATION_FAILED;\r
-       }\r
-\r
-       while (data_size >= 4) {          \r
-               tmp = le_to_h_u32(data);\r
-               target_write_u32(target, nfdata, tmp);\r
-\r
-               data_size -= 4;\r
-               data += 4;\r
-       }\r
-\r
-       while (data_size > 0) {\r
-               target_write_u8(target, nfdata, *data);\r
-\r
-               data_size -= 1;\r
-               data += 1;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
+/* src/flash/s3c2440_nand.c
+ *
+ * S3C2440 OpenOCD NAND Flash controller support.
+ *
+ * Copyright 2007,2008 Ben Dooks <ben@fluff.org>
+ *
+ * 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.
+ *
+ * Many thanks to Simtec Electronics for sponsoring this work.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nand.h"
+#include "s3c24xx_nand.h"
+#include "target.h"
+
+int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct nand_device_s *device);
+int s3c2440_init(struct nand_device_s *device);
+int s3c2440_nand_ready(struct nand_device_s *device, int timeout);
+
+nand_flash_controller_t s3c2440_nand_controller =
+{
+       .name                   = "s3c2440",
+       .nand_device_command    = s3c2440_nand_device_command,
+       .register_commands      = s3c24xx_register_commands,
+       .init                   = s3c2440_init,
+       .reset                  = s3c24xx_reset,
+       .command                = s3c24xx_command,
+       .address                = s3c24xx_address,
+       .write_data             = s3c24xx_write_data,
+       .read_data              = s3c24xx_read_data,
+       .write_page             = s3c24xx_write_page,
+       .read_page              = s3c24xx_read_page,
+       .write_block_data       = s3c2440_write_block_data,
+       .read_block_data        = s3c2440_read_block_data,
+       .controller_ready       = s3c24xx_controller_ready,
+       .nand_ready             = s3c2440_nand_ready,
+};
+
+int s3c2440_nand_device_command(struct command_context_s *cmd_ctx, char *cmd,
+                               char **args, int argc,
+                               struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *info;
+       
+       info = s3c24xx_nand_device_command(cmd_ctx, cmd, args, argc, device);
+       if (info == NULL) {
+               return ERROR_NAND_DEVICE_INVALID;
+       }
+
+       /* fill in the address fields for the core device */
+       info->cmd = S3C2440_NFCMD;
+       info->addr = S3C2440_NFADDR;
+       info->data = S3C2440_NFDATA;
+       info->nfstat = S3C2440_NFSTAT;
+               
+       return ERROR_OK;
+}
+
+int s3c2440_init(struct nand_device_s *device)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 version;
+
+       target_write_u32(target, S3C2410_NFCONF,
+                        S3C2440_NFCONF_TACLS(3) |
+                        S3C2440_NFCONF_TWRPH0(7) |
+                        S3C2440_NFCONF_TWRPH1(7));
+
+       target_write_u32(target, S3C2440_NFCONT,
+                        S3C2440_NFCONT_INITECC | S3C2440_NFCONT_ENABLE);
+
+       return ERROR_OK;
+}
+
+int s3c2440_nand_ready(struct nand_device_s *device, int timeout)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u8 status;
+
+       if (target->state != TARGET_HALTED) {
+               ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+       
+       do {            
+               target_read_u8(target, s3c24xx_info->nfstat, &status);
+               
+               if (status & S3C2440_NFSTAT_READY)
+                       return 1;
+
+               usleep(1000);
+       } while (timeout-- > 0);
+
+
+       return 0;
+}
+
+/* use the fact we can read/write 4 bytes in one go via a single 32bit op */
+
+int s3c2440_read_block_data(struct nand_device_s *device, u8 *data, int data_size)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 nfdata = s3c24xx_info->data;
+       u32 tmp;
+
+       INFO("%s: reading data: %p, %p, %d\n", __func__, device, data, data_size);
+
+       if (target->state != TARGET_HALTED) {
+               ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       while (data_size >= 4) {          
+               target_read_u32(target, nfdata, &tmp);
+
+               data[0] = tmp;
+               data[1] = tmp >> 8;
+               data[2] = tmp >> 16;
+               data[3] = tmp >> 24;
+
+               data_size -= 4;
+               data += 4;
+       }
+
+       while (data_size > 0) {
+               target_read_u8(target, nfdata, data);
+
+               data_size -= 1;
+               data += 1;
+       }
+
+       return ERROR_OK;
+}
+
+int s3c2440_write_block_data(struct nand_device_s *device, u8 *data, int data_size)
+{
+       s3c24xx_nand_controller_t *s3c24xx_info = device->controller_priv;
+       target_t *target = s3c24xx_info->target;
+       u32 nfdata = s3c24xx_info->data;
+       u32 tmp;
+
+       if (target->state != TARGET_HALTED) {
+               ERROR("target must be halted to use S3C24XX NAND flash controller");
+               return ERROR_NAND_OPERATION_FAILED;
+       }
+
+       while (data_size >= 4) {          
+               tmp = le_to_h_u32(data);
+               target_write_u32(target, nfdata, tmp);
+
+               data_size -= 4;
+               data += 4;
+       }
+
+       while (data_size > 0) {
+               target_write_u8(target, nfdata, *data);
+
+               data_size -= 1;
+               data += 1;
+       }
+
+       return ERROR_OK;
+}
index 9df57dd5b1dbedc001acef9fafabceee71b60a0e..ea7aa97f3e10ea069157d016bd582a5b5d6bcdf6 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "str9xpec.h"\r
-#include "flash.h"\r
-#include "target.h"\r
-#include "log.h"\r
-#include "armv4_5.h"\r
-#include "arm7_9_common.h"\r
-#include "jtag.h"\r
-#include "binarybuffer.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <unistd.h>\r
-#include <getopt.h>\r
-\r
-str9xpec_mem_layout_t mem_layout_str9pec[] = {\r
-       {0x00000000, 0x10000, 0},\r
-       {0x00010000, 0x10000, 1},\r
-       {0x00020000, 0x10000, 2},\r
-       {0x00030000, 0x10000, 3},\r
-       {0x00040000, 0x10000, 4},\r
-       {0x00050000, 0x10000, 5},\r
-       {0x00060000, 0x10000, 6},\r
-       {0x00070000, 0x10000, 7},\r
-       {0x00080000, 0x02000, 32},\r
-       {0x00082000, 0x02000, 33},\r
-       {0x00084000, 0x02000, 34},\r
-       {0x00086000, 0x02000, 35}\r
-};\r
-\r
-int str9xpec_register_commands(struct command_context_s *cmd_ctx);\r
-int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);\r
-int str9xpec_erase(struct flash_bank_s *bank, int first, int last);\r
-int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);\r
-int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);\r
-int str9xpec_probe(struct flash_bank_s *bank);\r
-int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_protect_check(struct flash_bank_s *bank);\r
-int str9xpec_erase_check(struct flash_bank_s *bank);\r
-int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);\r
-\r
-int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);\r
-int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);\r
-int str9xpec_write_options(struct flash_bank_s *bank);\r
-\r
-int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-flash_driver_t str9xpec_flash =\r
-{\r
-       .name = "str9xpec",\r
-       .register_commands = str9xpec_register_commands,\r
-       .flash_bank_command = str9xpec_flash_bank_command,\r
-       .erase = str9xpec_erase,\r
-       .protect = str9xpec_protect,\r
-       .write = str9xpec_write,\r
-       .probe = str9xpec_probe,\r
-       .auto_probe = str9xpec_probe,\r
-       .erase_check = str9xpec_erase_check,\r
-       .protect_check = str9xpec_protect_check,\r
-       .info = str9xpec_info\r
-};\r
-\r
-int str9xpec_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");\r
-       \r
-       register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,\r
-                                        "enable str9xpec turbo mode");\r
-       register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,\r
-                                        "disable str9xpec turbo mode");\r
-       register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,\r
-                                        "configure str9xpec boot sector");\r
-       register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,\r
-                                        "configure str9xpec lvd threshold");\r
-       register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,\r
-                                        "configure str9xpec lvd selection");\r
-       register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,\r
-                                        "configure str9xpec lvd warning");\r
-       register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,\r
-                                        "read str9xpec options");\r
-       register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,\r
-                                        "write str9xpec options");\r
-       register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,\r
-                                        "lock str9xpec device");\r
-       register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,\r
-                                        "unlock str9xpec device");\r
-       register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,\r
-                                        "print part id of str9xpec flash bank <num>");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)\r
-{\r
-       jtag_device_t *device = jtag_get_device(chain_pos);\r
-       \r
-       if (device == NULL)\r
-       {\r
-               DEBUG("Invalid Target");\r
-               return ERROR_TARGET_INVALID;\r
-       }\r
-               \r
-       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
-       {\r
-               scan_field_t field;\r
-                               \r
-               field.device = chain_pos;\r
-               field.num_bits = device->ir_length;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-               \r
-               jtag_add_ir_scan(1, &field, end_state);\r
-               \r
-               free(field.out_value);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-u8 str9xpec_isc_status(int chain_pos)\r
-{\r
-       scan_field_t field;\r
-       u8 status;\r
-       \r
-       if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)\r
-               return ISC_STATUS_ERROR;\r
-       \r
-       field.device = chain_pos;\r
-       field.num_bits = 8;\r
-       field.out_value = NULL;\r
-       field.out_mask = NULL;\r
-       field.in_value = &status;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-       jtag_execute_queue();\r
-       \r
-       DEBUG("status: 0x%2.2x", status);\r
-       \r
-       if (status & ISC_STATUS_SECURITY)\r
-               INFO("Device Security Bit Set");\r
-       \r
-       return status;\r
-}\r
-\r
-int str9xpec_isc_enable(struct flash_bank_s *bank)\r
-{\r
-       u8 status;\r
-       u32 chain_pos;\r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       if (str9xpec_info->isc_enable)\r
-               return ERROR_OK;\r
-       \r
-       /* enter isc mode */\r
-       if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)\r
-               return ERROR_TARGET_INVALID;\r
-       \r
-       /* check ISC status */\r
-       status = str9xpec_isc_status(chain_pos);\r
-       if (status & ISC_STATUS_MODE)\r
-       {\r
-               /* we have entered isc mode */\r
-               str9xpec_info->isc_enable = 1;\r
-               DEBUG("ISC_MODE Enabled");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_isc_disable(struct flash_bank_s *bank)\r
-{\r
-       u8 status;\r
-       u32 chain_pos;\r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       if (!str9xpec_info->isc_enable)\r
-               return ERROR_OK;\r
-       \r
-       if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)\r
-               return ERROR_TARGET_INVALID;\r
-       \r
-       /* delay to handle aborts */\r
-       jtag_add_sleep(50);\r
-       \r
-       /* check ISC status */\r
-       status = str9xpec_isc_status(chain_pos);\r
-       if (!(status & ISC_STATUS_MODE))\r
-       {\r
-               /* we have left isc mode */\r
-               str9xpec_info->isc_enable = 0;\r
-               DEBUG("ISC_MODE Disabled");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_read_config(struct flash_bank_s *bank)\r
-{\r
-       scan_field_t field;\r
-       u8 status;\r
-       u32 chain_pos;\r
-               \r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       DEBUG("ISC_CONFIGURATION");\r
-       \r
-       /* execute ISC_CONFIGURATION command */\r
-       str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);\r
-       \r
-       field.device = chain_pos;\r
-       field.num_bits = 64;\r
-       field.out_value = NULL;\r
-       field.out_mask = NULL;\r
-       field.in_value = str9xpec_info->options;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-       jtag_execute_queue();\r
-       \r
-       status = str9xpec_isc_status(chain_pos);\r
-       \r
-       return status;\r
-}\r
-\r
-int str9xpec_build_block_list(struct flash_bank_s *bank)\r
-{\r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       int i;\r
-       int num_sectors = 0, b0_sectors = 0;\r
-               \r
-       switch (bank->size)\r
-       {\r
-               case (256 * 1024):\r
-                       b0_sectors = 4;\r
-                       break;\r
-               case (512 * 1024):\r
-                       b0_sectors = 8;\r
-                       break;\r
-               default:\r
-                       ERROR("BUG: unknown bank->size encountered");\r
-                       exit(-1);\r
-       }\r
-       \r
-       /* include bank 1 sectors */\r
-       num_sectors = b0_sectors + 4;\r
-       bank->size += (32 * 1024);\r
-       \r
-       bank->num_sectors = num_sectors;\r
-       bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);\r
-       str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);\r
-       \r
-       num_sectors = 0;\r
-       \r
-       for (i = 0; i < b0_sectors; i++)\r
-       {\r
-               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;\r
-               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;\r
-               bank->sectors[num_sectors].is_erased = -1;\r
-               bank->sectors[num_sectors].is_protected = 1;\r
-               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;\r
-       }\r
-       \r
-       for (i = 8; i < 12; i++)\r
-       {\r
-               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;\r
-               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;\r
-               bank->sectors[num_sectors].is_erased = -1;\r
-               bank->sectors[num_sectors].is_protected = 1;\r
-               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/* flash bank str9x <base> <size> 0 0 <target#>\r
- */\r
-int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)\r
-{\r
-       str9xpec_flash_controller_t *str9xpec_info;\r
-       armv4_5_common_t *armv4_5 = NULL;\r
-       arm7_9_common_t *arm7_9 = NULL;\r
-       arm_jtag_t *jtag_info = NULL;\r
-       \r
-       if (argc < 6)\r
-       {\r
-               WARNING("incomplete flash_bank str9x configuration");\r
-               return ERROR_FLASH_BANK_INVALID;\r
-       }\r
-       \r
-       str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));\r
-       bank->driver_priv = str9xpec_info;\r
-       \r
-       if (bank->base != 0x00000000)\r
-       {\r
-               WARNING("overriding flash base address for STR91x device with 0x00000000");\r
-               bank->base = 0x00000000;\r
-       }\r
-\r
-       /* find out jtag position of flash controller\r
-        * it is always after the arm966 core */\r
-       \r
-       armv4_5 = bank->target->arch_info;\r
-       arm7_9 = armv4_5->arch_info;\r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);\r
-       str9xpec_info->isc_enable = 0;\r
-       str9xpec_info->devarm = NULL;\r
-       \r
-       str9xpec_build_block_list(bank);\r
-       \r
-       /* clear option byte register */\r
-       buf_set_u32(str9xpec_info->options, 0, 64, 0);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       scan_field_t field;\r
-       u8 status;\r
-       u32 chain_pos;\r
-       int i;\r
-       u8 *buffer = NULL;\r
-               \r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               str9xpec_isc_enable( bank );\r
-       }\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-       \r
-       buffer = calloc(CEIL(64, 8), 1);\r
-\r
-       DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);\r
-       \r
-       for (i = first; i <= last; i++) {\r
-               buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);\r
-       }\r
-       \r
-       /* execute ISC_BLANK_CHECK command */\r
-       str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);\r
-       \r
-       field.device = chain_pos;\r
-       field.num_bits = 64;\r
-       field.out_value = buffer;\r
-       field.out_mask = NULL;\r
-       field.in_value = NULL;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-       jtag_add_sleep(40000);\r
-       \r
-       /* read blank check result */\r
-       field.device = chain_pos;\r
-       field.num_bits = 64;\r
-       field.out_value = NULL;\r
-       field.out_mask = NULL;\r
-       field.in_value = buffer;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_PI);\r
-       jtag_execute_queue();\r
-       \r
-       status = str9xpec_isc_status(chain_pos);\r
-       \r
-       for (i = first; i <= last; i++)\r
-       {\r
-               if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))\r
-                       bank->sectors[i].is_erased = 0;\r
-               else\r
-                       bank->sectors[i].is_erased = 1;\r
-       }\r
-       \r
-       free(buffer);\r
-       \r
-       str9xpec_isc_disable(bank);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED; \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_protect_check(struct flash_bank_s *bank)\r
-{\r
-       u8 status;\r
-       int i;\r
-               \r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       status = str9xpec_read_config(bank);\r
-       \r
-       for (i = 0; i < bank->num_sectors; i++)\r
-       {\r
-               if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))\r
-                       bank->sectors[i].is_protected = 1;\r
-               else\r
-                       bank->sectors[i].is_protected = 0;\r
-       }\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       scan_field_t field;\r
-       u8 status;\r
-       u32 chain_pos;\r
-       int i;\r
-       u8 *buffer = NULL;\r
-       \r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               str9xpec_isc_enable( bank );\r
-       }\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               return ISC_STATUS_ERROR;\r
-       }\r
-       \r
-       buffer = calloc(CEIL(64, 8), 1);\r
-       \r
-       DEBUG("erase: first_bank: %i, last_bank: %i", first, last);\r
-       \r
-       /* last bank: 0xFF signals a full erase (unlock complete device) */\r
-       /* last bank: 0xFE signals a option byte erase */\r
-       if (last == 0xFF)\r
-       {\r
-               for (i = 0; i < 64; i++) {\r
-                       buf_set_u32(buffer, i, 1, 1);\r
-               }       \r
-       }\r
-       else if (last == 0xFE)\r
-       {\r
-               buf_set_u32(buffer, 49, 1, 1);\r
-       }\r
-       else\r
-       {       \r
-               for (i = first; i <= last; i++) {\r
-                       buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);\r
-               }\r
-       }\r
-       \r
-       DEBUG("ISC_ERASE");\r
-       \r
-       /* execute ISC_ERASE command */\r
-       str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);\r
-       \r
-       field.device = chain_pos;\r
-       field.num_bits = 64;\r
-       field.out_value = buffer;\r
-       field.out_mask = NULL;\r
-       field.in_value = NULL;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-       jtag_execute_queue();\r
-       \r
-       jtag_add_sleep(10);\r
-       \r
-       /* wait for erase completion */\r
-       while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {\r
-               usleep(1000);\r
-       }\r
-       \r
-       free(buffer);\r
-       \r
-       str9xpec_isc_disable(bank);\r
-       \r
-       return status;\r
-}\r
-\r
-int str9xpec_erase(struct flash_bank_s *bank, int first, int last)\r
-{\r
-       int status;\r
-       \r
-       status = str9xpec_erase_area(bank, first, last);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_lock_device(struct flash_bank_s *bank)\r
-{\r
-       scan_field_t field;\r
-       u8 status;\r
-       u32 chain_pos;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               str9xpec_isc_enable( bank );\r
-       }\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               return ISC_STATUS_ERROR;\r
-       }\r
-       \r
-       /* set security address */\r
-       str9xpec_set_address(bank, 0x80);\r
-       \r
-       /* execute ISC_PROGRAM command */\r
-       str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);\r
-       \r
-       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
-       \r
-       do {\r
-               field.device = chain_pos;\r
-               field.num_bits = 8;\r
-               field.out_value = NULL;\r
-               field.out_mask = NULL;\r
-               field.in_value = &status;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-               \r
-               jtag_add_dr_scan(1, &field, -1);\r
-               jtag_execute_queue();\r
-               \r
-       } while(!(status & ISC_STATUS_BUSY));\r
-       \r
-       str9xpec_isc_disable(bank);\r
-       \r
-       return status;\r
-}\r
-\r
-int str9xpec_unlock_device(struct flash_bank_s *bank)\r
-{\r
-       u8 status;\r
-       \r
-       status = str9xpec_erase_area(bank, 0, 255);\r
-       \r
-       return status;\r
-}\r
-\r
-int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)\r
-{\r
-       u8 status;\r
-       int i;\r
-       \r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       status = str9xpec_read_config(bank);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-\r
-       DEBUG("protect: first_bank: %i, last_bank: %i", first, last);\r
-       \r
-       /* last bank: 0xFF signals a full device protect */\r
-       if (last == 0xFF)\r
-       {\r
-               if( set )\r
-               {\r
-                       status = str9xpec_lock_device(bank);\r
-               }\r
-               else\r
-               {\r
-                       /* perform full erase to unlock device */\r
-                       status = str9xpec_unlock_device(bank);\r
-               }\r
-       }\r
-       else\r
-       {       \r
-               for (i = first; i <= last; i++)\r
-               {\r
-                       if( set )\r
-                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);\r
-                       else\r
-                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);\r
-               }\r
-               \r
-               status = str9xpec_write_options(bank);\r
-       }\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)\r
-{\r
-       u32 chain_pos;\r
-       scan_field_t field;\r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       /* set flash controller address */\r
-       str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);\r
-       \r
-       field.device = chain_pos;\r
-       field.num_bits = 8;\r
-       field.out_value = &sector;\r
-       field.out_mask = NULL;\r
-       field.in_value = NULL;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, -1);\r
-               \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)\r
-{\r
-       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;\r
-       u32 dwords_remaining = (count / 8);\r
-       u32 bytes_remaining = (count & 0x00000007);\r
-       u32 bytes_written = 0;\r
-       u8 status;\r
-       u32 check_address = offset;\r
-       u32 chain_pos;\r
-       scan_field_t field;\r
-       u8 *scanbuf;\r
-       int i;\r
-       u32 first_sector = 0;\r
-       u32 last_sector = 0;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               str9xpec_isc_enable(bank);\r
-       }\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-       \r
-       if (offset & 0x7)\r
-       {\r
-               WARNING("offset 0x%x breaks required 8-byte alignment", offset);\r
-               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;\r
-       }\r
-       \r
-       for (i = 0; i < bank->num_sectors; i++)\r
-       {\r
-               u32 sec_start = bank->sectors[i].offset;\r
-               u32 sec_end = sec_start + bank->sectors[i].size;\r
-               \r
-               /* check if destination falls within the current sector */\r
-               if ((check_address >= sec_start) && (check_address < sec_end))\r
-               {\r
-                       /* check if destination ends in the current sector */\r
-                       if (offset + count < sec_end)\r
-                               check_address = offset + count;\r
-                       else\r
-                               check_address = sec_end;\r
-               }\r
-               \r
-               if ((offset >= sec_start) && (offset < sec_end)){\r
-                       first_sector = i;\r
-               }\r
-               \r
-               if ((offset + count >= sec_start) && (offset + count < sec_end)){\r
-                       last_sector = i;\r
-               }\r
-       }\r
-       \r
-       if (check_address != offset + count)\r
-               return ERROR_FLASH_DST_OUT_OF_BANK;\r
-\r
-       DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);\r
-       \r
-       scanbuf = calloc(CEIL(64, 8), 1);\r
-       \r
-       DEBUG("ISC_PROGRAM");\r
-       \r
-       for (i = first_sector; i <= last_sector; i++)\r
-       {\r
-               str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);\r
-               \r
-               dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);\r
-\r
-               while (dwords_remaining > 0)\r
-               {       \r
-                       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
-                       \r
-                       field.device = chain_pos;\r
-                       field.num_bits = 64;\r
-                       field.out_value = (buffer + bytes_written);\r
-                       field.out_mask = NULL;\r
-                       field.in_value = NULL;\r
-                       field.in_check_value = NULL;\r
-                       field.in_check_mask = NULL;\r
-                       field.in_handler = NULL;\r
-                       field.in_handler_priv = NULL;\r
-                       \r
-                       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-                       \r
-                       /* small delay before polling */\r
-                       jtag_add_sleep(50);\r
-                       \r
-                       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
-                       \r
-                       do {\r
-                               field.device = chain_pos;\r
-                               field.num_bits = 8;\r
-                               field.out_value = NULL;\r
-                               field.out_mask = NULL;\r
-                               field.in_value = scanbuf;\r
-                               field.in_check_value = NULL;\r
-                               field.in_check_mask = NULL;\r
-                               field.in_handler = NULL;\r
-                               field.in_handler_priv = NULL;\r
-                               \r
-                               jtag_add_dr_scan(1, &field, -1);\r
-                               jtag_execute_queue();\r
-                               \r
-                               status = buf_get_u32(scanbuf, 0, 8);\r
-                               \r
-                       } while(!(status & ISC_STATUS_BUSY));\r
-                       \r
-                       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-                               return ERROR_FLASH_OPERATION_FAILED;\r
-                       \r
-                       //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)\r
-                       //      return ERROR_FLASH_OPERATION_FAILED;\r
-               \r
-                       dwords_remaining--;\r
-                       bytes_written += 8;\r
-               }\r
-       }\r
-       \r
-       if (bytes_remaining)\r
-       {\r
-               u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
-               int i = 0;\r
-                               \r
-               while(bytes_remaining > 0)\r
-               {\r
-                       last_dword[i++] = *(buffer + bytes_written); \r
-                       bytes_remaining--;\r
-                       bytes_written++;\r
-               }\r
-               \r
-               str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
-               \r
-               field.device = chain_pos;\r
-               field.num_bits = 64;\r
-               field.out_value = last_dword;\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-               \r
-               jtag_add_dr_scan(1, &field, TAP_RTI);\r
-               \r
-               /* small delay before polling */\r
-               jtag_add_sleep(50);\r
-               \r
-               str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
-               \r
-               do {\r
-                       field.device = chain_pos;\r
-                       field.num_bits = 8;\r
-                       field.out_value = NULL;\r
-                       field.out_mask = NULL;\r
-                       field.in_value = scanbuf;\r
-                       field.in_check_value = NULL;\r
-                       field.in_check_mask = NULL;\r
-                       field.in_handler = NULL;\r
-                       field.in_handler_priv = NULL;\r
-                       \r
-                       jtag_add_dr_scan(1, &field, -1);\r
-                       jtag_execute_queue();\r
-                       \r
-                       status = buf_get_u32(scanbuf, 0, 8);\r
-                       \r
-               } while(!(status & ISC_STATUS_BUSY));\r
-               \r
-               if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-                       return ERROR_FLASH_OPERATION_FAILED;\r
-               \r
-               //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)\r
-               //      return ERROR_FLASH_OPERATION_FAILED;\r
-       }\r
-\r
-       free(scanbuf);\r
-\r
-       str9xpec_isc_disable(bank);\r
-                               \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_probe(struct flash_bank_s *bank)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       scan_field_t field;\r
-       u8 *buffer = NULL;\r
-       u32 chain_pos;\r
-       u32 idcode;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-\r
-       if (argc < 1)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       buffer = calloc(CEIL(32, 8), 1);\r
-       \r
-       str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);\r
-       \r
-       field.device = chain_pos;\r
-       field.num_bits = 32;\r
-       field.out_value = NULL;\r
-       field.out_mask = NULL;\r
-       field.in_value = buffer;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-       jtag_execute_queue();\r
-       \r
-       idcode = buf_get_u32(buffer, 0, 32);\r
-       \r
-       command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);\r
-       \r
-       free(buffer);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_erase_check(struct flash_bank_s *bank)\r
-{\r
-       return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);\r
-}\r
-\r
-int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)\r
-{\r
-       snprintf(buf, buf_size, "str9xpec flash driver info" );\r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       u8 status;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec options_read <bank>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       status = str9xpec_read_config(bank);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       \r
-       /* boot bank */\r
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))\r
-               command_print(cmd_ctx, "CS Map: bank1");\r
-       else\r
-               command_print(cmd_ctx, "CS Map: bank0");\r
-       \r
-       /* OTP lock */\r
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))\r
-               command_print(cmd_ctx, "OTP Lock: OTP Locked");\r
-       else\r
-               command_print(cmd_ctx, "OTP Lock: OTP Unlocked");\r
-       \r
-       /* LVD Threshold */\r
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))\r
-               command_print(cmd_ctx, "LVD Threshold: 2.7v");\r
-       else\r
-               command_print(cmd_ctx, "LVD Threshold: 2.4v");\r
-       \r
-       /* LVD reset warning */\r
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))\r
-               command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");\r
-       else\r
-               command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");\r
-       \r
-       /* LVD reset select */\r
-       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))\r
-               command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");\r
-       else\r
-               command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_write_options(struct flash_bank_s *bank)\r
-{\r
-       scan_field_t field;\r
-       u8 status;\r
-       u32 chain_pos;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       /* erase config options first */\r
-       status = str9xpec_erase_area( bank, 0xFE, 0xFE );\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return status; \r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               str9xpec_isc_enable( bank );\r
-       }\r
-       \r
-       if (!str9xpec_info->isc_enable) {\r
-               return ISC_STATUS_ERROR;\r
-       }\r
-       \r
-       /* according to data 64th bit has to be set */\r
-       buf_set_u32(str9xpec_info->options, 63, 1, 1);\r
-       \r
-       /* set option byte address */\r
-       str9xpec_set_address(bank, 0x50);\r
-       \r
-       /* execute ISC_PROGRAM command */\r
-       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);\r
-               \r
-       field.device = chain_pos;\r
-       field.num_bits = 64;\r
-       field.out_value = str9xpec_info->options;\r
-       field.out_mask = NULL;\r
-       field.in_value = NULL;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(1, &field, TAP_RTI);\r
-       \r
-       /* small delay before polling */\r
-       jtag_add_sleep(50);\r
-       \r
-       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);\r
-       \r
-       do {\r
-               field.device = chain_pos;\r
-               field.num_bits = 8;\r
-               field.out_value = NULL;\r
-               field.out_mask = NULL;\r
-               field.in_value = &status;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-               \r
-               jtag_add_dr_scan(1, &field, -1);\r
-               jtag_execute_queue();\r
-               \r
-       } while(!(status & ISC_STATUS_BUSY));\r
-       \r
-       str9xpec_isc_disable(bank);\r
-       \r
-       return status;\r
-}\r
-\r
-int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       u8 status;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec options_write <bank>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       status = str9xpec_write_options(bank);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       if (strcmp(args[1], "bank1") == 0)\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);\r
-       }\r
-       else\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       if (strcmp(args[1], "2.7v") == 0)\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);\r
-       }\r
-       else\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       if (strcmp(args[1], "vdd_vddq") == 0)\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);\r
-       }\r
-       else\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       if (strcmp(args[1], "vdd_vddq") == 0)\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);\r
-       }\r
-       else\r
-       {\r
-               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       u8 status;\r
-       flash_bank_t *bank;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec lock <bank>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       status = str9xpec_lock_device(bank);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       u8 status;\r
-       flash_bank_t *bank;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec unlock <bank>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       status = str9xpec_unlock_device(bank);\r
-       \r
-       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)\r
-               return ERROR_FLASH_OPERATION_FAILED;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       u32 chain_pos;\r
-       jtag_device_t* dev0;\r
-       jtag_device_t* dev2;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec enable_turbo <bank>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       /* remove arm core from chain - enter turbo mode */\r
-       \r
-       str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);\r
-       jtag_execute_queue();\r
-       \r
-       /* modify scan chain - str9 core has been removed */\r
-       dev0 = jtag_get_device(chain_pos);\r
-       str9xpec_info->devarm = jtag_get_device(chain_pos+1);\r
-       dev2 = jtag_get_device(chain_pos+2);\r
-       dev0->next = dev2;\r
-       jtag_num_devices--;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       flash_bank_t *bank;\r
-       u32 chain_pos;\r
-       jtag_device_t* dev0;\r
-       str9xpec_flash_controller_t *str9xpec_info = NULL;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "str9xpec disable_turbo <bank>");\r
-               return ERROR_OK;        \r
-       }\r
-       \r
-       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));\r
-       if (!bank)\r
-       {\r
-               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       str9xpec_info = bank->driver_priv;\r
-       \r
-       chain_pos = str9xpec_info->chain_pos;\r
-       \r
-       dev0 = jtag_get_device(chain_pos);\r
-       \r
-       /* exit turbo mode via TLR */\r
-       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);\r
-       jtag_execute_queue();\r
-       \r
-       /* restore previous scan chain */\r
-       if( str9xpec_info->devarm ) {\r
-               dev0->next = str9xpec_info->devarm;\r
-               jtag_num_devices++;\r
-               str9xpec_info->devarm = NULL;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "str9xpec.h"
+#include "flash.h"
+#include "target.h"
+#include "log.h"
+#include "armv4_5.h"
+#include "arm7_9_common.h"
+#include "jtag.h"
+#include "binarybuffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+str9xpec_mem_layout_t mem_layout_str9pec[] = {
+       {0x00000000, 0x10000, 0},
+       {0x00010000, 0x10000, 1},
+       {0x00020000, 0x10000, 2},
+       {0x00030000, 0x10000, 3},
+       {0x00040000, 0x10000, 4},
+       {0x00050000, 0x10000, 5},
+       {0x00060000, 0x10000, 6},
+       {0x00070000, 0x10000, 7},
+       {0x00080000, 0x02000, 32},
+       {0x00082000, 0x02000, 33},
+       {0x00084000, 0x02000, 34},
+       {0x00086000, 0x02000, 35}
+};
+
+int str9xpec_register_commands(struct command_context_s *cmd_ctx);
+int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
+int str9xpec_erase(struct flash_bank_s *bank, int first, int last);
+int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);
+int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
+int str9xpec_probe(struct flash_bank_s *bank);
+int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_protect_check(struct flash_bank_s *bank);
+int str9xpec_erase_check(struct flash_bank_s *bank);
+int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);
+
+int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);
+int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);
+int str9xpec_write_options(struct flash_bank_s *bank);
+
+int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+flash_driver_t str9xpec_flash =
+{
+       .name = "str9xpec",
+       .register_commands = str9xpec_register_commands,
+       .flash_bank_command = str9xpec_flash_bank_command,
+       .erase = str9xpec_erase,
+       .protect = str9xpec_protect,
+       .write = str9xpec_write,
+       .probe = str9xpec_probe,
+       .auto_probe = str9xpec_probe,
+       .erase_check = str9xpec_erase_check,
+       .protect_check = str9xpec_protect_check,
+       .info = str9xpec_info
+};
+
+int str9xpec_register_commands(struct command_context_s *cmd_ctx)
+{
+       command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");
+       
+       register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,
+                                        "enable str9xpec turbo mode");
+       register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,
+                                        "disable str9xpec turbo mode");
+       register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,
+                                        "configure str9xpec boot sector");
+       register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,
+                                        "configure str9xpec lvd threshold");
+       register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,
+                                        "configure str9xpec lvd selection");
+       register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,
+                                        "configure str9xpec lvd warning");
+       register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,
+                                        "read str9xpec options");
+       register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,
+                                        "write str9xpec options");
+       register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,
+                                        "lock str9xpec device");
+       register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,
+                                        "unlock str9xpec device");
+       register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,
+                                        "print part id of str9xpec flash bank <num>");
+       
+       return ERROR_OK;
+}
+
+int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)
+{
+       jtag_device_t *device = jtag_get_device(chain_pos);
+       
+       if (device == NULL)
+       {
+               DEBUG("Invalid Target");
+               return ERROR_TARGET_INVALID;
+       }
+               
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+                               
+               field.device = chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               jtag_add_ir_scan(1, &field, end_state);
+               
+               free(field.out_value);
+       }
+       
+       return ERROR_OK;
+}
+
+u8 str9xpec_isc_status(int chain_pos)
+{
+       scan_field_t field;
+       u8 status;
+       
+       if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)
+               return ISC_STATUS_ERROR;
+       
+       field.device = chain_pos;
+       field.num_bits = 8;
+       field.out_value = NULL;
+       field.out_mask = NULL;
+       field.in_value = &status;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_RTI);
+       jtag_execute_queue();
+       
+       DEBUG("status: 0x%2.2x", status);
+       
+       if (status & ISC_STATUS_SECURITY)
+               INFO("Device Security Bit Set");
+       
+       return status;
+}
+
+int str9xpec_isc_enable(struct flash_bank_s *bank)
+{
+       u8 status;
+       u32 chain_pos;
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       if (str9xpec_info->isc_enable)
+               return ERROR_OK;
+       
+       /* enter isc mode */
+       if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)
+               return ERROR_TARGET_INVALID;
+       
+       /* check ISC status */
+       status = str9xpec_isc_status(chain_pos);
+       if (status & ISC_STATUS_MODE)
+       {
+               /* we have entered isc mode */
+               str9xpec_info->isc_enable = 1;
+               DEBUG("ISC_MODE Enabled");
+       }
+       
+       return ERROR_OK;
+}
+
+int str9xpec_isc_disable(struct flash_bank_s *bank)
+{
+       u8 status;
+       u32 chain_pos;
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       if (!str9xpec_info->isc_enable)
+               return ERROR_OK;
+       
+       if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)
+               return ERROR_TARGET_INVALID;
+       
+       /* delay to handle aborts */
+       jtag_add_sleep(50);
+       
+       /* check ISC status */
+       status = str9xpec_isc_status(chain_pos);
+       if (!(status & ISC_STATUS_MODE))
+       {
+               /* we have left isc mode */
+               str9xpec_info->isc_enable = 0;
+               DEBUG("ISC_MODE Disabled");
+       }
+       
+       return ERROR_OK;
+}
+
+int str9xpec_read_config(struct flash_bank_s *bank)
+{
+       scan_field_t field;
+       u8 status;
+       u32 chain_pos;
+               
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       DEBUG("ISC_CONFIGURATION");
+       
+       /* execute ISC_CONFIGURATION command */
+       str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);
+       
+       field.device = chain_pos;
+       field.num_bits = 64;
+       field.out_value = NULL;
+       field.out_mask = NULL;
+       field.in_value = str9xpec_info->options;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_RTI);
+       jtag_execute_queue();
+       
+       status = str9xpec_isc_status(chain_pos);
+       
+       return status;
+}
+
+int str9xpec_build_block_list(struct flash_bank_s *bank)
+{
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       int i;
+       int num_sectors = 0, b0_sectors = 0;
+               
+       switch (bank->size)
+       {
+               case (256 * 1024):
+                       b0_sectors = 4;
+                       break;
+               case (512 * 1024):
+                       b0_sectors = 8;
+                       break;
+               default:
+                       ERROR("BUG: unknown bank->size encountered");
+                       exit(-1);
+       }
+       
+       /* include bank 1 sectors */
+       num_sectors = b0_sectors + 4;
+       bank->size += (32 * 1024);
+       
+       bank->num_sectors = num_sectors;
+       bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
+       str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);
+       
+       num_sectors = 0;
+       
+       for (i = 0; i < b0_sectors; i++)
+       {
+               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
+               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
+               bank->sectors[num_sectors].is_erased = -1;
+               bank->sectors[num_sectors].is_protected = 1;
+               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
+       }
+       
+       for (i = 8; i < 12; i++)
+       {
+               bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
+               bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
+               bank->sectors[num_sectors].is_erased = -1;
+               bank->sectors[num_sectors].is_protected = 1;
+               str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
+       }
+       
+       return ERROR_OK;
+}
+
+/* flash bank str9x <base> <size> 0 0 <target#>
+ */
+int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+{
+       str9xpec_flash_controller_t *str9xpec_info;
+       armv4_5_common_t *armv4_5 = NULL;
+       arm7_9_common_t *arm7_9 = NULL;
+       arm_jtag_t *jtag_info = NULL;
+       
+       if (argc < 6)
+       {
+               WARNING("incomplete flash_bank str9x configuration");
+               return ERROR_FLASH_BANK_INVALID;
+       }
+       
+       str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));
+       bank->driver_priv = str9xpec_info;
+       
+       if (bank->base != 0x00000000)
+       {
+               WARNING("overriding flash base address for STR91x device with 0x00000000");
+               bank->base = 0x00000000;
+       }
+
+       /* find out jtag position of flash controller
+        * it is always after the arm966 core */
+       
+       armv4_5 = bank->target->arch_info;
+       arm7_9 = armv4_5->arch_info;
+       jtag_info = &arm7_9->jtag_info;
+       
+       str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);
+       str9xpec_info->isc_enable = 0;
+       str9xpec_info->devarm = NULL;
+       
+       str9xpec_build_block_list(bank);
+       
+       /* clear option byte register */
+       buf_set_u32(str9xpec_info->options, 0, 64, 0);
+       
+       return ERROR_OK;
+}
+
+int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)
+{
+       scan_field_t field;
+       u8 status;
+       u32 chain_pos;
+       int i;
+       u8 *buffer = NULL;
+               
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable( bank );
+       }
+       
+       if (!str9xpec_info->isc_enable) {
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+       
+       buffer = calloc(CEIL(64, 8), 1);
+
+       DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
+       
+       for (i = first; i <= last; i++) {
+               buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
+       }
+       
+       /* execute ISC_BLANK_CHECK command */
+       str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);
+       
+       field.device = chain_pos;
+       field.num_bits = 64;
+       field.out_value = buffer;
+       field.out_mask = NULL;
+       field.in_value = NULL;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_RTI);
+       jtag_add_sleep(40000);
+       
+       /* read blank check result */
+       field.device = chain_pos;
+       field.num_bits = 64;
+       field.out_value = NULL;
+       field.out_mask = NULL;
+       field.in_value = buffer;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_PI);
+       jtag_execute_queue();
+       
+       status = str9xpec_isc_status(chain_pos);
+       
+       for (i = first; i <= last; i++)
+       {
+               if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
+                       bank->sectors[i].is_erased = 0;
+               else
+                       bank->sectors[i].is_erased = 1;
+       }
+       
+       free(buffer);
+       
+       str9xpec_isc_disable(bank);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED; 
+       return ERROR_OK;
+}
+
+int str9xpec_protect_check(struct flash_bank_s *bank)
+{
+       u8 status;
+       int i;
+               
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       status = str9xpec_read_config(bank);
+       
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
+                       bank->sectors[i].is_protected = 1;
+               else
+                       bank->sectors[i].is_protected = 0;
+       }
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       return ERROR_OK;
+}
+
+int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)
+{
+       scan_field_t field;
+       u8 status;
+       u32 chain_pos;
+       int i;
+       u8 *buffer = NULL;
+       
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable( bank );
+       }
+       
+       if (!str9xpec_info->isc_enable) {
+               return ISC_STATUS_ERROR;
+       }
+       
+       buffer = calloc(CEIL(64, 8), 1);
+       
+       DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
+       
+       /* last bank: 0xFF signals a full erase (unlock complete device) */
+       /* last bank: 0xFE signals a option byte erase */
+       if (last == 0xFF)
+       {
+               for (i = 0; i < 64; i++) {
+                       buf_set_u32(buffer, i, 1, 1);
+               }       
+       }
+       else if (last == 0xFE)
+       {
+               buf_set_u32(buffer, 49, 1, 1);
+       }
+       else
+       {       
+               for (i = first; i <= last; i++) {
+                       buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
+               }
+       }
+       
+       DEBUG("ISC_ERASE");
+       
+       /* execute ISC_ERASE command */
+       str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);
+       
+       field.device = chain_pos;
+       field.num_bits = 64;
+       field.out_value = buffer;
+       field.out_mask = NULL;
+       field.in_value = NULL;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_RTI);
+       jtag_execute_queue();
+       
+       jtag_add_sleep(10);
+       
+       /* wait for erase completion */
+       while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {
+               usleep(1000);
+       }
+       
+       free(buffer);
+       
+       str9xpec_isc_disable(bank);
+       
+       return status;
+}
+
+int str9xpec_erase(struct flash_bank_s *bank, int first, int last)
+{
+       int status;
+       
+       status = str9xpec_erase_area(bank, first, last);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       
+       return ERROR_OK;
+}
+
+int str9xpec_lock_device(struct flash_bank_s *bank)
+{
+       scan_field_t field;
+       u8 status;
+       u32 chain_pos;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       str9xpec_info = bank->driver_priv;
+       chain_pos = str9xpec_info->chain_pos;
+       
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable( bank );
+       }
+       
+       if (!str9xpec_info->isc_enable) {
+               return ISC_STATUS_ERROR;
+       }
+       
+       /* set security address */
+       str9xpec_set_address(bank, 0x80);
+       
+       /* execute ISC_PROGRAM command */
+       str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);
+       
+       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+       
+       do {
+               field.device = chain_pos;
+               field.num_bits = 8;
+               field.out_value = NULL;
+               field.out_mask = NULL;
+               field.in_value = &status;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               jtag_add_dr_scan(1, &field, -1);
+               jtag_execute_queue();
+               
+       } while(!(status & ISC_STATUS_BUSY));
+       
+       str9xpec_isc_disable(bank);
+       
+       return status;
+}
+
+int str9xpec_unlock_device(struct flash_bank_s *bank)
+{
+       u8 status;
+       
+       status = str9xpec_erase_area(bank, 0, 255);
+       
+       return status;
+}
+
+int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+       u8 status;
+       int i;
+       
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       status = str9xpec_read_config(bank);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+
+       DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
+       
+       /* last bank: 0xFF signals a full device protect */
+       if (last == 0xFF)
+       {
+               if( set )
+               {
+                       status = str9xpec_lock_device(bank);
+               }
+               else
+               {
+                       /* perform full erase to unlock device */
+                       status = str9xpec_unlock_device(bank);
+               }
+       }
+       else
+       {       
+               for (i = first; i <= last; i++)
+               {
+                       if( set )
+                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
+                       else
+                               buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
+               }
+               
+               status = str9xpec_write_options(bank);
+       }
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       
+       return ERROR_OK;
+}
+
+int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)
+{
+       u32 chain_pos;
+       scan_field_t field;
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       /* set flash controller address */
+       str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);
+       
+       field.device = chain_pos;
+       field.num_bits = 8;
+       field.out_value = &sector;
+       field.out_mask = NULL;
+       field.in_value = NULL;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, -1);
+               
+       return ERROR_OK;
+}
+
+int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+{
+       str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+       u32 dwords_remaining = (count / 8);
+       u32 bytes_remaining = (count & 0x00000007);
+       u32 bytes_written = 0;
+       u8 status;
+       u32 check_address = offset;
+       u32 chain_pos;
+       scan_field_t field;
+       u8 *scanbuf;
+       int i;
+       u32 first_sector = 0;
+       u32 last_sector = 0;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable(bank);
+       }
+       
+       if (!str9xpec_info->isc_enable) {
+               return ERROR_FLASH_OPERATION_FAILED;
+       }
+       
+       if (offset & 0x7)
+       {
+               WARNING("offset 0x%x breaks required 8-byte alignment", offset);
+               return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+       }
+       
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               u32 sec_start = bank->sectors[i].offset;
+               u32 sec_end = sec_start + bank->sectors[i].size;
+               
+               /* check if destination falls within the current sector */
+               if ((check_address >= sec_start) && (check_address < sec_end))
+               {
+                       /* check if destination ends in the current sector */
+                       if (offset + count < sec_end)
+                               check_address = offset + count;
+                       else
+                               check_address = sec_end;
+               }
+               
+               if ((offset >= sec_start) && (offset < sec_end)){
+                       first_sector = i;
+               }
+               
+               if ((offset + count >= sec_start) && (offset + count < sec_end)){
+                       last_sector = i;
+               }
+       }
+       
+       if (check_address != offset + count)
+               return ERROR_FLASH_DST_OUT_OF_BANK;
+
+       DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
+       
+       scanbuf = calloc(CEIL(64, 8), 1);
+       
+       DEBUG("ISC_PROGRAM");
+       
+       for (i = first_sector; i <= last_sector; i++)
+       {
+               str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
+               
+               dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);
+
+               while (dwords_remaining > 0)
+               {       
+                       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
+                       
+                       field.device = chain_pos;
+                       field.num_bits = 64;
+                       field.out_value = (buffer + bytes_written);
+                       field.out_mask = NULL;
+                       field.in_value = NULL;
+                       field.in_check_value = NULL;
+                       field.in_check_mask = NULL;
+                       field.in_handler = NULL;
+                       field.in_handler_priv = NULL;
+                       
+                       jtag_add_dr_scan(1, &field, TAP_RTI);
+                       
+                       /* small delay before polling */
+                       jtag_add_sleep(50);
+                       
+                       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+                       
+                       do {
+                               field.device = chain_pos;
+                               field.num_bits = 8;
+                               field.out_value = NULL;
+                               field.out_mask = NULL;
+                               field.in_value = scanbuf;
+                               field.in_check_value = NULL;
+                               field.in_check_mask = NULL;
+                               field.in_handler = NULL;
+                               field.in_handler_priv = NULL;
+                               
+                               jtag_add_dr_scan(1, &field, -1);
+                               jtag_execute_queue();
+                               
+                               status = buf_get_u32(scanbuf, 0, 8);
+                               
+                       } while(!(status & ISC_STATUS_BUSY));
+                       
+                       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+                               return ERROR_FLASH_OPERATION_FAILED;
+                       
+                       //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
+                       //      return ERROR_FLASH_OPERATION_FAILED;
+               
+                       dwords_remaining--;
+                       bytes_written += 8;
+               }
+       }
+       
+       if (bytes_remaining)
+       {
+               u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+               int i = 0;
+                               
+               while(bytes_remaining > 0)
+               {
+                       last_dword[i++] = *(buffer + bytes_written); 
+                       bytes_remaining--;
+                       bytes_written++;
+               }
+               
+               str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
+               
+               field.device = chain_pos;
+               field.num_bits = 64;
+               field.out_value = last_dword;
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               jtag_add_dr_scan(1, &field, TAP_RTI);
+               
+               /* small delay before polling */
+               jtag_add_sleep(50);
+               
+               str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+               
+               do {
+                       field.device = chain_pos;
+                       field.num_bits = 8;
+                       field.out_value = NULL;
+                       field.out_mask = NULL;
+                       field.in_value = scanbuf;
+                       field.in_check_value = NULL;
+                       field.in_check_mask = NULL;
+                       field.in_handler = NULL;
+                       field.in_handler_priv = NULL;
+                       
+                       jtag_add_dr_scan(1, &field, -1);
+                       jtag_execute_queue();
+                       
+                       status = buf_get_u32(scanbuf, 0, 8);
+                       
+               } while(!(status & ISC_STATUS_BUSY));
+               
+               if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+                       return ERROR_FLASH_OPERATION_FAILED;
+               
+               //if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
+               //      return ERROR_FLASH_OPERATION_FAILED;
+       }
+
+       free(scanbuf);
+
+       str9xpec_isc_disable(bank);
+                               
+       return ERROR_OK;
+}
+
+int str9xpec_probe(struct flash_bank_s *bank)
+{
+       return ERROR_OK;
+}
+
+int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       scan_field_t field;
+       u8 *buffer = NULL;
+       u32 chain_pos;
+       u32 idcode;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+       if (argc < 1)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       chain_pos = str9xpec_info->chain_pos;
+       
+       buffer = calloc(CEIL(32, 8), 1);
+       
+       str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);
+       
+       field.device = chain_pos;
+       field.num_bits = 32;
+       field.out_value = NULL;
+       field.out_mask = NULL;
+       field.in_value = buffer;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_RTI);
+       jtag_execute_queue();
+       
+       idcode = buf_get_u32(buffer, 0, 32);
+       
+       command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);
+       
+       free(buffer);
+       
+       return ERROR_OK;
+}
+
+int str9xpec_erase_check(struct flash_bank_s *bank)
+{
+       return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
+}
+
+int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+       snprintf(buf, buf_size, "str9xpec flash driver info" );
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       u8 status;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec options_read <bank>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       status = str9xpec_read_config(bank);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       
+       /* boot bank */
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
+               command_print(cmd_ctx, "CS Map: bank1");
+       else
+               command_print(cmd_ctx, "CS Map: bank0");
+       
+       /* OTP lock */
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
+               command_print(cmd_ctx, "OTP Lock: OTP Locked");
+       else
+               command_print(cmd_ctx, "OTP Lock: OTP Unlocked");
+       
+       /* LVD Threshold */
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
+               command_print(cmd_ctx, "LVD Threshold: 2.7v");
+       else
+               command_print(cmd_ctx, "LVD Threshold: 2.4v");
+       
+       /* LVD reset warning */
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
+               command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");
+       else
+               command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");
+       
+       /* LVD reset select */
+       if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
+               command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");
+       else
+               command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");
+       
+       return ERROR_OK;
+}
+
+int str9xpec_write_options(struct flash_bank_s *bank)
+{
+       scan_field_t field;
+       u8 status;
+       u32 chain_pos;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       str9xpec_info = bank->driver_priv;
+       chain_pos = str9xpec_info->chain_pos;
+       
+       /* erase config options first */
+       status = str9xpec_erase_area( bank, 0xFE, 0xFE );
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return status; 
+       
+       if (!str9xpec_info->isc_enable) {
+               str9xpec_isc_enable( bank );
+       }
+       
+       if (!str9xpec_info->isc_enable) {
+               return ISC_STATUS_ERROR;
+       }
+       
+       /* according to data 64th bit has to be set */
+       buf_set_u32(str9xpec_info->options, 63, 1, 1);
+       
+       /* set option byte address */
+       str9xpec_set_address(bank, 0x50);
+       
+       /* execute ISC_PROGRAM command */
+       str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
+               
+       field.device = chain_pos;
+       field.num_bits = 64;
+       field.out_value = str9xpec_info->options;
+       field.out_mask = NULL;
+       field.in_value = NULL;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(1, &field, TAP_RTI);
+       
+       /* small delay before polling */
+       jtag_add_sleep(50);
+       
+       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+       
+       do {
+               field.device = chain_pos;
+               field.num_bits = 8;
+               field.out_value = NULL;
+               field.out_mask = NULL;
+               field.in_value = &status;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               jtag_add_dr_scan(1, &field, -1);
+               jtag_execute_queue();
+               
+       } while(!(status & ISC_STATUS_BUSY));
+       
+       str9xpec_isc_disable(bank);
+       
+       return status;
+}
+
+int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       u8 status;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec options_write <bank>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       status = str9xpec_write_options(bank);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       if (strcmp(args[1], "bank1") == 0)
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
+       }
+       else
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       if (strcmp(args[1], "2.7v") == 0)
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
+       }
+       else
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       if (strcmp(args[1], "vdd_vddq") == 0)
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
+       }
+       else
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       if (strcmp(args[1], "vdd_vddq") == 0)
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
+       }
+       else
+       {
+               buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u8 status;
+       flash_bank_t *bank;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec lock <bank>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       status = str9xpec_lock_device(bank);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u8 status;
+       flash_bank_t *bank;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec unlock <bank>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       status = str9xpec_unlock_device(bank);
+       
+       if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+               return ERROR_FLASH_OPERATION_FAILED;
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       u32 chain_pos;
+       jtag_device_t* dev0;
+       jtag_device_t* dev2;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec enable_turbo <bank>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       /* remove arm core from chain - enter turbo mode */
+       
+       str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);
+       jtag_execute_queue();
+       
+       /* modify scan chain - str9 core has been removed */
+       dev0 = jtag_get_device(chain_pos);
+       str9xpec_info->devarm = jtag_get_device(chain_pos+1);
+       dev2 = jtag_get_device(chain_pos+2);
+       dev0->next = dev2;
+       jtag_num_devices--;
+       
+       return ERROR_OK;
+}
+
+int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       flash_bank_t *bank;
+       u32 chain_pos;
+       jtag_device_t* dev0;
+       str9xpec_flash_controller_t *str9xpec_info = NULL;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "str9xpec disable_turbo <bank>");
+               return ERROR_OK;        
+       }
+       
+       bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+       if (!bank)
+       {
+               command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       str9xpec_info = bank->driver_priv;
+       
+       chain_pos = str9xpec_info->chain_pos;
+       
+       dev0 = jtag_get_device(chain_pos);
+       
+       /* exit turbo mode via TLR */
+       str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);
+       jtag_execute_queue();
+       
+       /* restore previous scan chain */
+       if( str9xpec_info->devarm ) {
+               dev0->next = str9xpec_info->devarm;
+               jtag_num_devices++;
+               str9xpec_info->devarm = NULL;
+       }
+       
+       return ERROR_OK;
+}
index f13a86c15da1e2f5928f1f1a589642c981612ff0..15cddcdc40d197650a8896d934f14b9c7a8e22d9 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\r
- *                                                                         *\r
- *   part of this file is taken from libcli (libcli.sourceforge.net)       *\r
- *   Copyright (C) David Parrish (david@dparrish.com)                      *\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
-\r
-#include "command.h"\r
-\r
-#include "log.h"\r
-#include "time_support.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <unistd.h>\r
-\r
-void command_print_help_line(command_context_t* context, struct command_s *command, int indent);\r
-\r
-int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int build_unique_lengths(command_context_t *context, command_t *commands)\r
-{\r
-       command_t *c, *p;\r
-\r
-       /* iterate through all commands */\r
-       for (c = commands; c; c = c->next)\r
-       {\r
-               /* find out how many characters are required to uniquely identify a command */\r
-               for (c->unique_len = 1; c->unique_len <= strlen(c->name); c->unique_len++)\r
-               {\r
-                       int foundmatch = 0;\r
-                       \r
-                       /* for every command, see if the current length is enough */\r
-                       for (p = commands; p; p = p->next)\r
-                       {\r
-                               /* ignore the command itself */\r
-                               if (c == p)\r
-                                       continue;\r
-                               \r
-                               /* compare commands up to the current length */\r
-                               if (strncmp(p->name, c->name, c->unique_len) == 0)\r
-                                       foundmatch++;\r
-                       }\r
-                       \r
-                       /* when none of the commands matched, we've found the minimum length required */\r
-                       if (!foundmatch)\r
-                               break;\r
-               }\r
-               \r
-               /* if the current command has children, build the unique lengths for them */\r
-               if (c->children)\r
-                       build_unique_lengths(context, c->children);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/* Avoid evaluating this each time we add a command. Reduces overhead from O(n^2) to O(n). \r
- * Makes a difference on ARM7 types machines and is not observable on GHz machines.\r
- */\r
-static int unique_length_dirty = 1; \r
-\r
-command_t* register_command(command_context_t *context, command_t *parent, char *name, int (*handler)(struct command_context_s *context, char* name, char** args, int argc), enum command_mode mode, char *help)\r
-{\r
-       command_t *c, *p;\r
-       unique_length_dirty = 1;\r
-       \r
-       if (!context || !name)\r
-               return NULL;\r
-                               \r
-       c = malloc(sizeof(command_t));\r
-       \r
-       c->name = strdup(name);\r
-       c->parent = parent;\r
-       c->children = NULL;\r
-       c->handler = handler;\r
-       c->mode = mode;\r
-       if (help)\r
-               c->help = strdup(help);\r
-       else\r
-               c->help = NULL;\r
-       c->unique_len = 0;\r
-       c->next = NULL;\r
-       \r
-       /* place command in tree */\r
-       if (parent)\r
-       {\r
-               if (parent->children)\r
-               {\r
-                       /* find last child */\r
-                       for (p = parent->children; p && p->next; p = p->next);\r
-                       if (p)\r
-                               p->next = c;\r
-               }\r
-               else\r
-               {\r
-                       parent->children = c;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               if (context->commands)\r
-               {\r
-                       /* find last command */\r
-                       for (p = context->commands; p && p->next; p = p->next);\r
-                       if (p)\r
-                               p->next = c;\r
-               }\r
-               else\r
-               {\r
-                       context->commands = c;\r
-               }\r
-       }\r
-       \r
-       return c;\r
-}\r
-\r
-int unregister_command(command_context_t *context, char *name)\r
-{\r
-       unique_length_dirty = 1;\r
-       \r
-       command_t *c, *p = NULL, *c2;\r
-       \r
-       if ((!context) || (!name))\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       \r
-       /* find command */\r
-       for (c = context->commands; c; c = c->next)\r
-       {\r
-               if (strcmp(name, c->name) == 0)\r
-               {\r
-                       /* unlink command */\r
-                       if (p)\r
-                       {\r
-                               p->next = c->next;\r
-                       }\r
-                       else\r
-                       {\r
-                               context->commands = c->next;\r
-                       }\r
-                       \r
-                       /* unregister children */\r
-                       if (c->children)\r
-                       {\r
-                               for (c2 = c->children; c2; c2 = c2->next)\r
-                               {\r
-                                       free(c2->name);\r
-                                       if (c2->help)\r
-                                               free(c2->help);\r
-                                       free(c2);\r
-                               }\r
-                       }\r
-                       \r
-                       /* delete command */\r
-                       free(c->name);\r
-                       if (c->help)\r
-                               free(c->help);\r
-                       free(c);\r
-               }\r
-               \r
-               /* remember the last command for unlinking */\r
-               p = c;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int parse_line(char *line, char *words[], int max_words)\r
-{\r
-       int nwords = 0;\r
-       char *p = line;\r
-       char *word_start = line;\r
-       int inquote = 0;\r
-\r
-       while (nwords < max_words - 1)\r
-       {\r
-               /* check if we reached\r
-                * a terminating NUL\r
-                * a matching closing quote character " or '\r
-                * we're inside a word but not a quote, and the current character is whitespace\r
-                */\r
-               if (!*p || *p == inquote || (word_start && !inquote && isspace(*p)))\r
-               {\r
-                       /* we're inside a word or quote, and reached its end*/\r
-                       if (word_start)\r
-                       {\r
-                               int len;\r
-                               char *word_end=p;\r
-                               \r
-                               /* This will handle extra whitespace within quotes */\r
-                               while (isspace(*word_start)&&(word_start<word_end))\r
-                                       word_start++;\r
-                               while (isspace(*(word_end-1))&&(word_start<word_end))\r
-                                       word_end--;\r
-                               len = word_end - word_start;\r
-                               \r
-                               if (len>0)\r
-                               {\r
-                                       /* copy the word */\r
-                                       memcpy(words[nwords] = malloc(len + 1), word_start, len);\r
-                                       /* add terminating NUL */\r
-                                       words[nwords++][len] = 0;\r
-                               }\r
-                       }\r
-                       /* we're done parsing the line */\r
-                       if (!*p)\r
-                               break;\r
-\r
-                       /* skip over trailing quote or whitespace*/\r
-                       if (inquote || isspace(*p))\r
-                               p++;\r
-                       while (isspace(*p))\r
-                               p++;\r
-                       \r
-                       inquote = 0;\r
-                       word_start = 0;\r
-               }\r
-               else if (*p == '"' || *p == '\'')\r
-               {\r
-                       /* we've reached the beginning of a quote */\r
-                       inquote = *p++;\r
-                       word_start = p;\r
-               }\r
-               else\r
-               {\r
-                       /* we've reached the beginning of a new word */\r
-                       if (!word_start)\r
-                               word_start = p;\r
-                       \r
-                       /* normal character, skip */\r
-                       p++;\r
-               }\r
-       }\r
-       \r
-       return nwords;\r
-}\r
-\r
-void command_print(command_context_t *context, char *format, ...)\r
-{\r
-       char *buffer = NULL;\r
-       int n, size = 0;\r
-       char *p;\r
-\r
-       /* process format string */\r
-       for (;;)\r
-       {\r
-               va_list ap;\r
-               va_start(ap, format);\r
-               if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)\r
-               {\r
-                       /* increase buffer until it fits the whole string */\r
-                       if (!(p = realloc(buffer, size += 4096)))\r
-                       {\r
-                               /* gotta free up */\r
-                               if (buffer)\r
-                                       free(buffer);\r
-                               va_end(ap);\r
-                               return;\r
-                       }\r
-       \r
-                       buffer = p;\r
-                       \r
-                       va_end(ap);\r
-                       continue;\r
-               }\r
-               va_end(ap);\r
-               break;\r
-       }\r
-       \r
-       /* vsnprintf failed */\r
-       if (n < 0)\r
-       {\r
-               if (buffer)\r
-                       free(buffer);\r
-               return;\r
-       }\r
-\r
-       p = buffer;\r
-       \r
-       /* process lines in buffer */\r
-       do {\r
-               char *next = strchr(p, '\n');\r
-               \r
-               if (next)\r
-                       *next++ = 0;\r
-\r
-               if (context->output_handler)\r
-                       context->output_handler(context, p);\r
-\r
-               p = next;\r
-       } while (p);\r
-       \r
-       if (buffer)\r
-               free(buffer);\r
-}\r
-\r
-int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word)\r
-{\r
-       command_t *c;\r
-       \r
-       if (unique_length_dirty)\r
-       {\r
-               unique_length_dirty = 0;\r
-               /* update unique lengths */\r
-               build_unique_lengths(context, context->commands);\r
-       }\r
-       \r
-       for (c = commands; c; c = c->next)\r
-       {\r
-               if (strncasecmp(c->name, words[start_word], c->unique_len))\r
-                       continue;\r
-\r
-               if (strncasecmp(c->name, words[start_word], strlen(words[start_word])))\r
-                       continue;\r
-               \r
-               if ((context->mode == COMMAND_CONFIG) || (c->mode == COMMAND_ANY) || (c->mode == context->mode) )\r
-               {\r
-                       if (!c->children)\r
-                       {\r
-                               if (!c->handler)\r
-                               {\r
-                                       command_print(context, "No handler for command");\r
-                                       break;\r
-                               }\r
-                               else\r
-                               {\r
-                                       int retval = c->handler(context, c->name, words + start_word + 1, num_words - start_word - 1);\r
-                                       if (retval == ERROR_COMMAND_SYNTAX_ERROR)\r
-                                       {\r
-                                               command_print(context, "Syntax error:");\r
-                                               command_print_help_line(context, c, 0);\r
-                                       }\r
-                                       return retval; \r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               if (start_word == num_words - 1)\r
-                               {\r
-                                       command_print(context, "Incomplete command");\r
-                                       break;\r
-                               }\r
-                               return find_and_run_command(context, c->children, words, num_words, start_word + 1);\r
-                       }\r
-               }\r
-       }\r
-       \r
-       command_print(context, "Command %s not found", words[start_word]);\r
-       return ERROR_OK;\r
-}\r
-\r
-int command_run_line(command_context_t *context, char *line)\r
-{\r
-       int nwords;\r
-       char *words[128] = {0};\r
-       int retval;\r
-       int i;\r
-       \r
-       if ((!context) || (!line))\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       \r
-       /* skip preceding whitespace */\r
-       while (isspace(*line))\r
-               line++;\r
-       \r
-       /* empty line, ignore */\r
-       if (!*line)\r
-               return ERROR_OK;\r
-       \r
-       /* ignore comments */\r
-       if (*line && (line[0] == '#'))\r
-               return ERROR_OK;\r
-       \r
-       if (context->echo)\r
-       {\r
-               command_print(context, "%s", line);\r
-       }\r
-\r
-       nwords = parse_line(line, words, sizeof(words) / sizeof(words[0]));\r
-       \r
-       if (nwords > 0)\r
-               retval = find_and_run_command(context, context->commands, words, nwords, 0);\r
-       else\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       \r
-       for (i = 0; i < nwords; i++)\r
-               free(words[i]);\r
-       \r
-       return retval;\r
-}\r
-\r
-int command_run_file(command_context_t *context, FILE *file, enum command_mode mode)\r
-{\r
-       int retval = ERROR_OK;\r
-       int old_command_mode;\r
-       char *buffer=malloc(4096);\r
-       if (buffer==NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-       \r
-       old_command_mode = context->mode;\r
-       context->mode = mode;\r
-       \r
-       while (fgets(buffer, 4096, file))\r
-       {\r
-               char *p;\r
-               char *cmd, *end;\r
-               \r
-               /* stop processing line after a comment (#, !) or a LF, CR were encountered */\r
-               if ((p = strpbrk(buffer, "#!\r\n")))\r
-                       *p = 0;\r
-\r
-               /* skip over leading whitespace */\r
-               cmd = buffer;\r
-               while (isspace(*cmd))\r
-                       cmd++;\r
-\r
-               /* empty (all whitespace) line? */\r
-               if (!*cmd)\r
-                       continue;\r
-               \r
-               /* search the end of the current line, ignore trailing whitespace */\r
-               for (p = end = cmd; *p; p++)\r
-                       if (!isspace(*p))\r
-                               end = p;\r
-               \r
-               /* terminate end */\r
-               *++end = 0;\r
-               if (strcasecmp(cmd, "quit") == 0)\r
-                       break;\r
-\r
-               /* run line */\r
-               if ((retval = command_run_line(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)\r
-                       break;\r
-       }\r
-       \r
-       context->mode = old_command_mode;\r
-\r
-       \r
-       free(buffer);\r
-       \r
-       return retval;\r
-}\r
-\r
-void command_print_help_line(command_context_t* context, struct command_s *command, int indent)\r
-{\r
-       command_t *c;\r
-       char indents[32] = {0};\r
-       char *help = "no help available";\r
-       char name_buf[64];\r
-       int i;\r
-       \r
-       for (i = 0; i < indent; i+=2)\r
-       {\r
-               indents[i*2] = ' ';\r
-               indents[i*2+1] = '-';\r
-       }\r
-       indents[i*2] = 0;\r
-       \r
-       if (command->help)\r
-               help = command->help;\r
-               \r
-       snprintf(name_buf, 64, command->name);\r
-       strncat(name_buf, indents, 64);\r
-       command_print(context, "%20s\t%s", name_buf, help);\r
-       \r
-       if (command->children)\r
-       {\r
-               for (c = command->children; c; c = c->next)\r
-               {\r
-                       command_print_help_line(context, c, indent + 1);\r
-               }\r
-       }\r
-}\r
-\r
-int command_print_help(command_context_t* context, char* name, char** args, int argc)\r
-{\r
-       command_t *c;\r
-\r
-       for (c = context->commands; c; c = c->next)\r
-       {\r
-               if (argc == 1)\r
-               {\r
-                        if (strncasecmp(c->name, args[0], c->unique_len))\r
-                                continue;\r
-\r
-                        if (strncasecmp(c->name, args[0], strlen(args[0])))\r
-                                continue;\r
-               } \r
-\r
-               command_print_help_line(context, c, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, char* line), void *priv)\r
-{\r
-       context->output_handler = output_handler;\r
-       context->output_handler_priv = priv;\r
-}\r
-\r
-command_context_t* copy_command_context(command_context_t* context)\r
-{\r
-       command_context_t* copy_context = malloc(sizeof(command_context_t));\r
-\r
-       *copy_context = *context;\r
-       \r
-       return copy_context;\r
-}\r
-\r
-int command_done(command_context_t *context)\r
-{\r
-       free(context);\r
-       context = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-command_context_t* command_init()\r
-{\r
-       command_context_t* context = malloc(sizeof(command_context_t));\r
-       \r
-       context->mode = COMMAND_EXEC;\r
-       context->commands = NULL;\r
-       context->current_target = 0;\r
-       context->echo = 0;\r
-       context->output_handler = NULL;\r
-       context->output_handler_priv = NULL;\r
-       \r
-       register_command(context, NULL, "help", command_print_help,\r
-                                        COMMAND_EXEC, "display this help");\r
-       \r
-       register_command(context, NULL, "sleep", handle_sleep_command,\r
-                                        COMMAND_ANY, "sleep for <n> milliseconds");\r
-       \r
-       register_command(context, NULL, "time", handle_time_command,\r
-                                        COMMAND_ANY, "time <cmd + args> - execute <cmd + args> and print time it took");\r
-       \r
-       return context;\r
-}\r
-\r
-/* sleep command sleeps for <n> miliseconds\r
- * this is useful in target startup scripts\r
- */\r
-int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       unsigned long duration = 0;\r
-       \r
-       if (argc == 1)\r
-       {\r
-               duration = strtoul(args[0], NULL, 0);\r
-               usleep(duration * 1000);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc<1)\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       \r
-       duration_t duration;\r
-       char *duration_text;\r
-       int retval;\r
-       \r
-       duration_start_measure(&duration);\r
-       \r
-       retval = find_and_run_command(cmd_ctx, cmd_ctx->commands, args, argc, 0);\r
-       \r
-       duration_stop_measure(&duration, &duration_text);\r
-       \r
-       float t=duration.duration.tv_sec;\r
-       t+=((float)duration.duration.tv_usec / 1000000.0);\r
-       command_print(cmd_ctx, "%s took %fs", args[0], t);\r
-       \r
-       free(duration_text);\r
-\r
-       return retval;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   part of this file is taken from libcli (libcli.sourceforge.net)       *
+ *   Copyright (C) David Parrish (david@dparrish.com)                      *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "command.h"
+
+#include "log.h"
+#include "time_support.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void command_print_help_line(command_context_t* context, struct command_s *command, int indent);
+
+int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int build_unique_lengths(command_context_t *context, command_t *commands)
+{
+       command_t *c, *p;
+
+       /* iterate through all commands */
+       for (c = commands; c; c = c->next)
+       {
+               /* find out how many characters are required to uniquely identify a command */
+               for (c->unique_len = 1; c->unique_len <= strlen(c->name); c->unique_len++)
+               {
+                       int foundmatch = 0;
+                       
+                       /* for every command, see if the current length is enough */
+                       for (p = commands; p; p = p->next)
+                       {
+                               /* ignore the command itself */
+                               if (c == p)
+                                       continue;
+                               
+                               /* compare commands up to the current length */
+                               if (strncmp(p->name, c->name, c->unique_len) == 0)
+                                       foundmatch++;
+                       }
+                       
+                       /* when none of the commands matched, we've found the minimum length required */
+                       if (!foundmatch)
+                               break;
+               }
+               
+               /* if the current command has children, build the unique lengths for them */
+               if (c->children)
+                       build_unique_lengths(context, c->children);
+       }
+       
+       return ERROR_OK;
+}
+
+/* Avoid evaluating this each time we add a command. Reduces overhead from O(n^2) to O(n). 
+ * Makes a difference on ARM7 types machines and is not observable on GHz machines.
+ */
+static int unique_length_dirty = 1; 
+
+command_t* register_command(command_context_t *context, command_t *parent, char *name, int (*handler)(struct command_context_s *context, char* name, char** args, int argc), enum command_mode mode, char *help)
+{
+       command_t *c, *p;
+       unique_length_dirty = 1;
+       
+       if (!context || !name)
+               return NULL;
+                               
+       c = malloc(sizeof(command_t));
+       
+       c->name = strdup(name);
+       c->parent = parent;
+       c->children = NULL;
+       c->handler = handler;
+       c->mode = mode;
+       if (help)
+               c->help = strdup(help);
+       else
+               c->help = NULL;
+       c->unique_len = 0;
+       c->next = NULL;
+       
+       /* place command in tree */
+       if (parent)
+       {
+               if (parent->children)
+               {
+                       /* find last child */
+                       for (p = parent->children; p && p->next; p = p->next);
+                       if (p)
+                               p->next = c;
+               }
+               else
+               {
+                       parent->children = c;
+               }
+       }
+       else
+       {
+               if (context->commands)
+               {
+                       /* find last command */
+                       for (p = context->commands; p && p->next; p = p->next);
+                       if (p)
+                               p->next = c;
+               }
+               else
+               {
+                       context->commands = c;
+               }
+       }
+       
+       return c;
+}
+
+int unregister_command(command_context_t *context, char *name)
+{
+       unique_length_dirty = 1;
+       
+       command_t *c, *p = NULL, *c2;
+       
+       if ((!context) || (!name))
+               return ERROR_INVALID_ARGUMENTS;
+       
+       /* find command */
+       for (c = context->commands; c; c = c->next)
+       {
+               if (strcmp(name, c->name) == 0)
+               {
+                       /* unlink command */
+                       if (p)
+                       {
+                               p->next = c->next;
+                       }
+                       else
+                       {
+                               context->commands = c->next;
+                       }
+                       
+                       /* unregister children */
+                       if (c->children)
+                       {
+                               for (c2 = c->children; c2; c2 = c2->next)
+                               {
+                                       free(c2->name);
+                                       if (c2->help)
+                                               free(c2->help);
+                                       free(c2);
+                               }
+                       }
+                       
+                       /* delete command */
+                       free(c->name);
+                       if (c->help)
+                               free(c->help);
+                       free(c);
+               }
+               
+               /* remember the last command for unlinking */
+               p = c;
+       }
+       
+       return ERROR_OK;
+}
+
+int parse_line(char *line, char *words[], int max_words)
+{
+       int nwords = 0;
+       char *p = line;
+       char *word_start = line;
+       int inquote = 0;
+
+       while (nwords < max_words - 1)
+       {
+               /* check if we reached
+                * a terminating NUL
+                * a matching closing quote character " or '
+                * we're inside a word but not a quote, and the current character is whitespace
+                */
+               if (!*p || *p == inquote || (word_start && !inquote && isspace(*p)))
+               {
+                       /* we're inside a word or quote, and reached its end*/
+                       if (word_start)
+                       {
+                               int len;
+                               char *word_end=p;
+                               
+                               /* This will handle extra whitespace within quotes */
+                               while (isspace(*word_start)&&(word_start<word_end))
+                                       word_start++;
+                               while (isspace(*(word_end-1))&&(word_start<word_end))
+                                       word_end--;
+                               len = word_end - word_start;
+                               
+                               if (len>0)
+                               {
+                                       /* copy the word */
+                                       memcpy(words[nwords] = malloc(len + 1), word_start, len);
+                                       /* add terminating NUL */
+                                       words[nwords++][len] = 0;
+                               }
+                       }
+                       /* we're done parsing the line */
+                       if (!*p)
+                               break;
+
+                       /* skip over trailing quote or whitespace*/
+                       if (inquote || isspace(*p))
+                               p++;
+                       while (isspace(*p))
+                               p++;
+                       
+                       inquote = 0;
+                       word_start = 0;
+               }
+               else if (*p == '"' || *p == '\'')
+               {
+                       /* we've reached the beginning of a quote */
+                       inquote = *p++;
+                       word_start = p;
+               }
+               else
+               {
+                       /* we've reached the beginning of a new word */
+                       if (!word_start)
+                               word_start = p;
+                       
+                       /* normal character, skip */
+                       p++;
+               }
+       }
+       
+       return nwords;
+}
+
+void command_print(command_context_t *context, char *format, ...)
+{
+       char *buffer = NULL;
+       int n, size = 0;
+       char *p;
+
+       /* process format string */
+       for (;;)
+       {
+               va_list ap;
+               va_start(ap, format);
+               if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)
+               {
+                       /* increase buffer until it fits the whole string */
+                       if (!(p = realloc(buffer, size += 4096)))
+                       {
+                               /* gotta free up */
+                               if (buffer)
+                                       free(buffer);
+                               va_end(ap);
+                               return;
+                       }
+       
+                       buffer = p;
+                       
+                       va_end(ap);
+                       continue;
+               }
+               va_end(ap);
+               break;
+       }
+       
+       /* vsnprintf failed */
+       if (n < 0)
+       {
+               if (buffer)
+                       free(buffer);
+               return;
+       }
+
+       p = buffer;
+       
+       /* process lines in buffer */
+       do {
+               char *next = strchr(p, '\n');
+               
+               if (next)
+                       *next++ = 0;
+
+               if (context->output_handler)
+                       context->output_handler(context, p);
+
+               p = next;
+       } while (p);
+       
+       if (buffer)
+               free(buffer);
+}
+
+int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word)
+{
+       command_t *c;
+       
+       if (unique_length_dirty)
+       {
+               unique_length_dirty = 0;
+               /* update unique lengths */
+               build_unique_lengths(context, context->commands);
+       }
+       
+       for (c = commands; c; c = c->next)
+       {
+               if (strncasecmp(c->name, words[start_word], c->unique_len))
+                       continue;
+
+               if (strncasecmp(c->name, words[start_word], strlen(words[start_word])))
+                       continue;
+               
+               if ((context->mode == COMMAND_CONFIG) || (c->mode == COMMAND_ANY) || (c->mode == context->mode) )
+               {
+                       if (!c->children)
+                       {
+                               if (!c->handler)
+                               {
+                                       command_print(context, "No handler for command");
+                                       break;
+                               }
+                               else
+                               {
+                                       int retval = c->handler(context, c->name, words + start_word + 1, num_words - start_word - 1);
+                                       if (retval == ERROR_COMMAND_SYNTAX_ERROR)
+                                       {
+                                               command_print(context, "Syntax error:");
+                                               command_print_help_line(context, c, 0);
+                                       }
+                                       return retval; 
+                               }
+                       }
+                       else
+                       {
+                               if (start_word == num_words - 1)
+                               {
+                                       command_print(context, "Incomplete command");
+                                       break;
+                               }
+                               return find_and_run_command(context, c->children, words, num_words, start_word + 1);
+                       }
+               }
+       }
+       
+       command_print(context, "Command %s not found", words[start_word]);
+       return ERROR_OK;
+}
+
+int command_run_line(command_context_t *context, char *line)
+{
+       int nwords;
+       char *words[128] = {0};
+       int retval;
+       int i;
+       
+       if ((!context) || (!line))
+               return ERROR_INVALID_ARGUMENTS;
+       
+       /* skip preceding whitespace */
+       while (isspace(*line))
+               line++;
+       
+       /* empty line, ignore */
+       if (!*line)
+               return ERROR_OK;
+       
+       /* ignore comments */
+       if (*line && (line[0] == '#'))
+               return ERROR_OK;
+       
+       if (context->echo)
+       {
+               command_print(context, "%s", line);
+       }
+
+       nwords = parse_line(line, words, sizeof(words) / sizeof(words[0]));
+       
+       if (nwords > 0)
+               retval = find_and_run_command(context, context->commands, words, nwords, 0);
+       else
+               return ERROR_INVALID_ARGUMENTS;
+       
+       for (i = 0; i < nwords; i++)
+               free(words[i]);
+       
+       return retval;
+}
+
+int command_run_file(command_context_t *context, FILE *file, enum command_mode mode)
+{
+       int retval = ERROR_OK;
+       int old_command_mode;
+       char *buffer=malloc(4096);
+       if (buffer==NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       
+       old_command_mode = context->mode;
+       context->mode = mode;
+       
+       while (fgets(buffer, 4096, file))
+       {
+               char *p;
+               char *cmd, *end;
+               
+               /* stop processing line after a comment (#, !) or a LF, CR were encountered */
+               if ((p = strpbrk(buffer, "#!\r\n")))
+                       *p = 0;
+
+               /* skip over leading whitespace */
+               cmd = buffer;
+               while (isspace(*cmd))
+                       cmd++;
+
+               /* empty (all whitespace) line? */
+               if (!*cmd)
+                       continue;
+               
+               /* search the end of the current line, ignore trailing whitespace */
+               for (p = end = cmd; *p; p++)
+                       if (!isspace(*p))
+                               end = p;
+               
+               /* terminate end */
+               *++end = 0;
+               if (strcasecmp(cmd, "quit") == 0)
+                       break;
+
+               /* run line */
+               if ((retval = command_run_line(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)
+                       break;
+       }
+       
+       context->mode = old_command_mode;
+
+       
+       free(buffer);
+       
+       return retval;
+}
+
+void command_print_help_line(command_context_t* context, struct command_s *command, int indent)
+{
+       command_t *c;
+       char indents[32] = {0};
+       char *help = "no help available";
+       char name_buf[64];
+       int i;
+       
+       for (i = 0; i < indent; i+=2)
+       {
+               indents[i*2] = ' ';
+               indents[i*2+1] = '-';
+       }
+       indents[i*2] = 0;
+       
+       if (command->help)
+               help = command->help;
+               
+       snprintf(name_buf, 64, command->name);
+       strncat(name_buf, indents, 64);
+       command_print(context, "%20s\t%s", name_buf, help);
+       
+       if (command->children)
+       {
+               for (c = command->children; c; c = c->next)
+               {
+                       command_print_help_line(context, c, indent + 1);
+               }
+       }
+}
+
+int command_print_help(command_context_t* context, char* name, char** args, int argc)
+{
+       command_t *c;
+
+       for (c = context->commands; c; c = c->next)
+       {
+               if (argc == 1)
+               {
+                        if (strncasecmp(c->name, args[0], c->unique_len))
+                                continue;
+
+                        if (strncasecmp(c->name, args[0], strlen(args[0])))
+                                continue;
+               } 
+
+               command_print_help_line(context, c, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, char* line), void *priv)
+{
+       context->output_handler = output_handler;
+       context->output_handler_priv = priv;
+}
+
+command_context_t* copy_command_context(command_context_t* context)
+{
+       command_context_t* copy_context = malloc(sizeof(command_context_t));
+
+       *copy_context = *context;
+       
+       return copy_context;
+}
+
+int command_done(command_context_t *context)
+{
+       free(context);
+       context = NULL;
+       
+       return ERROR_OK;
+}
+
+command_context_t* command_init()
+{
+       command_context_t* context = malloc(sizeof(command_context_t));
+       
+       context->mode = COMMAND_EXEC;
+       context->commands = NULL;
+       context->current_target = 0;
+       context->echo = 0;
+       context->output_handler = NULL;
+       context->output_handler_priv = NULL;
+       
+       register_command(context, NULL, "help", command_print_help,
+                                        COMMAND_EXEC, "display this help");
+       
+       register_command(context, NULL, "sleep", handle_sleep_command,
+                                        COMMAND_ANY, "sleep for <n> milliseconds");
+       
+       register_command(context, NULL, "time", handle_time_command,
+                                        COMMAND_ANY, "time <cmd + args> - execute <cmd + args> and print time it took");
+       
+       return context;
+}
+
+/* sleep command sleeps for <n> miliseconds
+ * this is useful in target startup scripts
+ */
+int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       unsigned long duration = 0;
+       
+       if (argc == 1)
+       {
+               duration = strtoul(args[0], NULL, 0);
+               usleep(duration * 1000);
+       }
+
+       return ERROR_OK;
+}
+
+int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc<1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       
+       duration_t duration;
+       char *duration_text;
+       int retval;
+       
+       duration_start_measure(&duration);
+       
+       retval = find_and_run_command(cmd_ctx, cmd_ctx->commands, args, argc, 0);
+       
+       duration_stop_measure(&duration, &duration_text);
+       
+       float t=duration.duration.tv_sec;
+       t+=((float)duration.duration.tv_usec / 1000000.0);
+       command_print(cmd_ctx, "%s took %fs", args[0], t);
+       
+       free(duration_text);
+
+       return retval;
+}
index 1bed1e06ee3e29f9a386202a78726d3e458dd76f..9b9c18160b87ebdbdc8c0abfc9bc0db4c14f374b 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2004, 2005 by Dominic Rath                              *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "types.h"\r
-#include "command.h"\r
-#include "configuration.h"\r
-#include "log.h"\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-static size_t num_config_files;\r
-static char** config_file_names;\r
-\r
-static size_t num_script_dirs;\r
-static char** script_search_dirs;\r
-\r
-\r
-void add_script_search_dir (const char *dir)\r
-{\r
-       num_script_dirs++;\r
-       script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));\r
-\r
-       script_search_dirs[num_script_dirs-1] = strdup(dir);\r
-       script_search_dirs[num_script_dirs] = NULL;\r
-}\r
-\r
-void add_config_file_name (const char *cfg)\r
-{\r
-       num_config_files++;\r
-       config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));\r
-\r
-       config_file_names[num_config_files-1] = strdup(cfg);\r
-       config_file_names[num_config_files] = NULL;\r
-}\r
-\r
-FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)\r
-{\r
-       FILE *fp = NULL;\r
-       char **search_dirs = script_search_dirs;\r
-       char *dir;\r
-       char full_path[1024];\r
-\r
-       /* Check absolute and relative to current working dir first.\r
-        * This keeps full_path reporting belowing working. */\r
-       snprintf(full_path, 1024, "%s", file);\r
-       fp = fopen(full_path, mode);\r
-\r
-       while (!fp)\r
-       {\r
-               dir = *search_dirs++;\r
-\r
-               if (!dir)\r
-                       break;\r
-\r
-               snprintf(full_path, 1024, "%s/%s", dir, file);\r
-               fp = fopen(full_path, mode);\r
-       }\r
-\r
-       if (fp)\r
-               command_print(cmd_ctx, "opened %s", full_path);\r
-\r
-       return fp;\r
-}\r
-\r
-int parse_config_file(struct command_context_s *cmd_ctx)\r
-{\r
-       char **cfg;\r
-       FILE *config_file;\r
-\r
-       if (!config_file_names)\r
-               add_config_file_name ("script openocd.cfg");\r
-\r
-       cfg = config_file_names;\r
-\r
-       while (*cfg)\r
-       {\r
-               command_run_line(cmd_ctx, *cfg);\r
-               cfg++;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2004, 2005 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "types.h"
+#include "command.h"
+#include "configuration.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static size_t num_config_files;
+static char** config_file_names;
+
+static size_t num_script_dirs;
+static char** script_search_dirs;
+
+
+void add_script_search_dir (const char *dir)
+{
+       num_script_dirs++;
+       script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));
+
+       script_search_dirs[num_script_dirs-1] = strdup(dir);
+       script_search_dirs[num_script_dirs] = NULL;
+}
+
+void add_config_file_name (const char *cfg)
+{
+       num_config_files++;
+       config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));
+
+       config_file_names[num_config_files-1] = strdup(cfg);
+       config_file_names[num_config_files] = NULL;
+}
+
+FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)
+{
+       FILE *fp = NULL;
+       char **search_dirs = script_search_dirs;
+       char *dir;
+       char full_path[1024];
+
+       /* Check absolute and relative to current working dir first.
+        * This keeps full_path reporting belowing working. */
+       snprintf(full_path, 1024, "%s", file);
+       fp = fopen(full_path, mode);
+
+       while (!fp)
+       {
+               dir = *search_dirs++;
+
+               if (!dir)
+                       break;
+
+               snprintf(full_path, 1024, "%s/%s", dir, file);
+               fp = fopen(full_path, mode);
+       }
+
+       if (fp)
+               command_print(cmd_ctx, "opened %s", full_path);
+
+       return fp;
+}
+
+int parse_config_file(struct command_context_s *cmd_ctx)
+{
+       char **cfg;
+       FILE *config_file;
+
+       if (!config_file_names)
+               add_config_file_name ("script openocd.cfg");
+
+       cfg = config_file_names;
+
+       while (*cfg)
+       {
+               command_run_line(cmd_ctx, *cfg);
+               cfg++;
+       }
+
+       return ERROR_OK;
+}
index 90077ea3ea1d2f046c740573326ed7991c59bdd3..861e4b376859823413491f31b1ff62ffc2c2ceff 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "log.h"\r
-#include "configuration.h"\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <stdarg.h>\r
-#include <time.h>\r
-\r
-int debug_level = -1;\r
-\r
-static FILE* log_output;\r
-static log_callback_t *log_callbacks = NULL;\r
-\r
-static time_t start;\r
-\r
-static char *log_strings[5] =\r
-{\r
-       "User:   ",\r
-       "Error:  ",\r
-       "Warning:",\r
-       "Info:   ",\r
-       "Debug:  "\r
-};\r
-\r
-void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)\r
-{\r
-       static int count = 0;\r
-       count++;\r
-       va_list args;\r
-       char buffer[512];\r
-       log_callback_t *cb;\r
-\r
-       if (level > debug_level)\r
-               return;\r
-\r
-       va_start(args, format);\r
-       vsnprintf(buffer, 512, format, args);\r
-       va_end(args);\r
-\r
-       if (level == LOG_OUTPUT)\r
-       {\r
-               /* do not prepend any headers, just print out what we were given and return */\r
-               fputs(buffer, log_output);\r
-               fflush(log_output);\r
-               return;\r
-       }\r
-\r
-       char *f = strrchr(file, '/');\r
-       if (f != NULL)\r
-               file = f + 1;\r
-\r
-       if (debug_level >= LOG_DEBUG)\r
-       {\r
-               /* print with count and time information */\r
-               time_t t=time(NULL)-start;\r
-               fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);\r
-       }\r
-       else\r
-       {\r
-               /* do not print count and time */\r
-               fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer);\r
-       }\r
-\r
-       fflush(log_output);\r
-       \r
-       /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */\r
-       if (level <= LOG_INFO)\r
-       {\r
-               for (cb = log_callbacks; cb; cb = cb->next)\r
-               {\r
-                       va_start(args, format);\r
-                       cb->fn(cb->priv, file, line, function, format, args);\r
-                       va_end(args);\r
-               }\r
-       }\r
-}\r
-\r
-/* change the current debug level on the fly\r
- * 0: only ERRORS\r
- * 1: + WARNINGS\r
- * 2: + INFORMATIONAL MSGS\r
- * 3: + DEBUG MSGS\r
- */\r
-int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 0)\r
-               command_print(cmd_ctx, "debug_level: %i", debug_level);\r
-\r
-       if (argc > 0)\r
-               debug_level = strtoul(args[0], NULL, 0);\r
-\r
-       if (debug_level < 0)\r
-               debug_level = 0;\r
-\r
-       if (debug_level > 3)\r
-               debug_level = 3;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               FILE* file = fopen(args[0], "w");\r
-               \r
-               if (file)\r
-               {\r
-                       log_output = file;\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int log_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       start = time(NULL);\r
-       register_command(cmd_ctx, NULL, "log_output", handle_log_output_command,\r
-               COMMAND_ANY, "redirect logging to <file> (default: stderr)");\r
-       register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command,\r
-               COMMAND_ANY, "adjust debug level <0-3>");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int log_init(struct command_context_s *cmd_ctx)\r
-{\r
-       /* set defaults for daemon configuration, if not set by cmdline or cfgfile */\r
-       if (debug_level == -1)\r
-               debug_level = LOG_INFO;\r
-       \r
-       if (log_output == NULL)\r
-       {\r
-               log_output = stderr;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-       \r
-int set_log_output(struct command_context_s *cmd_ctx, FILE *output)\r
-{\r
-       log_output = output;\r
-       return ERROR_OK;\r
-}\r
-\r
-/* add/remove log callback handler */\r
-int log_add_callback(log_callback_fn fn, void *priv)\r
-{\r
-       log_callback_t *cb;\r
-\r
-       /* prevent the same callback to be registered more than once, just for sure */\r
-       for (cb = log_callbacks; cb; cb = cb->next)\r
-       {\r
-               if (cb->fn == fn && cb->priv == priv)\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-\r
-       /* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */\r
-       if ((cb = malloc(sizeof(log_callback_t))) == NULL)\r
-               return ERROR_BUF_TOO_SMALL;\r
-\r
-       /* add item to the beginning of the linked list */\r
-       cb->fn = fn;\r
-       cb->priv = priv;\r
-       cb->next = log_callbacks;\r
-       log_callbacks = cb;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int log_remove_callback(log_callback_fn fn, void *priv)\r
-{\r
-       log_callback_t *cb, **p;\r
-\r
-       for (p = &log_callbacks; cb = *p; p = &(*p)->next)\r
-       {\r
-           if (cb->fn == fn && cb->priv == priv)\r
-           {\r
-               *p = cb->next;\r
-                       free(cb);\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-\r
-       /* no such item */\r
-       return ERROR_INVALID_ARGUMENTS;\r
-}\r
-\r
-/* return allocated string w/printf() result */\r
-char *alloc_printf(const char *fmt, va_list ap)\r
-{\r
-       char *string = NULL;\r
-       \r
-       /* start by 0 to exercise all the code paths. Need minimum 2 bytes to\r
-        * fit 1 char and 0 terminator. */\r
-       int size = 0;\r
-       int first = 1;\r
-       for (;;)\r
-       {\r
-               if ((string == NULL) || (!first))\r
-               {\r
-                       size = size * 2 + 2;\r
-                       char *t = string;\r
-                       string = realloc(string, size);\r
-                       if (string == NULL)\r
-                       {\r
-                               if (t != NULL)\r
-                                       free(t);\r
-                               return NULL;\r
-                       }\r
-               }\r
-       \r
-           int ret;\r
-           ret = vsnprintf(string, size, fmt, ap);\r
-           /* NB! The result of the vsnprintf() might be an *EMPTY* string! */\r
-           if ((ret >= 0) && ((ret + 1) < size))\r
-           {\r
-               return string;\r
-           }\r
-           /* there was just enough or not enough space, allocate more. */\r
-           first = 0;\r
-       }\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "log.h"
+#include "configuration.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+int debug_level = -1;
+
+static FILE* log_output;
+static log_callback_t *log_callbacks = NULL;
+
+static time_t start;
+
+static char *log_strings[5] =
+{
+       "User:   ",
+       "Error:  ",
+       "Warning:",
+       "Info:   ",
+       "Debug:  "
+};
+
+void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
+{
+       static int count = 0;
+       count++;
+       va_list args;
+       char buffer[512];
+       log_callback_t *cb;
+
+       if (level > debug_level)
+               return;
+
+       va_start(args, format);
+       vsnprintf(buffer, 512, format, args);
+       va_end(args);
+
+       if (level == LOG_OUTPUT)
+       {
+               /* do not prepend any headers, just print out what we were given and return */
+               fputs(buffer, log_output);
+               fflush(log_output);
+               return;
+       }
+
+       char *f = strrchr(file, '/');
+       if (f != NULL)
+               file = f + 1;
+
+       if (debug_level >= LOG_DEBUG)
+       {
+               /* print with count and time information */
+               time_t t=time(NULL)-start;
+               fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
+       }
+       else
+       {
+               /* do not print count and time */
+               fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer);
+       }
+
+       fflush(log_output);
+       
+       /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */
+       if (level <= LOG_INFO)
+       {
+               for (cb = log_callbacks; cb; cb = cb->next)
+               {
+                       va_start(args, format);
+                       cb->fn(cb->priv, file, line, function, format, args);
+                       va_end(args);
+               }
+       }
+}
+
+/* change the current debug level on the fly
+ * 0: only ERRORS
+ * 1: + WARNINGS
+ * 2: + INFORMATIONAL MSGS
+ * 3: + DEBUG MSGS
+ */
+int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               command_print(cmd_ctx, "debug_level: %i", debug_level);
+
+       if (argc > 0)
+               debug_level = strtoul(args[0], NULL, 0);
+
+       if (debug_level < 0)
+               debug_level = 0;
+
+       if (debug_level > 3)
+               debug_level = 3;
+
+       return ERROR_OK;
+}
+
+int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               FILE* file = fopen(args[0], "w");
+               
+               if (file)
+               {
+                       log_output = file;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int log_register_commands(struct command_context_s *cmd_ctx)
+{
+       start = time(NULL);
+       register_command(cmd_ctx, NULL, "log_output", handle_log_output_command,
+               COMMAND_ANY, "redirect logging to <file> (default: stderr)");
+       register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command,
+               COMMAND_ANY, "adjust debug level <0-3>");
+
+       return ERROR_OK;
+}
+
+int log_init(struct command_context_s *cmd_ctx)
+{
+       /* set defaults for daemon configuration, if not set by cmdline or cfgfile */
+       if (debug_level == -1)
+               debug_level = LOG_INFO;
+       
+       if (log_output == NULL)
+       {
+               log_output = stderr;
+       }
+       
+       return ERROR_OK;
+}
+       
+int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
+{
+       log_output = output;
+       return ERROR_OK;
+}
+
+/* add/remove log callback handler */
+int log_add_callback(log_callback_fn fn, void *priv)
+{
+       log_callback_t *cb;
+
+       /* prevent the same callback to be registered more than once, just for sure */
+       for (cb = log_callbacks; cb; cb = cb->next)
+       {
+               if (cb->fn == fn && cb->priv == priv)
+                       return ERROR_INVALID_ARGUMENTS;
+       }
+
+       /* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */
+       if ((cb = malloc(sizeof(log_callback_t))) == NULL)
+               return ERROR_BUF_TOO_SMALL;
+
+       /* add item to the beginning of the linked list */
+       cb->fn = fn;
+       cb->priv = priv;
+       cb->next = log_callbacks;
+       log_callbacks = cb;
+
+       return ERROR_OK;
+}
+
+int log_remove_callback(log_callback_fn fn, void *priv)
+{
+       log_callback_t *cb, **p;
+
+       for (p = &log_callbacks; cb = *p; p = &(*p)->next)
+       {
+           if (cb->fn == fn && cb->priv == priv)
+           {
+               *p = cb->next;
+                       free(cb);
+                       return ERROR_OK;
+               }
+       }
+
+       /* no such item */
+       return ERROR_INVALID_ARGUMENTS;
+}
+
+/* return allocated string w/printf() result */
+char *alloc_printf(const char *fmt, va_list ap)
+{
+       char *string = NULL;
+       
+       /* start by 0 to exercise all the code paths. Need minimum 2 bytes to
+        * fit 1 char and 0 terminator. */
+       int size = 0;
+       int first = 1;
+       for (;;)
+       {
+               if ((string == NULL) || (!first))
+               {
+                       size = size * 2 + 2;
+                       char *t = string;
+                       string = realloc(string, size);
+                       if (string == NULL)
+                       {
+                               if (t != NULL)
+                                       free(t);
+                               return NULL;
+                       }
+               }
+       
+           int ret;
+           ret = vsnprintf(string, size, fmt, ap);
+           /* NB! The result of the vsnprintf() might be an *EMPTY* string! */
+           if ((ret >= 0) && ((ret + 1) < size))
+           {
+               return string;
+           }
+           /* there was just enough or not enough space, allocate more. */
+           first = 0;
+       }
+}
index 61050009bfe6fae0aeb15f5d545087d5de6dc73e..6c7c3de68482cc4e4f900ac886af7b94ddba7f45 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-#ifndef ERROR_H\r
-#define ERROR_H\r
-\r
-#include "replacements.h"\r
-#include "command.h"\r
-\r
-#include <stdarg.h>\r
-\r
-/* logging priorities \r
- * LOG_USER - user messages. Could be anything from information \r
- *            to progress messags. These messages do not represent\r
- *            incorrect or unexpected behaviour, just normal execution. \r
- * LOG_ERROR - fatal errors, that are likely to cause program abort\r
- * LOG_WARNING - non-fatal errors, that may be resolved later\r
- * LOG_INFO - state information, etc.\r
- * LOG_DEBUG - debug statements, execution trace\r
- */\r
-enum log_levels\r
-{\r
-       LOG_OUTPUT = -2,\r
-       LOG_USER = -1,\r
-       LOG_ERROR = 0,\r
-       LOG_WARNING = 1,\r
-       LOG_INFO = 2,\r
-       LOG_DEBUG = 3\r
-};\r
-\r
-extern void log_printf(enum log_levels level, const char *file, int line, \r
-       const char *function, const char *format, ...) \r
-       __attribute__ ((format (printf, 5, 6)));\r
-extern int log_register_commands(struct command_context_s *cmd_ctx);\r
-extern int log_init(struct command_context_s *cmd_ctx);\r
-extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);\r
-\r
-typedef void (*log_callback_fn)(void *priv, const char *file, int line,\r
-               const char *function, const char *format, va_list args);\r
-\r
-typedef struct log_callback_s\r
-{\r
-    log_callback_fn fn;\r
-       void *priv;\r
-    struct log_callback_s *next;\r
-} log_callback_t;\r
-\r
-extern int log_add_callback(log_callback_fn fn, void *priv);\r
-extern int log_remove_callback(log_callback_fn fn, void *priv);\r
-\r
-char *alloc_printf(const char *fmt, va_list ap);\r
-\r
-extern int debug_level;\r
-\r
-/* Avoid fn call and building parameter list if we're not outputting the information.\r
- * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */\r
-\r
-#define DEBUG(expr ...) \\r
-       do { if (debug_level >= LOG_DEBUG) \\r
-               log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-\r
-#define INFO(expr ...) \\r
-       do { if (debug_level >= LOG_INFO) \\r
-               log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-\r
-#define WARNING(expr ...) \\r
-       do { \\r
-               log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-\r
-#define ERROR(expr ...) \\r
-       do { \\r
-               log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-\r
-#define USER(expr ...) \\r
-       do { \\r
-               log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-\r
-#define OUTPUT(expr ...) \\r
-       do { \\r
-               log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-\r
-\r
-/* general failures\r
- * error codes < 100\r
- */\r
-#define ERROR_OK                                       (0)\r
-#define ERROR_INVALID_ARGUMENTS                (-1)\r
-#define ERROR_NO_CONFIG_FILE           (-2)\r
-#define ERROR_BUF_TOO_SMALL                    (-3)\r
-\r
-#endif /* LOG_H */\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef ERROR_H
+#define ERROR_H
+
+#include "replacements.h"
+#include "command.h"
+
+#include <stdarg.h>
+
+/* logging priorities 
+ * LOG_USER - user messages. Could be anything from information 
+ *            to progress messags. These messages do not represent
+ *            incorrect or unexpected behaviour, just normal execution. 
+ * LOG_ERROR - fatal errors, that are likely to cause program abort
+ * LOG_WARNING - non-fatal errors, that may be resolved later
+ * LOG_INFO - state information, etc.
+ * LOG_DEBUG - debug statements, execution trace
+ */
+enum log_levels
+{
+       LOG_OUTPUT = -2,
+       LOG_USER = -1,
+       LOG_ERROR = 0,
+       LOG_WARNING = 1,
+       LOG_INFO = 2,
+       LOG_DEBUG = 3
+};
+
+extern void log_printf(enum log_levels level, const char *file, int line, 
+       const char *function, const char *format, ...) 
+       __attribute__ ((format (printf, 5, 6)));
+extern int log_register_commands(struct command_context_s *cmd_ctx);
+extern int log_init(struct command_context_s *cmd_ctx);
+extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
+
+typedef void (*log_callback_fn)(void *priv, const char *file, int line,
+               const char *function, const char *format, va_list args);
+
+typedef struct log_callback_s
+{
+    log_callback_fn fn;
+       void *priv;
+    struct log_callback_s *next;
+} log_callback_t;
+
+extern int log_add_callback(log_callback_fn fn, void *priv);
+extern int log_remove_callback(log_callback_fn fn, void *priv);
+
+char *alloc_printf(const char *fmt, va_list ap);
+
+extern int debug_level;
+
+/* Avoid fn call and building parameter list if we're not outputting the information.
+ * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */
+
+#define DEBUG(expr ...) \
+       do { if (debug_level >= LOG_DEBUG) \
+               log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+
+#define INFO(expr ...) \
+       do { if (debug_level >= LOG_INFO) \
+               log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+
+#define WARNING(expr ...) \
+       do { \
+               log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+
+#define ERROR(expr ...) \
+       do { \
+               log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+
+#define USER(expr ...) \
+       do { \
+               log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+
+#define OUTPUT(expr ...) \
+       do { \
+               log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+
+
+/* general failures
+ * error codes < 100
+ */
+#define ERROR_OK                                       (0)
+#define ERROR_INVALID_ARGUMENTS                (-1)
+#define ERROR_NO_CONFIG_FILE           (-2)
+#define ERROR_BUF_TOO_SMALL                    (-3)
+
+#endif /* LOG_H */
index 4232cb443979510540464ef81f5565066ab33d71..89bf1f9b24e32530f839a1af29c0337d78d33aaa 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2004, 2005 by Dominic Rath                              *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "types.h"\r
-#include "command.h"\r
-#include "configuration.h"\r
-#include "log.h"\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <getopt.h>\r
-#include <string.h>\r
-\r
-\r
-static int help_flag;\r
-\r
-static struct option long_options[] =\r
-{\r
-       {"help",                        no_argument,    &help_flag, 1},\r
-\r
-       {"debug",                       optional_argument,      0, 'd'},\r
-       {"file",                        required_argument,      0, 'f'},\r
-       {"search",                      required_argument,      0, 's'},\r
-       {"log_output",          required_argument,      0, 'l'},\r
-       {"command",                     required_argument,      0, 'c'},\r
-       \r
-       {0, 0, 0, 0}\r
-};\r
-\r
-\r
-\r
-int configuration_output_handler(struct command_context_s *context, char* line)\r
-{\r
-       INFO(line);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])\r
-{\r
-       int c;\r
-       char command_buffer[128];\r
-\r
-       while (1)\r
-       {       \r
-               /* getopt_long stores the option index here. */\r
-               int option_index = 0;\r
-               \r
-               c = getopt_long(argc, argv, "hd::l:f:s:c:", long_options, &option_index);\r
-               \r
-               /* Detect the end of the options. */\r
-               if (c == -1)\r
-                       break;\r
-               \r
-               switch (c)\r
-               {\r
-                       case 0:\r
-                               break;\r
-                       case 'h':       /* --help | -h */\r
-                               help_flag = 1;\r
-                               break;\r
-                       case 'f':       /* --file | -f */\r
-                               snprintf(command_buffer, 128, "script %s", optarg);\r
-                               add_config_file_name(command_buffer);\r
-                               break;\r
-                       case 's':       /* --search | -s */\r
-                               add_script_search_dir(optarg);\r
-                               break;\r
-                       case 'd':       /* --debug | -d */\r
-                               if (optarg)\r
-                                       snprintf(command_buffer, 128, "debug_level %s", optarg);\r
-                               else\r
-                                       snprintf(command_buffer, 128, "debug_level 3");\r
-                               command_run_line(cmd_ctx, command_buffer);\r
-                               break;\r
-                       case 'l':       /* --log_output | -l */\r
-                               if (optarg)\r
-                               {\r
-                                       snprintf(command_buffer, 128, "log_output %s", optarg);\r
-                                       command_run_line(cmd_ctx, command_buffer);\r
-                               }       \r
-                               break;\r
-                       case 'c':       /* --command | -c */\r
-                               if (optarg)\r
-                               {\r
-                                       add_config_file_name(optarg);\r
-                               }       \r
-                               break;\r
-                               \r
-               }\r
-       }\r
-\r
-       if (help_flag)\r
-       {\r
-               OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");\r
-               OUTPUT("--help       | -h\tdisplay this help\n");\r
-               OUTPUT("--file       | -f\tuse configuration file <name>\n");\r
-               OUTPUT("--search     | -s\tdir to search for config files and scripts.\n");\r
-               OUTPUT("--debug      | -d\tset debug level <0-3>\n");\r
-               OUTPUT("--log_output | -l\tredirect log output to file <name>\n");\r
-               OUTPUT("--command    | -c\trun <command>\n");\r
-               exit(-1);\r
-       }       \r
-\r
-#ifdef _WIN32\r
-       /* Add the parent of the directory where openocd.exe resides to the\r
-        * config script search path.\r
-        * Directory layout: \r
-        * bin\openocd.exe\r
-        * lib\openocd\r
-        * event\at91eb40a_reset.cfg\r
-        * target\at91eb40a.cfg\r
-        */\r
-       {\r
-               char strExePath [MAX_PATH];\r
-               GetModuleFileName (NULL, strExePath, MAX_PATH);\r
-               /* Either this code will *always* work or it will SEGFAULT giving\r
-                * excellent information on the culprit. \r
-                */\r
-               *strrchr(strExePath, '\\')=0;\r
-               strcat(strExePath, "\\..");\r
-               add_script_search_dir(strExePath);\r
-       }\r
-#else\r
-       /* Add dir for openocd supplied scripts last so that user can over\r
-          ride those scripts if desired. */\r
-       add_script_search_dir(PKGDATADIR);\r
-       add_script_search_dir(PKGLIBDIR);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2004, 2005 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "types.h"
+#include "command.h"
+#include "configuration.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+
+
+static int help_flag;
+
+static struct option long_options[] =
+{
+       {"help",                        no_argument,    &help_flag, 1},
+
+       {"debug",                       optional_argument,      0, 'd'},
+       {"file",                        required_argument,      0, 'f'},
+       {"search",                      required_argument,      0, 's'},
+       {"log_output",          required_argument,      0, 'l'},
+       {"command",                     required_argument,      0, 'c'},
+       
+       {0, 0, 0, 0}
+};
+
+
+
+int configuration_output_handler(struct command_context_s *context, char* line)
+{
+       INFO(line);
+
+       return ERROR_OK;
+}
+
+
+int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
+{
+       int c;
+       char command_buffer[128];
+
+       while (1)
+       {       
+               /* getopt_long stores the option index here. */
+               int option_index = 0;
+               
+               c = getopt_long(argc, argv, "hd::l:f:s:c:", long_options, &option_index);
+               
+               /* Detect the end of the options. */
+               if (c == -1)
+                       break;
+               
+               switch (c)
+               {
+                       case 0:
+                               break;
+                       case 'h':       /* --help | -h */
+                               help_flag = 1;
+                               break;
+                       case 'f':       /* --file | -f */
+                               snprintf(command_buffer, 128, "script %s", optarg);
+                               add_config_file_name(command_buffer);
+                               break;
+                       case 's':       /* --search | -s */
+                               add_script_search_dir(optarg);
+                               break;
+                       case 'd':       /* --debug | -d */
+                               if (optarg)
+                                       snprintf(command_buffer, 128, "debug_level %s", optarg);
+                               else
+                                       snprintf(command_buffer, 128, "debug_level 3");
+                               command_run_line(cmd_ctx, command_buffer);
+                               break;
+                       case 'l':       /* --log_output | -l */
+                               if (optarg)
+                               {
+                                       snprintf(command_buffer, 128, "log_output %s", optarg);
+                                       command_run_line(cmd_ctx, command_buffer);
+                               }       
+                               break;
+                       case 'c':       /* --command | -c */
+                               if (optarg)
+                               {
+                                       add_config_file_name(optarg);
+                               }       
+                               break;
+                               
+               }
+       }
+
+       if (help_flag)
+       {
+               OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
+               OUTPUT("--help       | -h\tdisplay this help\n");
+               OUTPUT("--file       | -f\tuse configuration file <name>\n");
+               OUTPUT("--search     | -s\tdir to search for config files and scripts.\n");
+               OUTPUT("--debug      | -d\tset debug level <0-3>\n");
+               OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
+               OUTPUT("--command    | -c\trun <command>\n");
+               exit(-1);
+       }       
+
+#ifdef _WIN32
+       /* Add the parent of the directory where openocd.exe resides to the
+        * config script search path.
+        * Directory layout: 
+        * bin\openocd.exe
+        * lib\openocd
+        * event\at91eb40a_reset.cfg
+        * target\at91eb40a.cfg
+        */
+       {
+               char strExePath [MAX_PATH];
+               GetModuleFileName (NULL, strExePath, MAX_PATH);
+               /* Either this code will *always* work or it will SEGFAULT giving
+                * excellent information on the culprit. 
+                */
+               *strrchr(strExePath, '\\')=0;
+               strcat(strExePath, "\\..");
+               add_script_search_dir(strExePath);
+       }
+#else
+       /* Add dir for openocd supplied scripts last so that user can over
+          ride those scripts if desired. */
+       add_script_search_dir(PKGDATADIR);
+       add_script_search_dir(PKGLIBDIR);
+#endif
+
+       return ERROR_OK;
+}
index 84705c528acd42013efd8e4688483b6888b3e5d7..296afdb64fa9d087204c487c7e5e5ff1051c2aca 100644 (file)
@@ -67,38 +67,38 @@ struct timezone {
 };
 
 extern int gettimeofday(struct timeval *tv, struct timezone *tz);
-#endif\r
-\r
+#endif
+
 /**** clear_malloc & fill_malloc ****/
 void *clear_malloc(size_t size);
 void *fill_malloc(size_t size);
-\r
-/*\r
- * Now you have 3 ways for the malloc function:\r
- *\r
- * 1. Do not change anything, use the original malloc\r
- *\r
- * 2. Use the clear_malloc function instead of the original malloc.\r
- *    In this case you must use the following define:\r
- *    #define malloc((_a)) clear_malloc((_a))\r
- *\r
- * 3. Use the fill_malloc function instead of the original malloc.\r
- *    In this case you must use the following define:\r
- *    #define malloc((_a)) fill_malloc((_a))\r
- *\r
- * We have figured out that there could exist some malloc problems\r
- * where variables are using without to be initialise. To find this\r
- * places, use the fill_malloc function. With this function we want \r
- * to initialize memory to some known bad state. This is quite easily \r
- * spotted in the debugger and will trap to an invalid address. \r
- *\r
- * clear_malloc can be used if you want to set not initialise \r
- * variable to 0.\r
- *\r
- * If you do not want to change the malloc function, to not use one of\r
- * the following macros. Which is the default way.\r
- */\r
\r
+
+/*
+ * Now you have 3 ways for the malloc function:
+ *
+ * 1. Do not change anything, use the original malloc
+ *
+ * 2. Use the clear_malloc function instead of the original malloc.
+ *    In this case you must use the following define:
+ *    #define malloc((_a)) clear_malloc((_a))
+ *
+ * 3. Use the fill_malloc function instead of the original malloc.
+ *    In this case you must use the following define:
+ *    #define malloc((_a)) fill_malloc((_a))
+ *
+ * We have figured out that there could exist some malloc problems
+ * where variables are using without to be initialise. To find this
+ * places, use the fill_malloc function. With this function we want 
+ * to initialize memory to some known bad state. This is quite easily 
+ * spotted in the debugger and will trap to an invalid address. 
+ *
+ * clear_malloc can be used if you want to set not initialise 
+ * variable to 0.
+ *
+ * If you do not want to change the malloc function, to not use one of
+ * the following macros. Which is the default way.
+ */
 //#define malloc(_a) clear_malloc(_a)
 //#define malloc(_a) fill_malloc(_a)
 
index 4e53bc5507e5f95e33dffa3271beebd0b7ad950e..7c47b8e8cd3e8aa636fdddf470af7e755fadc068 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Pavel Chromy                                    *\r
- *   chromy@asix.cz                                                        *\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 "bitq.h"\r
-\r
-/* project specific includes */\r
-#include "log.h"\r
-#include "types.h"\r
-#include "jtag.h"\r
-#include "configuration.h"\r
-\r
-/* system includes */\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-\r
-#include <sys/time.h>\r
-#include <time.h>\r
-\r
-\r
-bitq_interface_t *bitq_interface; /* low level bit queue interface */\r
-\r
-bitq_state_t bitq_in_state; /* state of input queue */\r
-\r
-u8 *bitq_in_buffer; /* buffer dynamically reallocated as needed */\r
-unsigned long bitq_in_bufsize=32; /* min. buffer size */\r
-\r
-\r
-/*\r
- * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead\r
- * also the buffer for incomming data is reallocated only if necessary\r
- * no parameters, makes use of stored state information\r
- */\r
-void bitq_in_proc(void)\r
-{\r
-       /* static information preserved between calls to increase performance */\r
-       static u8 *in_buff; /* pointer to buffer for scanned data */\r
-       static int in_idx; /* index of byte being scanned */\r
-       static u8 in_mask; /* mask of next bit to be scanned */\r
-\r
-       scan_field_t *field;\r
-       int tdo;\r
-\r
-       /* loop through the queue */\r
-       while (bitq_in_state.cmd) {\r
-               /* only JTAG_SCAN command may return data */\r
-               if (bitq_in_state.cmd->type==JTAG_SCAN) {\r
-                       /* loop through the fields */\r
-                       while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields) {\r
-\r
-                               field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];\r
-                               if ( field->in_value || field->in_handler) {\r
-\r
-                                       if (bitq_in_state.bit_pos==0) {\r
-                                               /* initialize field scanning */\r
-                                               in_mask=0x01;\r
-                                               in_idx=0;\r
-                                               if (field->in_value) in_buff=field->in_value;\r
-                                               else {\r
-                                                       /* buffer reallocation needed? */\r
-                                                       if (field->num_bits>bitq_in_bufsize*8) {\r
-                                                               /* buffer previously allocated? */\r
-                                                               if (bitq_in_buffer!=NULL) {\r
-                                                                       /* free it */\r
-                                                                       free(bitq_in_buffer);\r
-                                                                       bitq_in_buffer=NULL;\r
-                                                               }\r
-                                                               /* double the buffer size until it fits */\r
-                                                               while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2;\r
-                                                       }\r
-                                                       /* if necessary, allocate buffer and check for malloc error */\r
-                                                       if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) {\r
-                                                               ERROR("malloc error");\r
-                                                               exit(-1);\r
-                                                       }\r
-                                                       in_buff=(void *)bitq_in_buffer;\r
-                                               }\r
-                                       }\r
-\r
-                                       /* field scanning */\r
-                                       while (bitq_in_state.bit_pos<field->num_bits) {\r
-                                               if ((tdo=bitq_interface->in())<0) {\r
-#ifdef _DEBUG_JTAG_IO_\r
-                                                       DEBUG("bitq in EOF");\r
-#endif\r
-                                                       return;\r
-                                               }\r
-                                               if (in_mask==0x01) in_buff[in_idx]=0;\r
-                                               if (tdo) in_buff[in_idx]|=in_mask;\r
-                                               if (in_mask==0x80) {\r
-                                                       in_mask=0x01;\r
-                                                       in_idx++;\r
-                                               }\r
-                                               else in_mask<<=1;\r
-                                               bitq_in_state.bit_pos++;\r
-                                       }\r
-\r
-\r
-                                       if (field->in_handler && bitq_in_state.status==ERROR_OK) {\r
-                                               bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv, field);\r
-                                       }\r
-\r
-                               }\r
-\r
-                               bitq_in_state.field_idx++; /* advance to next field */\r
-                               bitq_in_state.bit_pos=0; /* start next field from the first bit */\r
-                       }\r
-\r
-               }\r
-               bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */\r
-               bitq_in_state.field_idx=0; /* preselect first field */\r
-       }\r
-}\r
-\r
-\r
-\r
-void bitq_io(int tms, int tdi, int tdo_req)\r
-{\r
-       bitq_interface->out(tms, tdi, tdo_req);\r
-       /* check and process the input queue */\r
-       if (bitq_interface->in_rdy()) bitq_in_proc();\r
-}\r
-\r
-\r
-void bitq_end_state(enum tap_state state)\r
-{\r
-       if (state==-1) return;\r
-       if (tap_move_map[state]==-1) {\r
-               ERROR("BUG: %i is not a valid end state", state);\r
-               exit(-1);\r
-       }\r
-       end_state = state;\r
-}\r
-\r
-\r
-void bitq_state_move(enum tap_state new_state)\r
-{\r
-       int i=0;\r
-       u8 tms_scan;\r
-\r
-       if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) {\r
-               ERROR("TAP move from or to unstable state");\r
-               exit(-1);\r
-       }\r
-\r
-       tms_scan=TAP_MOVE(cur_state, new_state);\r
-\r
-       for (i=0; i<7; i++) {\r
-               bitq_io(tms_scan&1, 0, 0);\r
-               tms_scan>>=1;\r
-       }\r
-\r
-       cur_state = new_state;\r
-}\r
-\r
-\r
-void bitq_path_move(pathmove_command_t *cmd)\r
-{\r
-       int i;\r
-\r
-       for (i=0; i<=cmd->num_states; i++) {\r
-               if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0);\r
-               else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0);\r
-               else {\r
-                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]);\r
-                       exit(-1);\r
-               }\r
-\r
-               cur_state = cmd->path[i];\r
-       }\r
-\r
-       end_state = cur_state;\r
-}\r
-\r
-\r
-void bitq_runtest(int num_cycles)\r
-{\r
-       int i;\r
-\r
-       /* only do a state_move when we're not already in RTI */\r
-       if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI);\r
-\r
-       /* execute num_cycles */\r
-       for (i = 0; i < num_cycles; i++)\r
-               bitq_io(0, 0, 0);\r
-\r
-       /* finish in end_state */\r
-       if (cur_state != end_state) bitq_state_move(end_state);\r
-}\r
-\r
-\r
-void bitq_scan_field(scan_field_t *field, int pause)\r
-{\r
-       int bit_cnt;\r
-       int tdo_req;\r
-\r
-       u8 *out_ptr;\r
-       u8 out_mask;\r
-\r
-       if ( field->in_value || field->in_handler) tdo_req=1;\r
-       else tdo_req=0;\r
-\r
-       if (field->out_value==NULL) {\r
-               /* just send zeros and request data from TDO */\r
-               for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--)\r
-                       bitq_io(0, 0, tdo_req);\r
-               bitq_io(pause, 0, tdo_req);\r
-       }\r
-       else {\r
-               /* send data, and optionally request TDO */\r
-               out_mask=0x01;\r
-               out_ptr=field->out_value;\r
-               for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) {\r
-                       bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req);\r
-                       if (out_mask==0x80) {\r
-                               out_mask=0x01;\r
-                               out_ptr++;\r
-                       }\r
-                       else out_mask<<=1;\r
-               }\r
-               bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req);\r
-       }\r
-\r
-       if (pause) {\r
-               bitq_io(0,0,0);\r
-               if (cur_state==TAP_SI) cur_state=TAP_PI;\r
-               else if (cur_state==TAP_SD) cur_state=TAP_PD;\r
-       }\r
-}\r
-\r
-\r
-void bitq_scan(scan_command_t *cmd)\r
-{\r
-       int i;\r
-\r
-       if (cmd->ir_scan) bitq_state_move(TAP_SI);\r
-       else bitq_state_move(TAP_SD);\r
-\r
-       for (i=0; i < cmd->num_fields-1; i++)\r
-               bitq_scan_field(&cmd->fields[i], 0);\r
-       bitq_scan_field(&cmd->fields[i], 1);\r
-}\r
-\r
-\r
-int bitq_execute_queue(void)\r
-{\r
-       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */\r
-\r
-       bitq_in_state.cmd = jtag_command_queue;\r
-       bitq_in_state.field_idx = 0;\r
-       bitq_in_state.bit_pos = 0;\r
-       bitq_in_state.status = ERROR_OK;\r
-\r
-       while (cmd) {\r
-\r
-               switch (cmd->type) {\r
-\r
-                       case JTAG_END_STATE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);\r
-#endif\r
-                               bitq_end_state(cmd->cmd.end_state->end_state);\r
-                               break;\r
-\r
-                       case JTAG_RESET:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-#endif\r
-                               bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-                               if (bitq_interface->in_rdy()) bitq_in_proc();\r
-                               break;\r
-\r
-                       case JTAG_RUNTEST:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);\r
-#endif\r
-                               bitq_end_state(cmd->cmd.runtest->end_state);\r
-                               bitq_runtest(cmd->cmd.runtest->num_cycles);\r
-                               break;\r
-\r
-                       case JTAG_STATEMOVE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);\r
-#endif\r
-                               bitq_end_state(cmd->cmd.statemove->end_state);\r
-                               bitq_state_move(end_state); /* uncoditional TAP move */\r
-                               break;\r
-\r
-                       case JTAG_PATHMOVE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);\r
-#endif\r
-                               bitq_path_move(cmd->cmd.pathmove);\r
-                               break;\r
-\r
-                       case JTAG_SCAN:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);\r
-                               if (cmd->cmd.scan->ir_scan) DEBUG("scan ir");\r
-                               else DEBUG("scan dr");\r
-#endif\r
-                               bitq_end_state(cmd->cmd.scan->end_state);\r
-                               bitq_scan(cmd->cmd.scan);\r
-                               if (cur_state != end_state) bitq_state_move(end_state);\r
-                               break;\r
-\r
-                       case JTAG_SLEEP:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("sleep %i", cmd->cmd.sleep->us);\r
-#endif\r
-                               bitq_interface->sleep(cmd->cmd.sleep->us);\r
-                               if (bitq_interface->in_rdy()) bitq_in_proc();\r
-                               break;\r
-\r
-                       default:\r
-                               ERROR("BUG: unknown JTAG command type encountered");\r
-                               exit(-1);\r
-               }\r
-\r
-               cmd = cmd->next;\r
-       }\r
-\r
-       bitq_interface->flush();\r
-       bitq_in_proc();\r
-\r
-       if (bitq_in_state.cmd) {\r
-               ERROR("missing data from bitq interface");\r
-               return ERROR_JTAG_QUEUE_FAILED;\r
-       }\r
-       if (bitq_interface->in()>=0) {\r
-               ERROR("extra data from bitq interface");\r
-               return ERROR_JTAG_QUEUE_FAILED;\r
-       }\r
-\r
-       return bitq_in_state.status;\r
-}\r
-\r
-\r
-void bitq_cleanup(void)\r
-{\r
-       if (bitq_in_buffer!=NULL)\r
-       {\r
-               free(bitq_in_buffer);\r
-               bitq_in_buffer=NULL;\r
-       }\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Pavel Chromy                                    *
+ *   chromy@asix.cz                                                        *
+ *                                                                         *
+ *   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 "bitq.h"
+
+/* project specific includes */
+#include "log.h"
+#include "types.h"
+#include "jtag.h"
+#include "configuration.h"
+
+/* system includes */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+
+bitq_interface_t *bitq_interface; /* low level bit queue interface */
+
+bitq_state_t bitq_in_state; /* state of input queue */
+
+u8 *bitq_in_buffer; /* buffer dynamically reallocated as needed */
+unsigned long bitq_in_bufsize=32; /* min. buffer size */
+
+
+/*
+ * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
+ * also the buffer for incomming data is reallocated only if necessary
+ * no parameters, makes use of stored state information
+ */
+void bitq_in_proc(void)
+{
+       /* static information preserved between calls to increase performance */
+       static u8 *in_buff; /* pointer to buffer for scanned data */
+       static int in_idx; /* index of byte being scanned */
+       static u8 in_mask; /* mask of next bit to be scanned */
+
+       scan_field_t *field;
+       int tdo;
+
+       /* loop through the queue */
+       while (bitq_in_state.cmd) {
+               /* only JTAG_SCAN command may return data */
+               if (bitq_in_state.cmd->type==JTAG_SCAN) {
+                       /* loop through the fields */
+                       while (bitq_in_state.field_idx<bitq_in_state.cmd->cmd.scan->num_fields) {
+
+                               field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
+                               if ( field->in_value || field->in_handler) {
+
+                                       if (bitq_in_state.bit_pos==0) {
+                                               /* initialize field scanning */
+                                               in_mask=0x01;
+                                               in_idx=0;
+                                               if (field->in_value) in_buff=field->in_value;
+                                               else {
+                                                       /* buffer reallocation needed? */
+                                                       if (field->num_bits>bitq_in_bufsize*8) {
+                                                               /* buffer previously allocated? */
+                                                               if (bitq_in_buffer!=NULL) {
+                                                                       /* free it */
+                                                                       free(bitq_in_buffer);
+                                                                       bitq_in_buffer=NULL;
+                                                               }
+                                                               /* double the buffer size until it fits */
+                                                               while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2;
+                                                       }
+                                                       /* if necessary, allocate buffer and check for malloc error */
+                                                       if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) {
+                                                               ERROR("malloc error");
+                                                               exit(-1);
+                                                       }
+                                                       in_buff=(void *)bitq_in_buffer;
+                                               }
+                                       }
+
+                                       /* field scanning */
+                                       while (bitq_in_state.bit_pos<field->num_bits) {
+                                               if ((tdo=bitq_interface->in())<0) {
+#ifdef _DEBUG_JTAG_IO_
+                                                       DEBUG("bitq in EOF");
+#endif
+                                                       return;
+                                               }
+                                               if (in_mask==0x01) in_buff[in_idx]=0;
+                                               if (tdo) in_buff[in_idx]|=in_mask;
+                                               if (in_mask==0x80) {
+                                                       in_mask=0x01;
+                                                       in_idx++;
+                                               }
+                                               else in_mask<<=1;
+                                               bitq_in_state.bit_pos++;
+                                       }
+
+
+                                       if (field->in_handler && bitq_in_state.status==ERROR_OK) {
+                                               bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv, field);
+                                       }
+
+                               }
+
+                               bitq_in_state.field_idx++; /* advance to next field */
+                               bitq_in_state.bit_pos=0; /* start next field from the first bit */
+                       }
+
+               }
+               bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */
+               bitq_in_state.field_idx=0; /* preselect first field */
+       }
+}
+
+
+
+void bitq_io(int tms, int tdi, int tdo_req)
+{
+       bitq_interface->out(tms, tdi, tdo_req);
+       /* check and process the input queue */
+       if (bitq_interface->in_rdy()) bitq_in_proc();
+}
+
+
+void bitq_end_state(enum tap_state state)
+{
+       if (state==-1) return;
+       if (tap_move_map[state]==-1) {
+               ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+       end_state = state;
+}
+
+
+void bitq_state_move(enum tap_state new_state)
+{
+       int i=0;
+       u8 tms_scan;
+
+       if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) {
+               ERROR("TAP move from or to unstable state");
+               exit(-1);
+       }
+
+       tms_scan=TAP_MOVE(cur_state, new_state);
+
+       for (i=0; i<7; i++) {
+               bitq_io(tms_scan&1, 0, 0);
+               tms_scan>>=1;
+       }
+
+       cur_state = new_state;
+}
+
+
+void bitq_path_move(pathmove_command_t *cmd)
+{
+       int i;
+
+       for (i=0; i<=cmd->num_states; i++) {
+               if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0);
+               else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0);
+               else {
+                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]);
+                       exit(-1);
+               }
+
+               cur_state = cmd->path[i];
+       }
+
+       end_state = cur_state;
+}
+
+
+void bitq_runtest(int num_cycles)
+{
+       int i;
+
+       /* only do a state_move when we're not already in RTI */
+       if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI);
+
+       /* execute num_cycles */
+       for (i = 0; i < num_cycles; i++)
+               bitq_io(0, 0, 0);
+
+       /* finish in end_state */
+       if (cur_state != end_state) bitq_state_move(end_state);
+}
+
+
+void bitq_scan_field(scan_field_t *field, int pause)
+{
+       int bit_cnt;
+       int tdo_req;
+
+       u8 *out_ptr;
+       u8 out_mask;
+
+       if ( field->in_value || field->in_handler) tdo_req=1;
+       else tdo_req=0;
+
+       if (field->out_value==NULL) {
+               /* just send zeros and request data from TDO */
+               for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--)
+                       bitq_io(0, 0, tdo_req);
+               bitq_io(pause, 0, tdo_req);
+       }
+       else {
+               /* send data, and optionally request TDO */
+               out_mask=0x01;
+               out_ptr=field->out_value;
+               for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) {
+                       bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req);
+                       if (out_mask==0x80) {
+                               out_mask=0x01;
+                               out_ptr++;
+                       }
+                       else out_mask<<=1;
+               }
+               bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req);
+       }
+
+       if (pause) {
+               bitq_io(0,0,0);
+               if (cur_state==TAP_SI) cur_state=TAP_PI;
+               else if (cur_state==TAP_SD) cur_state=TAP_PD;
+       }
+}
+
+
+void bitq_scan(scan_command_t *cmd)
+{
+       int i;
+
+       if (cmd->ir_scan) bitq_state_move(TAP_SI);
+       else bitq_state_move(TAP_SD);
+
+       for (i=0; i < cmd->num_fields-1; i++)
+               bitq_scan_field(&cmd->fields[i], 0);
+       bitq_scan_field(&cmd->fields[i], 1);
+}
+
+
+int bitq_execute_queue(void)
+{
+       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
+
+       bitq_in_state.cmd = jtag_command_queue;
+       bitq_in_state.field_idx = 0;
+       bitq_in_state.bit_pos = 0;
+       bitq_in_state.status = ERROR_OK;
+
+       while (cmd) {
+
+               switch (cmd->type) {
+
+                       case JTAG_END_STATE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
+#endif
+                               bitq_end_state(cmd->cmd.end_state->end_state);
+                               break;
+
+                       case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+                               bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               if (bitq_interface->in_rdy()) bitq_in_proc();
+                               break;
+
+                       case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+#endif
+                               bitq_end_state(cmd->cmd.runtest->end_state);
+                               bitq_runtest(cmd->cmd.runtest->num_cycles);
+                               break;
+
+                       case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
+#endif
+                               bitq_end_state(cmd->cmd.statemove->end_state);
+                               bitq_state_move(end_state); /* uncoditional TAP move */
+                               break;
+
+                       case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+#endif
+                               bitq_path_move(cmd->cmd.pathmove);
+                               break;
+
+                       case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);
+                               if (cmd->cmd.scan->ir_scan) DEBUG("scan ir");
+                               else DEBUG("scan dr");
+#endif
+                               bitq_end_state(cmd->cmd.scan->end_state);
+                               bitq_scan(cmd->cmd.scan);
+                               if (cur_state != end_state) bitq_state_move(end_state);
+                               break;
+
+                       case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("sleep %i", cmd->cmd.sleep->us);
+#endif
+                               bitq_interface->sleep(cmd->cmd.sleep->us);
+                               if (bitq_interface->in_rdy()) bitq_in_proc();
+                               break;
+
+                       default:
+                               ERROR("BUG: unknown JTAG command type encountered");
+                               exit(-1);
+               }
+
+               cmd = cmd->next;
+       }
+
+       bitq_interface->flush();
+       bitq_in_proc();
+
+       if (bitq_in_state.cmd) {
+               ERROR("missing data from bitq interface");
+               return ERROR_JTAG_QUEUE_FAILED;
+       }
+       if (bitq_interface->in()>=0) {
+               ERROR("extra data from bitq interface");
+               return ERROR_JTAG_QUEUE_FAILED;
+       }
+
+       return bitq_in_state.status;
+}
+
+
+void bitq_cleanup(void)
+{
+       if (bitq_in_buffer!=NULL)
+       {
+               free(bitq_in_buffer);
+               bitq_in_buffer=NULL;
+       }
+}
index ebedfdfec0314bbfadb40532d3ddeee3f143ce42..aa62ad5b14cbfeded29571b2bc980afeb4fdca89 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "log.h"\r
-#include "jtag.h"\r
-#include "bitbang.h"\r
-\r
-#define TDO_BIT                1\r
-#define TDI_BIT                2\r
-#define TCK_BIT                4\r
-#define TMS_BIT                8\r
-#define TRST_BIT       16\r
-#define SRST_BIT       32\r
-#define VCC_BIT                64\r
-\r
-/* system includes */\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <sys/mman.h>\r
-#include <unistd.h>\r
-#include <fcntl.h>\r
-\r
-static u8 output_value = 0x0;\r
-static int dev_mem_fd;\r
-static void *gpio_controller;\r
-static volatile u8 *gpio_data_register;\r
-static volatile u8 *gpio_data_direction_register;\r
-\r
-/* low level command set\r
- */\r
-int ep93xx_read(void);\r
-void ep93xx_write(int tck, int tms, int tdi);\r
-void ep93xx_reset(int trst, int srst);\r
-\r
-int ep93xx_speed(int speed);\r
-int ep93xx_register_commands(struct command_context_s *cmd_ctx);\r
-int ep93xx_init(void);\r
-int ep93xx_quit(void);\r
-\r
-struct timespec ep93xx_zzzz;\r
-\r
-jtag_interface_t ep93xx_interface = \r
-{\r
-       .name = "ep93xx",\r
-       \r
-       .execute_queue = bitbang_execute_queue,\r
-\r
-       .speed = ep93xx_speed,  \r
-       .register_commands = ep93xx_register_commands,\r
-       .init = ep93xx_init,\r
-       .quit = ep93xx_quit,\r
-};\r
-\r
-bitbang_interface_t ep93xx_bitbang =\r
-{\r
-       .read = ep93xx_read,\r
-       .write = ep93xx_write,\r
-       .reset = ep93xx_reset,\r
-       .blink = 0;\r
-};\r
-\r
-int ep93xx_read(void)\r
-{\r
-       return !!(*gpio_data_register & TDO_BIT);\r
-}\r
-\r
-void ep93xx_write(int tck, int tms, int tdi)\r
-{\r
-       if (tck)\r
-               output_value |= TCK_BIT;\r
-       else\r
-               output_value &= TCK_BIT;\r
-       \r
-       if (tms)\r
-               output_value |= TMS_BIT;\r
-       else\r
-               output_value &= TMS_BIT;\r
-       \r
-       if (tdi)\r
-               output_value |= TDI_BIT;\r
-       else\r
-               output_value &= TDI_BIT;\r
-\r
-       *gpio_data_register = output_value;\r
-       nanosleep(ep93xx_zzzz);\r
-}\r
-\r
-/* (1) assert or (0) deassert reset lines */\r
-void ep93xx_reset(int trst, int srst)\r
-{\r
-       if (trst == 0)\r
-               output_value |= TRST_BIT;\r
-       else if (trst == 1)\r
-               output_value &= TRST_BIT;\r
-\r
-       if (srst == 0)\r
-               output_value |= SRST_BIT;\r
-       else if (srst == 1)\r
-               output_value &= SRST_BIT;\r
-       \r
-       *gpio_data_register = output_value;\r
-       nanosleep(ep93xx_zzzz);\r
-}\r
-\r
-int ep93xx_speed(int speed)\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ep93xx_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-static int set_gonk_mode(void)\r
-{\r
-       void *syscon;\r
-       u32 devicecfg;\r
-\r
-       syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE,\r
-                       MAP_SHARED, dev_mem_fd, 0x80930000);\r
-       if (syscon == MAP_FAILED) {\r
-               perror("mmap");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       devicecfg = *((volatile int *)(syscon + 0x80));\r
-       *((volatile int *)(syscon + 0xc0)) = 0xaa;\r
-       *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000;\r
-\r
-       munmap(syscon, 4096);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ep93xx_init(void)\r
-{\r
-       int ret;\r
-\r
-       bitbang_interface = &ep93xx_bitbang;    \r
-\r
-       ep93xx_zzzz.tv_sec = 0;\r
-       ep93xx_zzzz.tv_nsec = 10000000;\r
-\r
-       dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);\r
-       if (dev_mem_fd < 0) {\r
-               perror("open");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,\r
-                               MAP_SHARED, dev_mem_fd, 0x80840000);\r
-       if (gpio_controller == MAP_FAILED) {\r
-               perror("mmap");\r
-               close(dev_mem_fd);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       ret = set_gonk_mode();\r
-       if (ret != ERROR_OK) {\r
-               munmap(gpio_controller, 4096);\r
-               close(dev_mem_fd);\r
-               return ret;\r
-       }\r
-\r
-#if 0\r
-       /* Use GPIO port A.  */\r
-       gpio_data_register = gpio_controller + 0x00;\r
-       gpio_data_direction_register = gpio_controller + 0x10;\r
-\r
-\r
-       /* Use GPIO port B.  */\r
-       gpio_data_register = gpio_controller + 0x04;\r
-       gpio_data_direction_register = gpio_controller + 0x14;\r
-\r
-       /* Use GPIO port C.  */\r
-       gpio_data_register = gpio_controller + 0x08;\r
-       gpio_data_direction_register = gpio_controller + 0x18;\r
-\r
-       /* Use GPIO port D.  */\r
-       gpio_data_register = gpio_controller + 0x0c;\r
-       gpio_data_direction_register = gpio_controller + 0x1c;\r
-#endif\r
-\r
-       /* Use GPIO port C.  */\r
-       gpio_data_register = gpio_controller + 0x08;\r
-       gpio_data_direction_register = gpio_controller + 0x18;\r
-\r
-       INFO("gpio_data_register      = %p\n", gpio_data_register);\r
-       INFO("gpio_data_direction_reg = %p\n", gpio_data_direction_register); \r
-       /*\r
-        * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK\r
-        * TMS, TRST, SRST) as outputs.  Drive TDI and TCK low, and\r
-        * TMS/TRST/SRST high.\r
-        */\r
-       output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;\r
-       *gpio_data_register = output_value;\r
-       nanosleep(ep93xx_zzzz);\r
-\r
-       /*\r
-        * Configure the direction register.  1 = output, 0 = input.\r
-        */\r
-       *gpio_data_direction_register =\r
-               TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;\r
-\r
-       nanosleep(ep93xx_zzzz);\r
-       return ERROR_OK;\r
-}\r
-\r
-int ep93xx_quit(void)\r
-{\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "log.h"
+#include "jtag.h"
+#include "bitbang.h"
+
+#define TDO_BIT                1
+#define TDI_BIT                2
+#define TCK_BIT                4
+#define TMS_BIT                8
+#define TRST_BIT       16
+#define SRST_BIT       32
+#define VCC_BIT                64
+
+/* system includes */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static u8 output_value = 0x0;
+static int dev_mem_fd;
+static void *gpio_controller;
+static volatile u8 *gpio_data_register;
+static volatile u8 *gpio_data_direction_register;
+
+/* low level command set
+ */
+int ep93xx_read(void);
+void ep93xx_write(int tck, int tms, int tdi);
+void ep93xx_reset(int trst, int srst);
+
+int ep93xx_speed(int speed);
+int ep93xx_register_commands(struct command_context_s *cmd_ctx);
+int ep93xx_init(void);
+int ep93xx_quit(void);
+
+struct timespec ep93xx_zzzz;
+
+jtag_interface_t ep93xx_interface = 
+{
+       .name = "ep93xx",
+       
+       .execute_queue = bitbang_execute_queue,
+
+       .speed = ep93xx_speed,  
+       .register_commands = ep93xx_register_commands,
+       .init = ep93xx_init,
+       .quit = ep93xx_quit,
+};
+
+bitbang_interface_t ep93xx_bitbang =
+{
+       .read = ep93xx_read,
+       .write = ep93xx_write,
+       .reset = ep93xx_reset,
+       .blink = 0;
+};
+
+int ep93xx_read(void)
+{
+       return !!(*gpio_data_register & TDO_BIT);
+}
+
+void ep93xx_write(int tck, int tms, int tdi)
+{
+       if (tck)
+               output_value |= TCK_BIT;
+       else
+               output_value &= TCK_BIT;
+       
+       if (tms)
+               output_value |= TMS_BIT;
+       else
+               output_value &= TMS_BIT;
+       
+       if (tdi)
+               output_value |= TDI_BIT;
+       else
+               output_value &= TDI_BIT;
+
+       *gpio_data_register = output_value;
+       nanosleep(ep93xx_zzzz);
+}
+
+/* (1) assert or (0) deassert reset lines */
+void ep93xx_reset(int trst, int srst)
+{
+       if (trst == 0)
+               output_value |= TRST_BIT;
+       else if (trst == 1)
+               output_value &= TRST_BIT;
+
+       if (srst == 0)
+               output_value |= SRST_BIT;
+       else if (srst == 1)
+               output_value &= SRST_BIT;
+       
+       *gpio_data_register = output_value;
+       nanosleep(ep93xx_zzzz);
+}
+
+int ep93xx_speed(int speed)
+{
+       
+       return ERROR_OK;
+}
+
+int ep93xx_register_commands(struct command_context_s *cmd_ctx)
+{
+
+       return ERROR_OK;
+}
+
+static int set_gonk_mode(void)
+{
+       void *syscon;
+       u32 devicecfg;
+
+       syscon = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, dev_mem_fd, 0x80930000);
+       if (syscon == MAP_FAILED) {
+               perror("mmap");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       devicecfg = *((volatile int *)(syscon + 0x80));
+       *((volatile int *)(syscon + 0xc0)) = 0xaa;
+       *((volatile int *)(syscon + 0x80)) = devicecfg | 0x08000000;
+
+       munmap(syscon, 4096);
+
+       return ERROR_OK;
+}
+
+int ep93xx_init(void)
+{
+       int ret;
+
+       bitbang_interface = &ep93xx_bitbang;    
+
+       ep93xx_zzzz.tv_sec = 0;
+       ep93xx_zzzz.tv_nsec = 10000000;
+
+       dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
+       if (dev_mem_fd < 0) {
+               perror("open");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       gpio_controller = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
+                               MAP_SHARED, dev_mem_fd, 0x80840000);
+       if (gpio_controller == MAP_FAILED) {
+               perror("mmap");
+               close(dev_mem_fd);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       ret = set_gonk_mode();
+       if (ret != ERROR_OK) {
+               munmap(gpio_controller, 4096);
+               close(dev_mem_fd);
+               return ret;
+       }
+
+#if 0
+       /* Use GPIO port A.  */
+       gpio_data_register = gpio_controller + 0x00;
+       gpio_data_direction_register = gpio_controller + 0x10;
+
+
+       /* Use GPIO port B.  */
+       gpio_data_register = gpio_controller + 0x04;
+       gpio_data_direction_register = gpio_controller + 0x14;
+
+       /* Use GPIO port C.  */
+       gpio_data_register = gpio_controller + 0x08;
+       gpio_data_direction_register = gpio_controller + 0x18;
+
+       /* Use GPIO port D.  */
+       gpio_data_register = gpio_controller + 0x0c;
+       gpio_data_direction_register = gpio_controller + 0x1c;
+#endif
+
+       /* Use GPIO port C.  */
+       gpio_data_register = gpio_controller + 0x08;
+       gpio_data_direction_register = gpio_controller + 0x18;
+
+       INFO("gpio_data_register      = %p\n", gpio_data_register);
+       INFO("gpio_data_direction_reg = %p\n", gpio_data_direction_register); 
+       /*
+        * Configure bit 0 (TDO) as an input, and bits 1-5 (TDI, TCK
+        * TMS, TRST, SRST) as outputs.  Drive TDI and TCK low, and
+        * TMS/TRST/SRST high.
+        */
+       output_value = TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
+       *gpio_data_register = output_value;
+       nanosleep(ep93xx_zzzz);
+
+       /*
+        * Configure the direction register.  1 = output, 0 = input.
+        */
+       *gpio_data_direction_register =
+               TDI_BIT | TCK_BIT | TMS_BIT | TRST_BIT | SRST_BIT | VCC_BIT;
+
+       nanosleep(ep93xx_zzzz);
+       return ERROR_OK;
+}
+
+int ep93xx_quit(void)
+{
+
+       return ERROR_OK;
+}
index 011eead1ea2adb9734c09841553776d4fb8d237a..d5c4af25421d994a49ab21696b754e905b0a56fd 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2004, 2006 by Dominic Rath                              *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-#if IS_CYGWIN == 1\r
-#include "windows.h"\r
-#undef ERROR\r
-#endif\r
-\r
-#include "replacements.h"\r
-\r
-/* project specific includes */\r
-#include "log.h"\r
-#include "types.h"\r
-#include "jtag.h"\r
-#include "configuration.h"\r
-#include "time_support.h"\r
-\r
-/* system includes */\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-\r
-/* FT2232 access library includes */\r
-#if BUILD_FT2232_FTD2XX == 1\r
-#include <ftd2xx.h>\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-#include <ftdi.h>\r
-#endif\r
-\r
-#include <sys/time.h>\r
-#include <time.h>\r
-\r
-/* enable this to debug io latency\r
- */\r
-#if 0\r
-#define _DEBUG_USB_IO_\r
-#endif\r
-\r
-/* enable this to debug communication\r
- */\r
-#if 0\r
-#define _DEBUG_USB_COMMS_\r
-#endif\r
-\r
-int ft2232_execute_queue(void);\r
-\r
-int ft2232_speed(int speed);\r
-int ft2232_register_commands(struct command_context_s *cmd_ctx);\r
-int ft2232_init(void);\r
-int ft2232_quit(void);\r
-\r
-int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-char *ft2232_device_desc = NULL;\r
-char *ft2232_serial = NULL;\r
-char *ft2232_layout = NULL;\r
-unsigned char ft2232_latency = 2;\r
-\r
-#define MAX_USB_IDS    8\r
-/* vid = pid = 0 marks the end of the list */\r
-static u16 ft2232_vid[MAX_USB_IDS+1] = { 0x0403, 0 };\r
-static u16 ft2232_pid[MAX_USB_IDS+1] = { 0x6010, 0 };\r
-\r
-typedef struct ft2232_layout_s\r
-{\r
-       char* name;\r
-       int(*init)(void);\r
-       void(*reset)(int trst, int srst);\r
-       void(*blink)(void);\r
-} ft2232_layout_t;\r
-\r
-/* init procedures for supported layouts */\r
-int usbjtag_init(void);\r
-int jtagkey_init(void);\r
-int olimex_jtag_init(void);\r
-int flyswatter_init(void);\r
-int turtle_init(void);\r
-int comstick_init(void);\r
-int stm32stick_init(void);\r
-\r
-/* reset procedures for supported layouts */\r
-void usbjtag_reset(int trst, int srst);\r
-void jtagkey_reset(int trst, int srst);\r
-void olimex_jtag_reset(int trst, int srst);\r
-void flyswatter_reset(int trst, int srst);\r
-void turtle_reset(int trst, int srst);\r
-void comstick_reset(int trst, int srst);\r
-void stm32stick_reset(int trst, int srst);\r
-\r
-/* blink procedures for layouts that support a blinking led */\r
-void olimex_jtag_blink(void);\r
-void turtle_jtag_blink(void);\r
-\r
-ft2232_layout_t ft2232_layouts[] =\r
-{\r
-       {"usbjtag", usbjtag_init, usbjtag_reset, NULL},\r
-       {"jtagkey", jtagkey_init, jtagkey_reset, NULL},\r
-       {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL},\r
-       {"oocdlink", jtagkey_init, jtagkey_reset, NULL},\r
-       {"signalyzer", usbjtag_init, usbjtag_reset, NULL},\r
-       {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL},\r
-       {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink},\r
-       {"flyswatter", flyswatter_init, flyswatter_reset, NULL},\r
-       {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink},\r
-       {"comstick", comstick_init, comstick_reset, NULL},\r
-       {"stm32stick", stm32stick_init, stm32stick_reset, NULL},\r
-       {NULL, NULL, NULL},\r
-};\r
-\r
-static u8 nTRST, nTRSTnOE, nSRST, nSRSTnOE;\r
-\r
-static ft2232_layout_t *layout;\r
-static u8 low_output = 0x0;\r
-static u8 low_direction = 0x0;\r
-static u8 high_output = 0x0;\r
-static u8 high_direction = 0x0;\r
-\r
-#if BUILD_FT2232_FTD2XX == 1\r
-static FT_HANDLE ftdih = NULL;\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-static struct ftdi_context ftdic;\r
-#endif\r
-\r
-static u8 *ft2232_buffer = NULL;\r
-static int ft2232_buffer_size = 0;\r
-static int ft2232_read_pointer = 0;\r
-static int ft2232_expect_read = 0;\r
-#define FT2232_BUFFER_SIZE     131072\r
-#define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++]\r
-#define BUFFER_READ ft2232_buffer[ft2232_read_pointer++]\r
-\r
-jtag_interface_t ft2232_interface = \r
-{\r
-       \r
-       .name = "ft2232",\r
-       \r
-       .execute_queue = ft2232_execute_queue,\r
-       \r
-       .speed = ft2232_speed,\r
-       .register_commands = ft2232_register_commands,\r
-       .init = ft2232_init,\r
-       .quit = ft2232_quit,\r
-};\r
-\r
-int ft2232_write(u8 *buf, int size, u32* bytes_written)\r
-{\r
-#if BUILD_FT2232_FTD2XX == 1\r
-       FT_STATUS status;\r
-       DWORD dw_bytes_written;\r
-       if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)\r
-       {\r
-               *bytes_written = dw_bytes_written;\r
-               ERROR("FT_Write returned: %lu", status);\r
-               return ERROR_JTAG_DEVICE_ERROR;\r
-       }\r
-       else\r
-       {\r
-               *bytes_written = dw_bytes_written;\r
-               return ERROR_OK;        \r
-       }\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-       int retval;\r
-       if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0)\r
-       {\r
-               *bytes_written = 0;\r
-               ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));\r
-               return ERROR_JTAG_DEVICE_ERROR;\r
-       }\r
-       else\r
-       {\r
-               *bytes_written = retval;\r
-               return ERROR_OK;        \r
-       }\r
-#endif\r
-}\r
-\r
-int ft2232_read(u8* buf, int size, u32* bytes_read)\r
-{\r
-#if BUILD_FT2232_FTD2XX == 1\r
-       DWORD dw_bytes_read;\r
-       FT_STATUS status;\r
-       int timeout = 5;\r
-       *bytes_read = 0;\r
-\r
-       while ((*bytes_read < size) && timeout--)\r
-       {\r
-               if ((status = FT_Read(ftdih, buf + *bytes_read, size - \r
-                       *bytes_read, &dw_bytes_read)) != FT_OK)         \r
-               {\r
-                       *bytes_read = 0; \r
-                       ERROR("FT_Read returned: %lu", status);\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-               *bytes_read += dw_bytes_read; \r
-       }\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-       int retval;\r
-       int timeout = 100;\r
-       *bytes_read = 0;\r
-       \r
-       while ((*bytes_read < size) && timeout--)\r
-       {\r
-               if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0)\r
-               {\r
-                       *bytes_read = 0;\r
-                       ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic));\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-               *bytes_read += retval;\r
-       }\r
-#endif\r
-\r
-       if (*bytes_read < size)\r
-       {\r
-               ERROR("couldn't read the requested number of bytes from FT2232 device (%i < %i)", *bytes_read, size);\r
-               return ERROR_JTAG_DEVICE_ERROR;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_speed(int speed)\r
-{\r
-       u8 buf[3];\r
-       int retval;\r
-       u32 bytes_written;\r
-\r
-       buf[0] = 0x86; /* command "set divisor" */\r
-       buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=2.0MHz, ...*/\r
-       buf[2] = (speed >> 8) & 0xff; /* valueH */\r
-       \r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't set FT2232 TCK speed");\r
-               return retval;\r
-       }\r
-\r
-       jtag_speed = speed;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command,\r
-               COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "ft2232_serial", ft2232_handle_serial_command,\r
-               COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command,\r
-               COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command,\r
-                                        COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "ft2232_latency", ft2232_handle_latency_command,\r
-                                        COMMAND_CONFIG, NULL);\r
-       return ERROR_OK;\r
-}\r
-\r
-void ft2232_end_state(enum tap_state state)\r
-{\r
-       if (tap_move_map[state] != -1)\r
-               end_state = state;\r
-       else\r
-       {\r
-               ERROR("BUG: %i is not a valid end state", state);\r
-               exit(-1);\r
-       }\r
-}\r
-\r
-void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size)\r
-{\r
-       int num_bytes = ((scan_size + 7) / 8);\r
-       int bits_left = scan_size;\r
-       int cur_byte = 0;\r
-\r
-       while(num_bytes-- > 1)\r
-       {\r
-               buffer[cur_byte] = BUFFER_READ;\r
-               cur_byte++;\r
-               bits_left -= 8;\r
-       }\r
-\r
-       buffer[cur_byte] = 0x0;\r
-\r
-       if (bits_left > 1)\r
-       {\r
-               buffer[cur_byte] = BUFFER_READ >> 1;\r
-       }\r
-\r
-       buffer[cur_byte] = (buffer[cur_byte] | ((BUFFER_READ & 0x02) << 6)) >> (8 - bits_left);\r
-\r
-}\r
-\r
-void ft2232_debug_dump_buffer(void)\r
-{\r
-       int i;\r
-       char line[256];\r
-       char *line_p = line;\r
-       \r
-       for (i = 0; i < ft2232_buffer_size; i++)\r
-       {\r
-               line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]);\r
-               if (i % 16 == 15)\r
-               {\r
-                       DEBUG("%s", line);\r
-                       line_p = line;\r
-               }\r
-       }\r
-       \r
-       if (line_p != line)\r
-               DEBUG("%s", line);\r
-}\r
-\r
-int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last)\r
-{\r
-       jtag_command_t *cmd;\r
-       u8 *buffer;\r
-       int scan_size;\r
-       enum scan_type type;\r
-       int retval;\r
-       u32 bytes_written;\r
-       u32 bytes_read;\r
-       \r
-#ifdef _DEBUG_USB_IO_\r
-       struct timeval start, inter, inter2, end;\r
-       struct timeval d_inter, d_inter2, d_end;\r
-#endif\r
-\r
-#ifdef _DEBUG_USB_COMMS_\r
-       DEBUG("write buffer (size %i):", ft2232_buffer_size);\r
-       ft2232_debug_dump_buffer();\r
-#endif\r
-\r
-#ifdef _DEBUG_USB_IO_\r
-       gettimeofday(&start, NULL);     \r
-#endif\r
-\r
-       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)\r
-       {\r
-               ERROR("couldn't write MPSSE commands to FT2232");\r
-               exit(-1);\r
-       }\r
-       \r
-#ifdef _DEBUG_USB_IO_\r
-       gettimeofday(&inter, NULL);     \r
-#endif\r
-       \r
-       if (ft2232_expect_read)\r
-       {\r
-               int timeout = 100;\r
-               ft2232_buffer_size = 0;\r
-               \r
-#ifdef _DEBUG_USB_IO_\r
-               gettimeofday(&inter2, NULL);    \r
-#endif\r
-               \r
-               if ((retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("couldn't read from FT2232");\r
-                       exit(-1);\r
-               }\r
-               \r
-#ifdef _DEBUG_USB_IO_\r
-               gettimeofday(&end, NULL);       \r
-\r
-               timeval_subtract(&d_inter, &inter, &start);\r
-               timeval_subtract(&d_inter2, &inter2, &start);\r
-               timeval_subtract(&d_end, &end, &start);\r
-\r
-               INFO("inter: %i.%i, inter2: %i.%i end: %i.%i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, d_inter2.tv_usec, d_end.tv_sec, d_end.tv_usec);\r
-#endif\r
-       \r
-               \r
-               ft2232_buffer_size = bytes_read;\r
-               \r
-               if (ft2232_expect_read != ft2232_buffer_size)\r
-               {\r
-                       ERROR("ft2232_expect_read (%i) != ft2232_buffer_size (%i) (%i retries)", ft2232_expect_read, ft2232_buffer_size, 100 - timeout);\r
-                       ft2232_debug_dump_buffer();     \r
-\r
-                       exit(-1);\r
-               }\r
-\r
-#ifdef _DEBUG_USB_COMMS_\r
-               DEBUG("read buffer (%i retries): %i bytes", 100 - timeout, ft2232_buffer_size);\r
-               ft2232_debug_dump_buffer();\r
-#endif\r
-       }\r
-\r
-       ft2232_expect_read = 0;\r
-       ft2232_read_pointer = 0;\r
-       \r
-       /* return ERROR_OK, unless a jtag_read_buffer returns a failed check\r
-        * that wasn't handled by a caller-provided error handler\r
-        */ \r
-       retval = ERROR_OK;\r
-       \r
-       cmd = first;\r
-       while (cmd != last)\r
-       {\r
-               switch (cmd->type)\r
-               {\r
-                       case JTAG_SCAN:\r
-                               type = jtag_scan_type(cmd->cmd.scan);\r
-                               if (type != SCAN_OUT)\r
-                               {\r
-                                       scan_size = jtag_scan_size(cmd->cmd.scan);\r
-                                       buffer = calloc(CEIL(scan_size, 8), 1);\r
-                                       ft2232_read_scan(type, buffer, scan_size);\r
-                                       if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       free(buffer);\r
-                               }\r
-                               break;\r
-                       default:\r
-                               break;\r
-               }\r
-               cmd = cmd->next;\r
-       }\r
-       \r
-       ft2232_buffer_size = 0;\r
-\r
-       return retval;\r
-}\r
-\r
-void ft2232_add_pathmove(pathmove_command_t *cmd)\r
-{\r
-       int num_states = cmd->num_states;\r
-       u8 tms_byte;\r
-       int state_count;\r
-\r
-       state_count = 0;\r
-       while (num_states)\r
-       {\r
-               tms_byte = 0x0;\r
-               int bit_count = 0;\r
-               \r
-               /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-               BUFFER_ADD = 0x4b;\r
-               /* number of states remaining */\r
-               BUFFER_ADD = (num_states % 7) - 1;\r
-               \r
-               while (num_states % 7)\r
-               {\r
-                       if (tap_transitions[cur_state].low == cmd->path[state_count])\r
-                               buf_set_u32(&tms_byte, bit_count++, 1, 0x0);\r
-                       else if (tap_transitions[cur_state].high == cmd->path[state_count])\r
-                               buf_set_u32(&tms_byte, bit_count++, 1, 0x1);\r
-                       else\r
-                       {\r
-                               ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);\r
-                               exit(-1);\r
-                       }\r
-\r
-                       cur_state = cmd->path[state_count];\r
-                       state_count++;\r
-                       num_states--;\r
-               }\r
-               \r
-               BUFFER_ADD = tms_byte;\r
-       }\r
-       \r
-       end_state = cur_state;\r
-}\r
-\r
-void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)\r
-{\r
-       int num_bytes = (scan_size + 7) / 8;\r
-       int bits_left = scan_size;\r
-       int cur_byte = 0;\r
-       int last_bit;\r
-\r
-       if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))\r
-       {\r
-               /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-               BUFFER_ADD = 0x4b;\r
-               /* scan 7 bit */\r
-               BUFFER_ADD = 0x6;\r
-               /* TMS data bits */\r
-               if (ir_scan)\r
-               {\r
-                       BUFFER_ADD = TAP_MOVE(cur_state, TAP_SI);\r
-                       cur_state = TAP_SI;\r
-               }\r
-               else\r
-               {\r
-                       BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);\r
-                       cur_state = TAP_SD;\r
-               }\r
-               //DEBUG("added TMS scan (no read)");\r
-       }\r
-       \r
-       /* add command for complete bytes */\r
-       while (num_bytes > 1)\r
-       {\r
-               int thisrun_bytes;\r
-               if (type == SCAN_IO)\r
-               {\r
-                       /* Clock Data Bytes In and Out LSB First */\r
-                       BUFFER_ADD = 0x39;\r
-                       //DEBUG("added TDI bytes (io %i)", num_bytes);\r
-               }\r
-               else if (type == SCAN_OUT)\r
-               {\r
-                       /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */\r
-                       BUFFER_ADD = 0x19;\r
-                       //DEBUG("added TDI bytes (o)");\r
-               }\r
-               else if (type == SCAN_IN)\r
-               {\r
-                       /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */\r
-                       BUFFER_ADD = 0x28;\r
-                       //DEBUG("added TDI bytes (i %i)", num_bytes);\r
-               }\r
-               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);\r
-               num_bytes -= thisrun_bytes;\r
-               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;\r
-               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;\r
-               if (type != SCAN_IN)\r
-               {\r
-                       /* add complete bytes */\r
-                       while(thisrun_bytes-- > 0)\r
-                       {\r
-                               BUFFER_ADD = buffer[cur_byte];\r
-                               cur_byte++;\r
-                               bits_left -= 8;\r
-                       }\r
-               }\r
-               else /* (type == SCAN_IN) */\r
-               {\r
-                       bits_left -= 8 * (thisrun_bytes);\r
-               }\r
-       }\r
-       \r
-       /* the most signifcant bit is scanned during TAP movement */\r
-       if (type != SCAN_IN)\r
-               last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;\r
-       else\r
-               last_bit = 0;\r
-\r
-       /* process remaining bits but the last one */\r
-       if (bits_left > 1)\r
-       {\r
-               if (type == SCAN_IO)\r
-               {\r
-                       /* Clock Data Bits In and Out LSB First */\r
-                       BUFFER_ADD = 0x3b;\r
-                       //DEBUG("added TDI bits (io) %i", bits_left - 1);\r
-               }\r
-               else if (type == SCAN_OUT)\r
-               {\r
-                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */\r
-                       BUFFER_ADD = 0x1b;\r
-                       //DEBUG("added TDI bits (o)");\r
-               }\r
-               else if (type == SCAN_IN)\r
-               {\r
-                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */\r
-                       BUFFER_ADD = 0x2a;\r
-                       //DEBUG("added TDI bits (i %i)", bits_left - 1);\r
-               }\r
-               BUFFER_ADD = bits_left - 2;\r
-               if (type != SCAN_IN)\r
-                       BUFFER_ADD = buffer[cur_byte];\r
-       }\r
-\r
-       if ((ir_scan && (end_state == TAP_SI)) ||\r
-               (!ir_scan && (end_state == TAP_SD)))\r
-       {\r
-               if (type == SCAN_IO)\r
-               {\r
-                       /* Clock Data Bits In and Out LSB First */\r
-                       BUFFER_ADD = 0x3b;\r
-                       //DEBUG("added TDI bits (io) %i", bits_left - 1);\r
-               }\r
-               else if (type == SCAN_OUT)\r
-               {\r
-                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */\r
-                       BUFFER_ADD = 0x1b;\r
-                       //DEBUG("added TDI bits (o)");\r
-               }\r
-               else if (type == SCAN_IN)\r
-               {\r
-                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */\r
-                       BUFFER_ADD = 0x2a;\r
-                       //DEBUG("added TDI bits (i %i)", bits_left - 1);\r
-               }\r
-               BUFFER_ADD = 0x0;\r
-               BUFFER_ADD = last_bit;\r
-       }\r
-       else\r
-       {\r
-               /* move from Shift-IR/DR to end state */\r
-               if (type != SCAN_OUT)\r
-               {\r
-                       /* Clock Data to TMS/CS Pin with Read */\r
-                       BUFFER_ADD = 0x6b;\r
-                       //DEBUG("added TMS scan (read)");\r
-               }\r
-               else\r
-               {\r
-                       /* Clock Data to TMS/CS Pin (no Read) */\r
-                       BUFFER_ADD = 0x4b;\r
-                       //DEBUG("added TMS scan (no read)");\r
-               }\r
-               BUFFER_ADD = 0x6;\r
-               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);\r
-               cur_state = end_state;\r
-       }\r
-}\r
-\r
-int ft2232_large_scan(scan_command_t *cmd, enum scan_type type, u8 *buffer, int scan_size)\r
-{\r
-       int num_bytes = (scan_size + 7) / 8;\r
-       int bits_left = scan_size;\r
-       int cur_byte = 0;\r
-       int last_bit;\r
-       u8 *receive_buffer = malloc(CEIL(scan_size, 8));\r
-       u8 *receive_pointer = receive_buffer;\r
-       u32 bytes_written;\r
-       u32 bytes_read;\r
-       int retval;\r
-       int thisrun_read = 0;\r
-       \r
-       if (cmd->ir_scan)\r
-       {\r
-               ERROR("BUG: large IR scans are not supported");\r
-               exit(-1);\r
-       }\r
-\r
-       if (cur_state != TAP_SD)\r
-       {\r
-               /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-               BUFFER_ADD = 0x4b;\r
-               /* scan 7 bit */\r
-               BUFFER_ADD = 0x6;\r
-               /* TMS data bits */\r
-               BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);\r
-               cur_state = TAP_SD;\r
-       }\r
-       \r
-       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)\r
-       {\r
-               ERROR("couldn't write MPSSE commands to FT2232");\r
-               exit(-1);\r
-       }\r
-       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);\r
-       ft2232_buffer_size = 0;\r
-       \r
-       /* add command for complete bytes */\r
-       while (num_bytes > 1)\r
-       {\r
-               int thisrun_bytes;\r
-               \r
-               if (type == SCAN_IO)\r
-               {\r
-                       /* Clock Data Bytes In and Out LSB First */\r
-                       BUFFER_ADD = 0x39;\r
-                       //DEBUG("added TDI bytes (io %i)", num_bytes);\r
-               }\r
-               else if (type == SCAN_OUT)\r
-               {\r
-                       /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */\r
-                       BUFFER_ADD = 0x19;\r
-                       //DEBUG("added TDI bytes (o)");\r
-               }\r
-               else if (type == SCAN_IN)\r
-               {\r
-                       /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */\r
-                       BUFFER_ADD = 0x28;\r
-                       //DEBUG("added TDI bytes (i %i)", num_bytes);\r
-               }\r
-               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);\r
-               thisrun_read = thisrun_bytes;\r
-               num_bytes -= thisrun_bytes;\r
-               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;\r
-               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;\r
-               if (type != SCAN_IN)\r
-               {\r
-                       /* add complete bytes */\r
-                       while(thisrun_bytes-- > 0)\r
-                       {\r
-                               BUFFER_ADD = buffer[cur_byte];\r
-                               cur_byte++;\r
-                               bits_left -= 8;\r
-                       }\r
-               }\r
-               else /* (type == SCAN_IN) */\r
-               {\r
-                       bits_left -= 8 * (thisrun_bytes);\r
-               }\r
-\r
-               if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)\r
-               {\r
-                       ERROR("couldn't write MPSSE commands to FT2232");\r
-                       exit(-1);\r
-               }\r
-               DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);\r
-               ft2232_buffer_size = 0;\r
-               \r
-               if (type != SCAN_OUT)\r
-               {\r
-                       if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)\r
-                       {\r
-                               ERROR("couldn't read from FT2232");\r
-                               exit(-1);\r
-                       }\r
-                       DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);\r
-                       receive_pointer += bytes_read;\r
-               }\r
-       }\r
-       \r
-       thisrun_read = 0;\r
-       \r
-       /* the most signifcant bit is scanned during TAP movement */\r
-       if (type != SCAN_IN)\r
-               last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;\r
-       else\r
-               last_bit = 0;\r
-\r
-       /* process remaining bits but the last one */\r
-       if (bits_left > 1)\r
-       {\r
-               if (type == SCAN_IO)\r
-               {\r
-                       /* Clock Data Bits In and Out LSB First */\r
-                       BUFFER_ADD = 0x3b;\r
-                       //DEBUG("added TDI bits (io) %i", bits_left - 1);\r
-               }\r
-               else if (type == SCAN_OUT)\r
-               {\r
-                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */\r
-                       BUFFER_ADD = 0x1b;\r
-                       //DEBUG("added TDI bits (o)");\r
-               }\r
-               else if (type == SCAN_IN)\r
-               {\r
-                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */\r
-                       BUFFER_ADD = 0x2a;\r
-                       //DEBUG("added TDI bits (i %i)", bits_left - 1);\r
-               }\r
-               BUFFER_ADD = bits_left - 2;\r
-               if (type != SCAN_IN)\r
-                       BUFFER_ADD = buffer[cur_byte];\r
-                       \r
-               if (type != SCAN_OUT)\r
-                       thisrun_read += 2;\r
-       }\r
-\r
-       if (end_state == TAP_SD)\r
-       {\r
-               if (type == SCAN_IO)\r
-               {\r
-                       /* Clock Data Bits In and Out LSB First */\r
-                       BUFFER_ADD = 0x3b;\r
-                       //DEBUG("added TDI bits (io) %i", bits_left - 1);\r
-               }\r
-               else if (type == SCAN_OUT)\r
-               {\r
-                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */\r
-                       BUFFER_ADD = 0x1b;\r
-                       //DEBUG("added TDI bits (o)");\r
-               }\r
-               else if (type == SCAN_IN)\r
-               {\r
-                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */\r
-                       BUFFER_ADD = 0x2a;\r
-                       //DEBUG("added TDI bits (i %i)", bits_left - 1);\r
-               }\r
-               BUFFER_ADD = 0x0;\r
-               BUFFER_ADD = last_bit;\r
-       }\r
-       else\r
-       {\r
-               /* move from Shift-IR/DR to end state */\r
-               if (type != SCAN_OUT)\r
-               {\r
-                       /* Clock Data to TMS/CS Pin with Read */\r
-                       BUFFER_ADD = 0x6b;\r
-                       //DEBUG("added TMS scan (read)");\r
-               }\r
-               else\r
-               {\r
-                       /* Clock Data to TMS/CS Pin (no Read) */\r
-                       BUFFER_ADD = 0x4b;\r
-                       //DEBUG("added TMS scan (no read)");\r
-               }\r
-               BUFFER_ADD = 0x6;\r
-               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);\r
-               cur_state = end_state;\r
-       }\r
-       \r
-       if (type != SCAN_OUT)\r
-               thisrun_read += 1;\r
-       \r
-       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)\r
-       {\r
-               ERROR("couldn't write MPSSE commands to FT2232");\r
-               exit(-1);\r
-       }\r
-       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);\r
-       ft2232_buffer_size = 0;\r
-       \r
-       if (type != SCAN_OUT)\r
-       {\r
-               if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("couldn't read from FT2232");\r
-                       exit(-1);\r
-               }\r
-               DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);\r
-               receive_pointer += bytes_read;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_predict_scan_out(int scan_size, enum scan_type type)\r
-{\r
-       int predicted_size = 3;\r
-       int num_bytes = (scan_size - 1) / 8;\r
-       \r
-       if (cur_state != TAP_SD)\r
-               predicted_size += 3;\r
-       \r
-       if (type == SCAN_IN)    /* only from device to host */\r
-       {\r
-               /* complete bytes */\r
-               predicted_size += (CEIL(num_bytes, 65536)) * 3;\r
-               /* remaining bits - 1 (up to 7) */\r
-               predicted_size += ((scan_size - 1) % 8) ? 2 : 0;\r
-       }\r
-       else                                    /* host to device, or bidirectional */\r
-       {\r
-               /* complete bytes */\r
-               predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3;\r
-               /* remaining bits -1 (up to 7) */\r
-               predicted_size += ((scan_size - 1) % 8) ? 3 : 0;\r
-       }\r
-\r
-       return predicted_size;\r
-}\r
-\r
-int ft2232_predict_scan_in(int scan_size, enum scan_type type)\r
-{\r
-       int predicted_size = 0;\r
-       \r
-       if (type != SCAN_OUT)\r
-       {\r
-               /* complete bytes */\r
-               predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) - 1) : 0;\r
-               /* remaining bits - 1 */\r
-               predicted_size += ((scan_size - 1) % 8) ? 1 : 0;\r
-               /* last bit (from TMS scan) */\r
-               predicted_size += 1;\r
-       }\r
-       \r
-       //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size);\r
-\r
-       return predicted_size;\r
-}\r
-\r
-void usbjtag_reset(int trst, int srst)\r
-{\r
-       if (trst == 1)\r
-       {\r
-               cur_state = TAP_TLR;\r
-               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-                       low_direction |= nTRSTnOE;      /* switch to output pin (output is low) */\r
-               else\r
-                       low_output &= ~nTRST;   /* switch output low */\r
-       }\r
-       else if (trst == 0)\r
-       {\r
-               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-                       low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal and external pullup) */\r
-               else\r
-                       low_output |= nTRST; /* switch output high */\r
-       }\r
-\r
-       if (srst == 1)\r
-       {\r
-               if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-                       low_output &= ~nSRST;   /* switch output low */\r
-               else\r
-                       low_direction |= nSRSTnOE;      /* switch to output pin (output is low) */\r
-       }\r
-       else if (srst == 0)\r
-       {\r
-               if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-                       low_output |= nSRST;    /* switch output high */\r
-               else\r
-                       low_direction &= ~nSRSTnOE;     /* switch to input pin (high-Z) */\r
-       }\r
-       \r
-       /* command "set data bits low byte" */\r
-       BUFFER_ADD = 0x80;\r
-       BUFFER_ADD = low_output;\r
-       BUFFER_ADD = low_direction;\r
-\r
-}\r
-\r
-void jtagkey_reset(int trst, int srst)\r
-{\r
-       if (trst == 1)\r
-       {\r
-               cur_state = TAP_TLR;\r
-               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-                       high_output &= ~nTRSTnOE;\r
-               else\r
-                       high_output &= ~nTRST;\r
-       }\r
-       else if (trst == 0)\r
-       {\r
-               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-                       high_output |= nTRSTnOE;\r
-               else\r
-                       high_output |= nTRST;\r
-       }\r
-\r
-       if (srst == 1)\r
-       {\r
-               if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-                       high_output &= ~nSRST;\r
-               else\r
-                       high_output &= ~nSRSTnOE;\r
-       }\r
-       else if (srst == 0)\r
-       {\r
-               if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-                       high_output |= nSRST;\r
-               else\r
-                       high_output |= nSRSTnOE;\r
-       }\r
-       \r
-       /* command "set data bits high byte" */\r
-       BUFFER_ADD = 0x82;\r
-       BUFFER_ADD = high_output;\r
-       BUFFER_ADD = high_direction;\r
-       DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);\r
-}\r
-\r
-void olimex_jtag_reset(int trst, int srst)\r
-{\r
-       if (trst == 1)\r
-       {\r
-               cur_state = TAP_TLR;\r
-               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-                       high_output &= ~nTRSTnOE;\r
-               else\r
-                       high_output &= ~nTRST;\r
-       }\r
-       else if (trst == 0)\r
-       {\r
-               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-                       high_output |= nTRSTnOE;\r
-               else\r
-                       high_output |= nTRST;\r
-       }\r
-\r
-    if (srst == 1)\r
-    {\r
-        high_output |= nSRST;\r
-    }\r
-    else if (srst == 0)\r
-    {\r
-        high_output &= ~nSRST;\r
-    }\r
-\r
-    /* command "set data bits high byte" */\r
-    BUFFER_ADD = 0x82;\r
-    BUFFER_ADD = high_output;\r
-    BUFFER_ADD = high_direction;\r
-    DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);\r
-}\r
-\r
-void flyswatter_reset(int trst, int srst)\r
-{\r
-       if (trst == 1)\r
-       {\r
-               cur_state = TAP_TLR;\r
-               low_output &= ~nTRST;\r
-       }\r
-       else if (trst == 0)\r
-       {\r
-               low_output |= nTRST;\r
-       }\r
-\r
-    if (srst == 1)\r
-    {\r
-        low_output |= nSRST;\r
-    }\r
-    else if (srst == 0)\r
-    {\r
-        low_output &= ~nSRST;\r
-    }\r
-\r
-    /* command "set data bits low byte" */\r
-    BUFFER_ADD = 0x80;\r
-    BUFFER_ADD = low_output;\r
-    BUFFER_ADD = low_direction;\r
-    DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction);\r
-}\r
-\r
-void turtle_reset(int trst, int srst)\r
-{\r
-       trst = trst;\r
-       \r
-       if (srst == 1)\r
-       {\r
-               low_output |= nSRST;\r
-       }\r
-       else if (srst == 0)\r
-       {\r
-               low_output &= ~nSRST;\r
-       }\r
-       \r
-       /* command "set data bits low byte" */\r
-       BUFFER_ADD = 0x80;\r
-       BUFFER_ADD = low_output;\r
-       BUFFER_ADD = low_direction;\r
-       DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction);\r
-}\r
-\r
-void comstick_reset(int trst, int srst)\r
-{\r
-       if (trst == 1)\r
-       {\r
-               cur_state = TAP_TLR;\r
-               high_output &= ~nTRST;\r
-       }\r
-       else if (trst == 0)\r
-       {\r
-               high_output |= nTRST;\r
-       }\r
-\r
-    if (srst == 1)\r
-    {\r
-        high_output &= ~nSRST;\r
-    }\r
-    else if (srst == 0)\r
-    {\r
-        high_output |= nSRST;\r
-    }\r
-       \r
-       /* command "set data bits high byte" */\r
-       BUFFER_ADD = 0x82;\r
-       BUFFER_ADD = high_output;\r
-       BUFFER_ADD = high_direction;\r
-       DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);\r
-}\r
-\r
-void stm32stick_reset(int trst, int srst)\r
-{\r
-       if (trst == 1)\r
-       {\r
-               cur_state = TAP_TLR;\r
-               high_output &= ~nTRST;\r
-       }\r
-       else if (trst == 0)\r
-       {\r
-               high_output |= nTRST;\r
-       }\r
-\r
-    if (srst == 1)\r
-    {\r
-        low_output &= ~nSRST;\r
-    }\r
-    else if (srst == 0)\r
-    {\r
-        low_output |= nSRST;\r
-    }\r
-       \r
-       /* command "set data bits low byte" */\r
-       BUFFER_ADD = 0x80;\r
-       BUFFER_ADD = low_output;\r
-       BUFFER_ADD = low_direction;\r
-       \r
-       /* command "set data bits high byte" */\r
-       BUFFER_ADD = 0x82;\r
-       BUFFER_ADD = high_output;\r
-       BUFFER_ADD = high_direction;\r
-       DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);\r
-}\r
-\r
-int ft2232_execute_queue()\r
-{\r
-       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */\r
-       jtag_command_t *first_unsent = cmd;     /* next command that has to be sent */\r
-       u8 *buffer;\r
-       int scan_size;  /* size of IR or DR scan */\r
-       enum scan_type type;\r
-       int i;\r
-       int predicted_size = 0;\r
-       int require_send = 0;\r
-       int retval;\r
-       \r
-       /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check\r
-        * that wasn't handled by a caller-provided error handler\r
-        */ \r
-       retval = ERROR_OK;\r
-\r
-       ft2232_buffer_size = 0;\r
-       ft2232_expect_read = 0;\r
-       \r
-       /* blink, if the current layout has that feature */\r
-       if (layout->blink)\r
-               layout->blink();\r
-\r
-       while (cmd)\r
-       {\r
-               switch(cmd->type)\r
-               {\r
-                       case JTAG_END_STATE:\r
-                               if (cmd->cmd.end_state->end_state != -1)\r
-                                       ft2232_end_state(cmd->cmd.end_state->end_state);\r
-                               break;\r
-                       case JTAG_RESET:\r
-                               /* only send the maximum buffer size that FT2232C can handle */\r
-                               predicted_size = 3;\r
-                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)\r
-                               {\r
-                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       require_send = 0;\r
-                                       first_unsent = cmd;\r
-                               }\r
-\r
-                               layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-                               require_send = 1;\r
-                               \r
-#ifdef _DEBUG_JTAG_IO_                         \r
-                               DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-#endif\r
-                               break;\r
-                       case JTAG_RUNTEST:\r
-                               /* only send the maximum buffer size that FT2232C can handle */\r
-                               predicted_size = 0;\r
-                               if (cur_state != TAP_RTI)\r
-                                       predicted_size += 3;\r
-                               predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7);\r
-                               if ((cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_RTI))\r
-                                       predicted_size += 3;\r
-                               if ((cmd->cmd.runtest->end_state == -1) && (end_state != TAP_RTI))\r
-                                       predicted_size += 3;\r
-                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)\r
-                               {\r
-                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       require_send = 0;\r
-                                       first_unsent = cmd;\r
-                               }\r
-                               if (cur_state != TAP_RTI)\r
-                               {\r
-                                       /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-                                       BUFFER_ADD = 0x4b;\r
-                                       /* scan 7 bit */\r
-                                       BUFFER_ADD = 0x6;\r
-                                       /* TMS data bits */\r
-                                       BUFFER_ADD = TAP_MOVE(cur_state, TAP_RTI);\r
-                                       cur_state = TAP_RTI;\r
-                                       require_send = 1;\r
-                               }\r
-                               i = cmd->cmd.runtest->num_cycles;\r
-                               while (i > 0)\r
-                               {\r
-                                       /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-                                       BUFFER_ADD = 0x4b;\r
-                                       /* scan 7 bit */\r
-                                       BUFFER_ADD = (i > 7) ? 6 : (i - 1);\r
-                                       /* TMS data bits */\r
-                                       BUFFER_ADD = 0x0;\r
-                                       cur_state = TAP_RTI;\r
-                                       i -= (i > 7) ? 7 : i;\r
-                                       //DEBUG("added TMS scan (no read)");\r
-                               }\r
-                               if (cmd->cmd.runtest->end_state != -1)\r
-                                       ft2232_end_state(cmd->cmd.runtest->end_state);\r
-                               if (cur_state != end_state)\r
-                               {\r
-                                       /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-                                       BUFFER_ADD = 0x4b;\r
-                                       /* scan 7 bit */\r
-                                       BUFFER_ADD = 0x6;\r
-                                       /* TMS data bits */\r
-                                       BUFFER_ADD = TAP_MOVE(cur_state, end_state);\r
-                                       cur_state = end_state;\r
-                                       //DEBUG("added TMS scan (no read)");\r
-                               }\r
-                               require_send = 1;\r
-#ifdef _DEBUG_JTAG_IO_                         \r
-                               DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state);\r
-#endif\r
-                               break;\r
-                       case JTAG_STATEMOVE:\r
-                               /* only send the maximum buffer size that FT2232C can handle */\r
-                               predicted_size = 3;\r
-                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)\r
-                               {\r
-                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       require_send = 0;\r
-                                       first_unsent = cmd;\r
-                               }\r
-                               if (cmd->cmd.statemove->end_state != -1)\r
-                                       ft2232_end_state(cmd->cmd.statemove->end_state);\r
-                               /* command "Clock Data to TMS/CS Pin (no Read)" */\r
-                               BUFFER_ADD = 0x4b;\r
-                               /* scan 7 bit */\r
-                               BUFFER_ADD = 0x6;\r
-                               /* TMS data bits */\r
-                               BUFFER_ADD = TAP_MOVE(cur_state, end_state);\r
-                               //DEBUG("added TMS scan (no read)");\r
-                               cur_state = end_state;\r
-                               require_send = 1;\r
-#ifdef _DEBUG_JTAG_IO_                         \r
-                               DEBUG("statemove: %i", end_state);\r
-#endif\r
-                               break;\r
-                       case JTAG_PATHMOVE:\r
-                               /* only send the maximum buffer size that FT2232C can handle */\r
-                               predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7);\r
-                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)\r
-                               {\r
-                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       require_send = 0;\r
-                                       first_unsent = cmd;\r
-                               }\r
-                               ft2232_add_pathmove(cmd->cmd.pathmove);\r
-                               require_send = 1;\r
-#ifdef _DEBUG_JTAG_IO_                         \r
-                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);\r
-#endif\r
-                               break;\r
-                       case JTAG_SCAN:\r
-                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);\r
-                               type = jtag_scan_type(cmd->cmd.scan);\r
-                               predicted_size = ft2232_predict_scan_out(scan_size, type);\r
-                               if ((predicted_size + 1) > FT2232_BUFFER_SIZE)\r
-                               {\r
-                                       DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");\r
-                                       /* unsent commands before this */\r
-                                       if (first_unsent != cmd)\r
-                                               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                                       retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       \r
-                                       /* current command */\r
-                                       if (cmd->cmd.scan->end_state != -1)\r
-                                               ft2232_end_state(cmd->cmd.scan->end_state);\r
-                                       ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size);\r
-                                       require_send = 0;\r
-                                       first_unsent = cmd->next;\r
-                                       if (buffer)\r
-                                               free(buffer);\r
-                                       break;\r
-                               }\r
-                               else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)\r
-                               {\r
-                                       DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd);\r
-                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       require_send = 0;\r
-                                       first_unsent = cmd;\r
-                               }\r
-                               ft2232_expect_read += ft2232_predict_scan_in(scan_size, type);\r
-                               //DEBUG("new read size: %i", ft2232_expect_read);\r
-                               if (cmd->cmd.scan->end_state != -1)\r
-                                       ft2232_end_state(cmd->cmd.scan->end_state);\r
-                               ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);\r
-                               require_send = 1;\r
-                               if (buffer)\r
-                                       free(buffer);\r
-#ifdef _DEBUG_JTAG_IO_                         \r
-                               DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state);\r
-#endif\r
-                               break;\r
-                       case JTAG_SLEEP:\r
-                               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                                       retval = ERROR_JTAG_QUEUE_FAILED;\r
-                               first_unsent = cmd->next;\r
-                               jtag_sleep(cmd->cmd.sleep->us);\r
-#ifdef _DEBUG_JTAG_IO_                         \r
-                               DEBUG("sleep %i usec", cmd->cmd.sleep->us);\r
-#endif\r
-                               break;\r
-                       default:\r
-                               ERROR("BUG: unknown JTAG command type encountered");\r
-                               exit(-1);\r
-               }\r
-               cmd = cmd->next;\r
-       }\r
-\r
-       if (require_send > 0)\r
-               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)\r
-                       retval = ERROR_JTAG_QUEUE_FAILED;\r
-\r
-       return retval;\r
-}\r
-\r
-#if BUILD_FT2232_FTD2XX == 1\r
-static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int *try_more)\r
-{\r
-       FT_STATUS status;\r
-       DWORD openex_flags = 0;\r
-       char *openex_string = NULL;\r
-       u8 latency_timer;\r
-\r
-       DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)",\r
-           ft2232_layout, vid, pid);\r
-\r
-#if IS_WIN32 == 0\r
-       /* Add non-standard Vid/Pid to the linux driver */\r
-       if ((status = FT_SetVIDPID(vid, pid)) != FT_OK)\r
-       {\r
-               WARNING("couldn't add %4.4x:%4.4x",\r
-                   vid, pid);\r
-       }\r
-#endif\r
-\r
-       if (ft2232_device_desc && ft2232_serial)\r
-       {\r
-               WARNING("can't open by device description and serial number, giving precedence to serial");\r
-               ft2232_device_desc = NULL;\r
-       }\r
-       \r
-       if (ft2232_device_desc)\r
-       {\r
-               openex_string = ft2232_device_desc;\r
-               openex_flags = FT_OPEN_BY_DESCRIPTION;\r
-       }\r
-       else if (ft2232_serial)\r
-       {\r
-               openex_string = ft2232_serial;\r
-               openex_flags = FT_OPEN_BY_SERIAL_NUMBER;\r
-       }\r
-       else\r
-       {\r
-               ERROR("neither device description nor serial number specified");\r
-               ERROR("please add \"ft2232_device_desc <string>\" or \"ft2232_serial <string>\" to your .cfg file");\r
-               \r
-               return ERROR_JTAG_INIT_FAILED;  \r
-       }\r
-\r
-       if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK)\r
-       {\r
-               DWORD num_devices;\r
-               \r
-               if (more) {\r
-                       WARNING("unable to open ftdi device (trying more): %lu",\r
-                           status);\r
-                       *try_more = 1;\r
-                       return ERROR_JTAG_INIT_FAILED;\r
-               }\r
-               ERROR("unable to open ftdi device: %lu", status);\r
-               status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);\r
-               if (status == FT_OK)\r
-               {\r
-                       char **desc_array = malloc(sizeof(char*) * (num_devices + 1));\r
-                       int i;\r
-\r
-                       for (i = 0; i < num_devices; i++)\r
-                               desc_array[i] = malloc(64);\r
-                       desc_array[num_devices] = NULL;\r
-\r
-                       status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags);\r
-\r
-                       if (status == FT_OK)\r
-                       {\r
-                               ERROR("ListDevices: %lu\n", num_devices);\r
-                               for (i = 0; i < num_devices; i++)\r
-                                       ERROR("%i: %s", i, desc_array[i]);\r
-                       }\r
-                       \r
-                       for (i = 0; i < num_devices; i++)\r
-                               free(desc_array[i]);\r
-                       free(desc_array);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("ListDevices: NONE\n");\r
-               }\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK)\r
-       {\r
-               ERROR("unable to set latency timer: %lu", status);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)\r
-       {\r
-               ERROR("unable to get latency timer: %lu", status);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       else\r
-       {\r
-               DEBUG("current latency timer: %i", latency_timer);\r
-       }\r
-       \r
-       if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)\r
-       {\r
-               ERROR("unable to set timeouts: %lu", status);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK)\r
-       {\r
-               ERROR("unable to enable bit i/o mode: %lu", status);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-static int ft2232_purge_ftd2xx(void)\r
-{\r
-       FT_STATUS status;\r
-\r
-       if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)\r
-       {\r
-               ERROR("error purging ftd2xx device: %lu", status);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-#endif /* BUILD_FT2232_FTD2XX == 1 */\r
-\r
-#if BUILD_FT2232_LIBFTDI == 1\r
-static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int *try_more)\r
-{\r
-       u8 latency_timer;\r
-\r
-       DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)",\r
-           ft2232_layout, vid, pid);\r
-\r
-       if (ftdi_init(&ftdic) < 0)\r
-               return ERROR_JTAG_INIT_FAILED;\r
-\r
-       /* context, vendor id, product id */\r
-       if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc,\r
-           ft2232_serial) < 0) {\r
-               if (more)\r
-                       WARNING("unable to open ftdi device (trying more): %s",\r
-                            ftdic.error_str);\r
-               else\r
-                       ERROR("unable to open ftdi device: %s", ftdic.error_str);\r
-               *try_more = 1;\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)\r
-       {\r
-               ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       if (ftdi_usb_reset(&ftdic) < 0)\r
-       {\r
-               ERROR("unable to reset ftdi device");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0)\r
-       {\r
-               ERROR("unable to set latency timer");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)\r
-       {\r
-               ERROR("unable to get latency timer");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       else\r
-       {\r
-               DEBUG("current latency timer: %i", latency_timer);\r
-       }\r
-\r
-       ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-static int ft2232_purge_libftdi(void)\r
-{\r
-       if (ftdi_usb_purge_buffers(&ftdic) < 0)\r
-       {\r
-               ERROR("ftdi_purge_buffers: %s", ftdic.error_str);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-#endif /* BUILD_FT2232_LIBFTDI == 1 */\r
-\r
-int ft2232_init(void)\r
-{\r
-       u8 buf[1];\r
-       int retval;\r
-       u32 bytes_written;\r
-       ft2232_layout_t *cur_layout = ft2232_layouts;\r
-       int i;\r
-       \r
-       if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0))\r
-       {\r
-               ft2232_layout = "usbjtag";\r
-               WARNING("No ft2232 layout specified, using default 'usbjtag'");\r
-       }\r
-       \r
-       while (cur_layout->name)\r
-       {\r
-               if (strcmp(cur_layout->name, ft2232_layout) == 0)\r
-               {\r
-                       layout = cur_layout;\r
-                       break;\r
-               }\r
-               cur_layout++;\r
-       }\r
-\r
-       if (!layout)\r
-       {\r
-               ERROR("No matching layout found for %s", ft2232_layout);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       for (i = 0; 1; i++) {\r
-               /*\r
-                * "more indicates that there are more IDs to try, so we should\r
-                * not print an error for an ID mismatch (but for anything\r
-                * else, we should).\r
-                *\r
-                * try_more indicates that the error code returned indicates an\r
-                * ID mismatch (and nothing else) and that we should proceeed\r
-                * with the next ID pair.\r
-                */\r
-               int more = ft2232_vid[i+1] || ft2232_pid[i+1];\r
-               int try_more = 0;\r
-\r
-#if BUILD_FT2232_FTD2XX == 1\r
-               retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i],\r
-                   more, &try_more);\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-               retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i],\r
-                   more, &try_more);\r
-#endif \r
-               if (retval >= 0)\r
-                       break;\r
-               if (!more || !try_more)\r
-                       return retval;\r
-       }\r
-\r
-       ft2232_buffer_size = 0;\r
-       ft2232_buffer = malloc(FT2232_BUFFER_SIZE);\r
-\r
-       if (layout->init() != ERROR_OK)\r
-               return ERROR_JTAG_INIT_FAILED;\r
-\r
-       ft2232_speed(jtag_speed);\r
-\r
-       buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */\r
-       if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1))\r
-       {\r
-               ERROR("couldn't write to FT2232 to disable loopback");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-#if BUILD_FT2232_FTD2XX == 1\r
-       return ft2232_purge_ftd2xx();\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-       return ft2232_purge_libftdi();\r
-#endif \r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbjtag_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x08;\r
-       low_direction = 0x0b;\r
-       \r
-       if (strcmp(ft2232_layout, "usbjtag") == 0)\r
-       {\r
-               nTRST = 0x10;\r
-               nTRSTnOE = 0x10;\r
-               nSRST = 0x40;\r
-               nSRSTnOE = 0x40;\r
-       }\r
-       else if (strcmp(ft2232_layout, "signalyzer") == 0)\r
-       {\r
-               nTRST = 0x10;\r
-               nTRSTnOE = 0x10;\r
-               nSRST = 0x20;\r
-               nSRSTnOE = 0x20;\r
-       }\r
-       else if (strcmp(ft2232_layout, "evb_lm3s811") == 0)\r
-       {\r
-               nTRST = 0x0;\r
-               nTRSTnOE = 0x00;\r
-               nSRST = 0x20;\r
-               nSRSTnOE = 0x20;\r
-               low_output = 0x88;\r
-               low_direction = 0x8b;\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout);\r
-               return ERROR_JTAG_INIT_FAILED;  \r
-       }\r
-       \r
-       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-       {\r
-               low_direction &= ~nTRSTnOE; /* nTRST input */\r
-               low_output &= ~nTRST; /* nTRST = 0 */\r
-       }\r
-       else\r
-       {\r
-               low_direction |= nTRSTnOE; /* nTRST output */\r
-               low_output |= nTRST; /* nTRST = 1 */\r
-       }\r
-       \r
-       if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-       {\r
-               low_direction |= nSRSTnOE; /* nSRST output */\r
-               low_output |= nSRST; /* nSRST = 1 */\r
-       }\r
-       else\r
-       {\r
-               low_direction &= ~nSRSTnOE; /* nSRST input */\r
-               low_output &= ~nSRST; /* nSRST = 0 */\r
-       }\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, xRST high) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'USBJTAG' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int jtagkey_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x08;\r
-       low_direction = 0x1b;\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       if (strcmp(layout->name, "jtagkey") == 0)\r
-       {\r
-               nTRST = 0x01;\r
-               nTRSTnOE = 0x4;\r
-               nSRST = 0x02;\r
-               nSRSTnOE = 0x08;\r
-       }\r
-       else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) ||\r
-               (strcmp(layout->name, "oocdlink") == 0))\r
-       {\r
-               nTRST = 0x02;\r
-               nTRSTnOE = 0x1;\r
-               nSRST = 0x08;\r
-               nSRSTnOE = 0x04;\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: jtagkey_init called for non jtagkey layout");\r
-               exit(-1);\r
-       }\r
-       \r
-       high_output = 0x0;\r
-       high_direction = 0x0f;\r
-\r
-       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-       {\r
-               high_output |= nTRSTnOE;\r
-               high_output &= ~nTRST;\r
-       }\r
-       else\r
-       {\r
-               high_output &= ~nTRSTnOE;\r
-               high_output |= nTRST;\r
-       }\r
-       \r
-       if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-       {\r
-               high_output &= ~nSRSTnOE;\r
-               high_output |= nSRST;\r
-       }\r
-       else\r
-       {\r
-               high_output |= nSRSTnOE;\r
-               high_output &= ~nSRST;\r
-       }\r
-       \r
-       /* initialize high port */\r
-       buf[0] = 0x82; /* command "set data bits high byte" */\r
-       buf[1] = high_output; /* value */\r
-       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int olimex_jtag_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x08;\r
-       low_direction = 0x1b;\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       nTRST = 0x01;\r
-       nTRSTnOE = 0x4;\r
-       nSRST = 0x02;\r
-       nSRSTnOE = 0x00; /* no output enable for nSRST */\r
-\r
-       high_output = 0x0;\r
-       high_direction = 0x0f;\r
-\r
-       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)\r
-       {\r
-               high_output |= nTRSTnOE;\r
-               high_output &= ~nTRST;\r
-       }\r
-       else\r
-       {\r
-               high_output &= ~nTRSTnOE;\r
-               high_output |= nTRST;\r
-       }\r
-       \r
-       if (jtag_reset_config & RESET_SRST_PUSH_PULL)\r
-       {\r
-               ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD");\r
-       }\r
-       else\r
-       {\r
-               high_output &= ~nSRST;\r
-       }\r
-       \r
-       /* turn red LED on */\r
-       high_output |= 0x08;\r
-       \r
-       /* initialize high port */\r
-       buf[0] = 0x82; /* command "set data bits high byte" */\r
-       buf[1] = high_output; /* value */\r
-       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int flyswatter_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x18;\r
-       low_direction = 0xfb;\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE[12]=out, n[ST]srst=out */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       nTRST = 0x10;\r
-       nTRSTnOE = 0x0; /* not output enable for nTRST */\r
-       nSRST = 0x20;\r
-       nSRSTnOE = 0x00; /* no output enable for nSRST */\r
-\r
-       high_output = 0x00;\r
-       high_direction = 0x0c;\r
-\r
-       /* turn red LED1 on, LED2 off */\r
-       high_output |= 0x08;\r
-       \r
-       /* initialize high port */\r
-       buf[0] = 0x82; /* command "set data bits high byte" */\r
-       buf[1] = high_output; /* value */\r
-       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int turtle_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x08;\r
-       low_direction = 0x5b;\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       nSRST = 0x40;\r
-       \r
-       high_output = 0x00;\r
-       high_direction = 0x0C;\r
-       \r
-       /* initialize high port */\r
-       buf[0] = 0x82; /* command "set data bits high byte" */\r
-       buf[1] = high_output;\r
-       buf[2] = high_direction;\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int comstick_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x08;\r
-       low_direction = 0x0b;\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'comstick' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       nTRST = 0x01;\r
-       nTRSTnOE = 0x00; /* no output enable for nTRST */\r
-       nSRST = 0x02;\r
-       nSRSTnOE = 0x00; /* no output enable for nSRST */\r
-       \r
-       high_output = 0x03;\r
-       high_direction = 0x03;\r
-       \r
-       /* initialize high port */\r
-       buf[0] = 0x82; /* command "set data bits high byte" */\r
-       buf[1] = high_output;\r
-       buf[2] = high_direction;\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'comstick' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int stm32stick_init(void)\r
-{\r
-       u8 buf[3];\r
-       u32 bytes_written;\r
-       \r
-       low_output = 0x88;\r
-       low_direction = 0x8b;\r
-       \r
-       /* initialize low byte for jtag */\r
-       buf[0] = 0x80; /* command "set data bits low byte" */\r
-       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */\r
-       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-               \r
-       nTRST = 0x01;\r
-       nTRSTnOE = 0x00; /* no output enable for nTRST */\r
-       nSRST = 0x80;\r
-       nSRSTnOE = 0x00; /* no output enable for nSRST */\r
-       \r
-       high_output = 0x01;\r
-       high_direction = 0x03;\r
-       \r
-       /* initialize high port */\r
-       buf[0] = 0x82; /* command "set data bits high byte" */\r
-       buf[1] = high_output;\r
-       buf[2] = high_direction;\r
-       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);\r
-       \r
-       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))\r
-       {\r
-               ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); \r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-void olimex_jtag_blink(void)\r
-{\r
-       /* Olimex ARM-USB-OCD has a LED connected to ACBUS3\r
-        * ACBUS3 is bit 3 of the GPIOH port\r
-        */\r
-       if (high_output & 0x08)\r
-       {\r
-               /* set port pin high */\r
-               high_output &= 0x07;\r
-       }\r
-       else\r
-       {\r
-               /* set port pin low */\r
-               high_output |= 0x08;\r
-       }\r
-       \r
-       BUFFER_ADD = 0x82;\r
-       BUFFER_ADD = high_output;\r
-       BUFFER_ADD = high_direction;\r
-}\r
-\r
-void turtle_jtag_blink(void)\r
-{\r
-       /* \r
-   * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3\r
-        */\r
-       if (high_output & 0x08)\r
-       {\r
-               high_output = 0x04;\r
-       }\r
-       else\r
-       {\r
-               high_output = 0x08;\r
-       }\r
-       \r
-       BUFFER_ADD = 0x82;\r
-       BUFFER_ADD = high_output;\r
-       BUFFER_ADD = high_direction;\r
-}\r
-\r
-\r
-int ft2232_quit(void)\r
-{\r
-#if BUILD_FT2232_FTD2XX == 1\r
-       FT_STATUS status;\r
-\r
-       status = FT_Close(ftdih);\r
-#elif BUILD_FT2232_LIBFTDI == 1\r
-       ftdi_disable_bitbang(&ftdic);\r
-       \r
-       ftdi_usb_close(&ftdic);\r
-       \r
-       ftdi_deinit(&ftdic);\r
-#endif\r
-\r
-       free(ft2232_buffer);\r
-       ft2232_buffer = NULL;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               ft2232_device_desc = strdup(args[0]);\r
-       }\r
-       else\r
-       {\r
-               ERROR("expected exactly one argument to ft2232_device_desc <description>");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               ft2232_serial = strdup(args[0]);\r
-       }\r
-       else\r
-       {\r
-               ERROR("expected exactly one argument to ft2232_serial <serial-number>");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 0)\r
-               return ERROR_OK;\r
-\r
-       ft2232_layout = malloc(strlen(args[0]) + 1);\r
-       strcpy(ft2232_layout, args[0]);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int i;\r
-\r
-       if (argc > MAX_USB_IDS*2) {\r
-               WARNING("ignoring extra IDs in ft2232_vid_pid "\r
-                   "(maximum is %d pairs)", MAX_USB_IDS);\r
-               argc = MAX_USB_IDS*2;\r
-       }\r
-       if (argc < 2 || (argc & 1))\r
-       {\r
-               WARNING("incomplete ft2232_vid_pid configuration directive");\r
-               if (argc < 2)\r
-                       return ERROR_OK;\r
-       }\r
-\r
-       for (i = 0; i+1 < argc; i += 2) {\r
-               ft2232_vid[i >> 1] = strtol(args[i], NULL, 0);\r
-               ft2232_pid[i >> 1] = strtol(args[i+1], NULL, 0);\r
-       }\r
-       /*\r
-        * Explicitly terminate, in case there are multiples instances of\r
-        * ft2232_vid_pid.\r
-        */\r
-       ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               ft2232_latency = atoi(args[0]);\r
-       }\r
-       else\r
-       {\r
-               ERROR("expected exactly one argument to ft2232_latency <ms>");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2004, 2006 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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
+
+#if IS_CYGWIN == 1
+#include "windows.h"
+#undef ERROR
+#endif
+
+#include "replacements.h"
+
+/* project specific includes */
+#include "log.h"
+#include "types.h"
+#include "jtag.h"
+#include "configuration.h"
+#include "time_support.h"
+
+/* system includes */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* FT2232 access library includes */
+#if BUILD_FT2232_FTD2XX == 1
+#include <ftd2xx.h>
+#elif BUILD_FT2232_LIBFTDI == 1
+#include <ftdi.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+
+/* enable this to debug io latency
+ */
+#if 0
+#define _DEBUG_USB_IO_
+#endif
+
+/* enable this to debug communication
+ */
+#if 0
+#define _DEBUG_USB_COMMS_
+#endif
+
+int ft2232_execute_queue(void);
+
+int ft2232_speed(int speed);
+int ft2232_register_commands(struct command_context_s *cmd_ctx);
+int ft2232_init(void);
+int ft2232_quit(void);
+
+int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+char *ft2232_device_desc = NULL;
+char *ft2232_serial = NULL;
+char *ft2232_layout = NULL;
+unsigned char ft2232_latency = 2;
+
+#define MAX_USB_IDS    8
+/* vid = pid = 0 marks the end of the list */
+static u16 ft2232_vid[MAX_USB_IDS+1] = { 0x0403, 0 };
+static u16 ft2232_pid[MAX_USB_IDS+1] = { 0x6010, 0 };
+
+typedef struct ft2232_layout_s
+{
+       char* name;
+       int(*init)(void);
+       void(*reset)(int trst, int srst);
+       void(*blink)(void);
+} ft2232_layout_t;
+
+/* init procedures for supported layouts */
+int usbjtag_init(void);
+int jtagkey_init(void);
+int olimex_jtag_init(void);
+int flyswatter_init(void);
+int turtle_init(void);
+int comstick_init(void);
+int stm32stick_init(void);
+
+/* reset procedures for supported layouts */
+void usbjtag_reset(int trst, int srst);
+void jtagkey_reset(int trst, int srst);
+void olimex_jtag_reset(int trst, int srst);
+void flyswatter_reset(int trst, int srst);
+void turtle_reset(int trst, int srst);
+void comstick_reset(int trst, int srst);
+void stm32stick_reset(int trst, int srst);
+
+/* blink procedures for layouts that support a blinking led */
+void olimex_jtag_blink(void);
+void turtle_jtag_blink(void);
+
+ft2232_layout_t ft2232_layouts[] =
+{
+       {"usbjtag", usbjtag_init, usbjtag_reset, NULL},
+       {"jtagkey", jtagkey_init, jtagkey_reset, NULL},
+       {"jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL},
+       {"oocdlink", jtagkey_init, jtagkey_reset, NULL},
+       {"signalyzer", usbjtag_init, usbjtag_reset, NULL},
+       {"evb_lm3s811", usbjtag_init, usbjtag_reset, NULL},
+       {"olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink},
+       {"flyswatter", flyswatter_init, flyswatter_reset, NULL},
+       {"turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink},
+       {"comstick", comstick_init, comstick_reset, NULL},
+       {"stm32stick", stm32stick_init, stm32stick_reset, NULL},
+       {NULL, NULL, NULL},
+};
+
+static u8 nTRST, nTRSTnOE, nSRST, nSRSTnOE;
+
+static ft2232_layout_t *layout;
+static u8 low_output = 0x0;
+static u8 low_direction = 0x0;
+static u8 high_output = 0x0;
+static u8 high_direction = 0x0;
+
+#if BUILD_FT2232_FTD2XX == 1
+static FT_HANDLE ftdih = NULL;
+#elif BUILD_FT2232_LIBFTDI == 1
+static struct ftdi_context ftdic;
+#endif
+
+static u8 *ft2232_buffer = NULL;
+static int ft2232_buffer_size = 0;
+static int ft2232_read_pointer = 0;
+static int ft2232_expect_read = 0;
+#define FT2232_BUFFER_SIZE     131072
+#define BUFFER_ADD ft2232_buffer[ft2232_buffer_size++]
+#define BUFFER_READ ft2232_buffer[ft2232_read_pointer++]
+
+jtag_interface_t ft2232_interface = 
+{
+       
+       .name = "ft2232",
+       
+       .execute_queue = ft2232_execute_queue,
+       
+       .speed = ft2232_speed,
+       .register_commands = ft2232_register_commands,
+       .init = ft2232_init,
+       .quit = ft2232_quit,
+};
+
+int ft2232_write(u8 *buf, int size, u32* bytes_written)
+{
+#if BUILD_FT2232_FTD2XX == 1
+       FT_STATUS status;
+       DWORD dw_bytes_written;
+       if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK)
+       {
+               *bytes_written = dw_bytes_written;
+               ERROR("FT_Write returned: %lu", status);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       else
+       {
+               *bytes_written = dw_bytes_written;
+               return ERROR_OK;        
+       }
+#elif BUILD_FT2232_LIBFTDI == 1
+       int retval;
+       if ((retval = ftdi_write_data(&ftdic, buf, size)) < 0)
+       {
+               *bytes_written = 0;
+               ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       else
+       {
+               *bytes_written = retval;
+               return ERROR_OK;        
+       }
+#endif
+}
+
+int ft2232_read(u8* buf, int size, u32* bytes_read)
+{
+#if BUILD_FT2232_FTD2XX == 1
+       DWORD dw_bytes_read;
+       FT_STATUS status;
+       int timeout = 5;
+       *bytes_read = 0;
+
+       while ((*bytes_read < size) && timeout--)
+       {
+               if ((status = FT_Read(ftdih, buf + *bytes_read, size - 
+                       *bytes_read, &dw_bytes_read)) != FT_OK)         
+               {
+                       *bytes_read = 0; 
+                       ERROR("FT_Read returned: %lu", status);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               *bytes_read += dw_bytes_read; 
+       }
+#elif BUILD_FT2232_LIBFTDI == 1
+       int retval;
+       int timeout = 100;
+       *bytes_read = 0;
+       
+       while ((*bytes_read < size) && timeout--)
+       {
+               if ((retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read)) < 0)
+               {
+                       *bytes_read = 0;
+                       ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic));
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+               *bytes_read += retval;
+       }
+#endif
+
+       if (*bytes_read < size)
+       {
+               ERROR("couldn't read the requested number of bytes from FT2232 device (%i < %i)", *bytes_read, size);
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+       
+       return ERROR_OK;
+}
+
+int ft2232_speed(int speed)
+{
+       u8 buf[3];
+       int retval;
+       u32 bytes_written;
+
+       buf[0] = 0x86; /* command "set divisor" */
+       buf[1] = speed & 0xff; /* valueL (0=6MHz, 1=3MHz, 2=2.0MHz, ...*/
+       buf[2] = (speed >> 8) & 0xff; /* valueH */
+       
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       if (((retval = ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't set FT2232 TCK speed");
+               return retval;
+       }
+
+       jtag_speed = speed;
+       
+       return ERROR_OK;
+}
+
+int ft2232_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "ft2232_device_desc", ft2232_handle_device_desc_command,
+               COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "ft2232_serial", ft2232_handle_serial_command,
+               COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "ft2232_layout", ft2232_handle_layout_command,
+               COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "ft2232_vid_pid", ft2232_handle_vid_pid_command,
+                                        COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "ft2232_latency", ft2232_handle_latency_command,
+                                        COMMAND_CONFIG, NULL);
+       return ERROR_OK;
+}
+
+void ft2232_end_state(enum tap_state state)
+{
+       if (tap_move_map[state] != -1)
+               end_state = state;
+       else
+       {
+               ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+}
+
+void ft2232_read_scan(enum scan_type type, u8* buffer, int scan_size)
+{
+       int num_bytes = ((scan_size + 7) / 8);
+       int bits_left = scan_size;
+       int cur_byte = 0;
+
+       while(num_bytes-- > 1)
+       {
+               buffer[cur_byte] = BUFFER_READ;
+               cur_byte++;
+               bits_left -= 8;
+       }
+
+       buffer[cur_byte] = 0x0;
+
+       if (bits_left > 1)
+       {
+               buffer[cur_byte] = BUFFER_READ >> 1;
+       }
+
+       buffer[cur_byte] = (buffer[cur_byte] | ((BUFFER_READ & 0x02) << 6)) >> (8 - bits_left);
+
+}
+
+void ft2232_debug_dump_buffer(void)
+{
+       int i;
+       char line[256];
+       char *line_p = line;
+       
+       for (i = 0; i < ft2232_buffer_size; i++)
+       {
+               line_p += snprintf(line_p, 256 - (line_p - line), "%2.2x ", ft2232_buffer[i]);
+               if (i % 16 == 15)
+               {
+                       DEBUG("%s", line);
+                       line_p = line;
+               }
+       }
+       
+       if (line_p != line)
+               DEBUG("%s", line);
+}
+
+int ft2232_send_and_recv(jtag_command_t *first, jtag_command_t *last)
+{
+       jtag_command_t *cmd;
+       u8 *buffer;
+       int scan_size;
+       enum scan_type type;
+       int retval;
+       u32 bytes_written;
+       u32 bytes_read;
+       
+#ifdef _DEBUG_USB_IO_
+       struct timeval start, inter, inter2, end;
+       struct timeval d_inter, d_inter2, d_end;
+#endif
+
+#ifdef _DEBUG_USB_COMMS_
+       DEBUG("write buffer (size %i):", ft2232_buffer_size);
+       ft2232_debug_dump_buffer();
+#endif
+
+#ifdef _DEBUG_USB_IO_
+       gettimeofday(&start, NULL);     
+#endif
+
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       
+#ifdef _DEBUG_USB_IO_
+       gettimeofday(&inter, NULL);     
+#endif
+       
+       if (ft2232_expect_read)
+       {
+               int timeout = 100;
+               ft2232_buffer_size = 0;
+               
+#ifdef _DEBUG_USB_IO_
+               gettimeofday(&inter2, NULL);    
+#endif
+               
+               if ((retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read)) != ERROR_OK)
+               {
+                       ERROR("couldn't read from FT2232");
+                       exit(-1);
+               }
+               
+#ifdef _DEBUG_USB_IO_
+               gettimeofday(&end, NULL);       
+
+               timeval_subtract(&d_inter, &inter, &start);
+               timeval_subtract(&d_inter2, &inter2, &start);
+               timeval_subtract(&d_end, &end, &start);
+
+               INFO("inter: %i.%i, inter2: %i.%i end: %i.%i", d_inter.tv_sec, d_inter.tv_usec, d_inter2.tv_sec, d_inter2.tv_usec, d_end.tv_sec, d_end.tv_usec);
+#endif
+       
+               
+               ft2232_buffer_size = bytes_read;
+               
+               if (ft2232_expect_read != ft2232_buffer_size)
+               {
+                       ERROR("ft2232_expect_read (%i) != ft2232_buffer_size (%i) (%i retries)", ft2232_expect_read, ft2232_buffer_size, 100 - timeout);
+                       ft2232_debug_dump_buffer();     
+
+                       exit(-1);
+               }
+
+#ifdef _DEBUG_USB_COMMS_
+               DEBUG("read buffer (%i retries): %i bytes", 100 - timeout, ft2232_buffer_size);
+               ft2232_debug_dump_buffer();
+#endif
+       }
+
+       ft2232_expect_read = 0;
+       ft2232_read_pointer = 0;
+       
+       /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
+        * that wasn't handled by a caller-provided error handler
+        */ 
+       retval = ERROR_OK;
+       
+       cmd = first;
+       while (cmd != last)
+       {
+               switch (cmd->type)
+               {
+                       case JTAG_SCAN:
+                               type = jtag_scan_type(cmd->cmd.scan);
+                               if (type != SCAN_OUT)
+                               {
+                                       scan_size = jtag_scan_size(cmd->cmd.scan);
+                                       buffer = calloc(CEIL(scan_size, 8), 1);
+                                       ft2232_read_scan(type, buffer, scan_size);
+                                       if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       free(buffer);
+                               }
+                               break;
+                       default:
+                               break;
+               }
+               cmd = cmd->next;
+       }
+       
+       ft2232_buffer_size = 0;
+
+       return retval;
+}
+
+void ft2232_add_pathmove(pathmove_command_t *cmd)
+{
+       int num_states = cmd->num_states;
+       u8 tms_byte;
+       int state_count;
+
+       state_count = 0;
+       while (num_states)
+       {
+               tms_byte = 0x0;
+               int bit_count = 0;
+               
+               /* command "Clock Data to TMS/CS Pin (no Read)" */
+               BUFFER_ADD = 0x4b;
+               /* number of states remaining */
+               BUFFER_ADD = (num_states % 7) - 1;
+               
+               while (num_states % 7)
+               {
+                       if (tap_transitions[cur_state].low == cmd->path[state_count])
+                               buf_set_u32(&tms_byte, bit_count++, 1, 0x0);
+                       else if (tap_transitions[cur_state].high == cmd->path[state_count])
+                               buf_set_u32(&tms_byte, bit_count++, 1, 0x1);
+                       else
+                       {
+                               ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
+                               exit(-1);
+                       }
+
+                       cur_state = cmd->path[state_count];
+                       state_count++;
+                       num_states--;
+               }
+               
+               BUFFER_ADD = tms_byte;
+       }
+       
+       end_state = cur_state;
+}
+
+void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
+{
+       int num_bytes = (scan_size + 7) / 8;
+       int bits_left = scan_size;
+       int cur_byte = 0;
+       int last_bit;
+
+       if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))
+       {
+               /* command "Clock Data to TMS/CS Pin (no Read)" */
+               BUFFER_ADD = 0x4b;
+               /* scan 7 bit */
+               BUFFER_ADD = 0x6;
+               /* TMS data bits */
+               if (ir_scan)
+               {
+                       BUFFER_ADD = TAP_MOVE(cur_state, TAP_SI);
+                       cur_state = TAP_SI;
+               }
+               else
+               {
+                       BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);
+                       cur_state = TAP_SD;
+               }
+               //DEBUG("added TMS scan (no read)");
+       }
+       
+       /* add command for complete bytes */
+       while (num_bytes > 1)
+       {
+               int thisrun_bytes;
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bytes In and Out LSB First */
+                       BUFFER_ADD = 0x39;
+                       //DEBUG("added TDI bytes (io %i)", num_bytes);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x19;
+                       //DEBUG("added TDI bytes (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x28;
+                       //DEBUG("added TDI bytes (i %i)", num_bytes);
+               }
+               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+               num_bytes -= thisrun_bytes;
+               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;
+               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;
+               if (type != SCAN_IN)
+               {
+                       /* add complete bytes */
+                       while(thisrun_bytes-- > 0)
+                       {
+                               BUFFER_ADD = buffer[cur_byte];
+                               cur_byte++;
+                               bits_left -= 8;
+                       }
+               }
+               else /* (type == SCAN_IN) */
+               {
+                       bits_left -= 8 * (thisrun_bytes);
+               }
+       }
+       
+       /* the most signifcant bit is scanned during TAP movement */
+       if (type != SCAN_IN)
+               last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
+       else
+               last_bit = 0;
+
+       /* process remaining bits but the last one */
+       if (bits_left > 1)
+       {
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = bits_left - 2;
+               if (type != SCAN_IN)
+                       BUFFER_ADD = buffer[cur_byte];
+       }
+
+       if ((ir_scan && (end_state == TAP_SI)) ||
+               (!ir_scan && (end_state == TAP_SD)))
+       {
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = 0x0;
+               BUFFER_ADD = last_bit;
+       }
+       else
+       {
+               /* move from Shift-IR/DR to end state */
+               if (type != SCAN_OUT)
+               {
+                       /* Clock Data to TMS/CS Pin with Read */
+                       BUFFER_ADD = 0x6b;
+                       //DEBUG("added TMS scan (read)");
+               }
+               else
+               {
+                       /* Clock Data to TMS/CS Pin (no Read) */
+                       BUFFER_ADD = 0x4b;
+                       //DEBUG("added TMS scan (no read)");
+               }
+               BUFFER_ADD = 0x6;
+               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
+               cur_state = end_state;
+       }
+}
+
+int ft2232_large_scan(scan_command_t *cmd, enum scan_type type, u8 *buffer, int scan_size)
+{
+       int num_bytes = (scan_size + 7) / 8;
+       int bits_left = scan_size;
+       int cur_byte = 0;
+       int last_bit;
+       u8 *receive_buffer = malloc(CEIL(scan_size, 8));
+       u8 *receive_pointer = receive_buffer;
+       u32 bytes_written;
+       u32 bytes_read;
+       int retval;
+       int thisrun_read = 0;
+       
+       if (cmd->ir_scan)
+       {
+               ERROR("BUG: large IR scans are not supported");
+               exit(-1);
+       }
+
+       if (cur_state != TAP_SD)
+       {
+               /* command "Clock Data to TMS/CS Pin (no Read)" */
+               BUFFER_ADD = 0x4b;
+               /* scan 7 bit */
+               BUFFER_ADD = 0x6;
+               /* TMS data bits */
+               BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);
+               cur_state = TAP_SD;
+       }
+       
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+       ft2232_buffer_size = 0;
+       
+       /* add command for complete bytes */
+       while (num_bytes > 1)
+       {
+               int thisrun_bytes;
+               
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bytes In and Out LSB First */
+                       BUFFER_ADD = 0x39;
+                       //DEBUG("added TDI bytes (io %i)", num_bytes);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x19;
+                       //DEBUG("added TDI bytes (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x28;
+                       //DEBUG("added TDI bytes (i %i)", num_bytes);
+               }
+               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+               thisrun_read = thisrun_bytes;
+               num_bytes -= thisrun_bytes;
+               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;
+               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;
+               if (type != SCAN_IN)
+               {
+                       /* add complete bytes */
+                       while(thisrun_bytes-- > 0)
+                       {
+                               BUFFER_ADD = buffer[cur_byte];
+                               cur_byte++;
+                               bits_left -= 8;
+                       }
+               }
+               else /* (type == SCAN_IN) */
+               {
+                       bits_left -= 8 * (thisrun_bytes);
+               }
+
+               if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+               {
+                       ERROR("couldn't write MPSSE commands to FT2232");
+                       exit(-1);
+               }
+               DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+               ft2232_buffer_size = 0;
+               
+               if (type != SCAN_OUT)
+               {
+                       if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)
+                       {
+                               ERROR("couldn't read from FT2232");
+                               exit(-1);
+                       }
+                       DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);
+                       receive_pointer += bytes_read;
+               }
+       }
+       
+       thisrun_read = 0;
+       
+       /* the most signifcant bit is scanned during TAP movement */
+       if (type != SCAN_IN)
+               last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
+       else
+               last_bit = 0;
+
+       /* process remaining bits but the last one */
+       if (bits_left > 1)
+       {
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = bits_left - 2;
+               if (type != SCAN_IN)
+                       BUFFER_ADD = buffer[cur_byte];
+                       
+               if (type != SCAN_OUT)
+                       thisrun_read += 2;
+       }
+
+       if (end_state == TAP_SD)
+       {
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = 0x0;
+               BUFFER_ADD = last_bit;
+       }
+       else
+       {
+               /* move from Shift-IR/DR to end state */
+               if (type != SCAN_OUT)
+               {
+                       /* Clock Data to TMS/CS Pin with Read */
+                       BUFFER_ADD = 0x6b;
+                       //DEBUG("added TMS scan (read)");
+               }
+               else
+               {
+                       /* Clock Data to TMS/CS Pin (no Read) */
+                       BUFFER_ADD = 0x4b;
+                       //DEBUG("added TMS scan (no read)");
+               }
+               BUFFER_ADD = 0x6;
+               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
+               cur_state = end_state;
+       }
+       
+       if (type != SCAN_OUT)
+               thisrun_read += 1;
+       
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+       ft2232_buffer_size = 0;
+       
+       if (type != SCAN_OUT)
+       {
+               if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)
+               {
+                       ERROR("couldn't read from FT2232");
+                       exit(-1);
+               }
+               DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);
+               receive_pointer += bytes_read;
+       }
+       
+       return ERROR_OK;
+}
+
+int ft2232_predict_scan_out(int scan_size, enum scan_type type)
+{
+       int predicted_size = 3;
+       int num_bytes = (scan_size - 1) / 8;
+       
+       if (cur_state != TAP_SD)
+               predicted_size += 3;
+       
+       if (type == SCAN_IN)    /* only from device to host */
+       {
+               /* complete bytes */
+               predicted_size += (CEIL(num_bytes, 65536)) * 3;
+               /* remaining bits - 1 (up to 7) */
+               predicted_size += ((scan_size - 1) % 8) ? 2 : 0;
+       }
+       else                                    /* host to device, or bidirectional */
+       {
+               /* complete bytes */
+               predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3;
+               /* remaining bits -1 (up to 7) */
+               predicted_size += ((scan_size - 1) % 8) ? 3 : 0;
+       }
+
+       return predicted_size;
+}
+
+int ft2232_predict_scan_in(int scan_size, enum scan_type type)
+{
+       int predicted_size = 0;
+       
+       if (type != SCAN_OUT)
+       {
+               /* complete bytes */
+               predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) - 1) : 0;
+               /* remaining bits - 1 */
+               predicted_size += ((scan_size - 1) % 8) ? 1 : 0;
+               /* last bit (from TMS scan) */
+               predicted_size += 1;
+       }
+       
+       //DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size);
+
+       return predicted_size;
+}
+
+void usbjtag_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+                       low_direction |= nTRSTnOE;      /* switch to output pin (output is low) */
+               else
+                       low_output &= ~nTRST;   /* switch output low */
+       }
+       else if (trst == 0)
+       {
+               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+                       low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal and external pullup) */
+               else
+                       low_output |= nTRST; /* switch output high */
+       }
+
+       if (srst == 1)
+       {
+               if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+                       low_output &= ~nSRST;   /* switch output low */
+               else
+                       low_direction |= nSRSTnOE;      /* switch to output pin (output is low) */
+       }
+       else if (srst == 0)
+       {
+               if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+                       low_output |= nSRST;    /* switch output high */
+               else
+                       low_direction &= ~nSRSTnOE;     /* switch to input pin (high-Z) */
+       }
+       
+       /* command "set data bits low byte" */
+       BUFFER_ADD = 0x80;
+       BUFFER_ADD = low_output;
+       BUFFER_ADD = low_direction;
+
+}
+
+void jtagkey_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+                       high_output &= ~nTRSTnOE;
+               else
+                       high_output &= ~nTRST;
+       }
+       else if (trst == 0)
+       {
+               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+                       high_output |= nTRSTnOE;
+               else
+                       high_output |= nTRST;
+       }
+
+       if (srst == 1)
+       {
+               if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+                       high_output &= ~nSRST;
+               else
+                       high_output &= ~nSRSTnOE;
+       }
+       else if (srst == 0)
+       {
+               if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+                       high_output |= nSRST;
+               else
+                       high_output |= nSRSTnOE;
+       }
+       
+       /* command "set data bits high byte" */
+       BUFFER_ADD = 0x82;
+       BUFFER_ADD = high_output;
+       BUFFER_ADD = high_direction;
+       DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
+}
+
+void olimex_jtag_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+                       high_output &= ~nTRSTnOE;
+               else
+                       high_output &= ~nTRST;
+       }
+       else if (trst == 0)
+       {
+               if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+                       high_output |= nTRSTnOE;
+               else
+                       high_output |= nTRST;
+       }
+
+    if (srst == 1)
+    {
+        high_output |= nSRST;
+    }
+    else if (srst == 0)
+    {
+        high_output &= ~nSRST;
+    }
+
+    /* command "set data bits high byte" */
+    BUFFER_ADD = 0x82;
+    BUFFER_ADD = high_output;
+    BUFFER_ADD = high_direction;
+    DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
+}
+
+void flyswatter_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               low_output &= ~nTRST;
+       }
+       else if (trst == 0)
+       {
+               low_output |= nTRST;
+       }
+
+    if (srst == 1)
+    {
+        low_output |= nSRST;
+    }
+    else if (srst == 0)
+    {
+        low_output &= ~nSRST;
+    }
+
+    /* command "set data bits low byte" */
+    BUFFER_ADD = 0x80;
+    BUFFER_ADD = low_output;
+    BUFFER_ADD = low_direction;
+    DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", trst, srst, low_output, low_direction);
+}
+
+void turtle_reset(int trst, int srst)
+{
+       trst = trst;
+       
+       if (srst == 1)
+       {
+               low_output |= nSRST;
+       }
+       else if (srst == 0)
+       {
+               low_output &= ~nSRST;
+       }
+       
+       /* command "set data bits low byte" */
+       BUFFER_ADD = 0x80;
+       BUFFER_ADD = low_output;
+       BUFFER_ADD = low_direction;
+       DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", srst, low_output, low_direction);
+}
+
+void comstick_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               high_output &= ~nTRST;
+       }
+       else if (trst == 0)
+       {
+               high_output |= nTRST;
+       }
+
+    if (srst == 1)
+    {
+        high_output &= ~nSRST;
+    }
+    else if (srst == 0)
+    {
+        high_output |= nSRST;
+    }
+       
+       /* command "set data bits high byte" */
+       BUFFER_ADD = 0x82;
+       BUFFER_ADD = high_output;
+       BUFFER_ADD = high_direction;
+       DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
+}
+
+void stm32stick_reset(int trst, int srst)
+{
+       if (trst == 1)
+       {
+               cur_state = TAP_TLR;
+               high_output &= ~nTRST;
+       }
+       else if (trst == 0)
+       {
+               high_output |= nTRST;
+       }
+
+    if (srst == 1)
+    {
+        low_output &= ~nSRST;
+    }
+    else if (srst == 0)
+    {
+        low_output |= nSRST;
+    }
+       
+       /* command "set data bits low byte" */
+       BUFFER_ADD = 0x80;
+       BUFFER_ADD = low_output;
+       BUFFER_ADD = low_direction;
+       
+       /* command "set data bits high byte" */
+       BUFFER_ADD = 0x82;
+       BUFFER_ADD = high_output;
+       BUFFER_ADD = high_direction;
+       DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", trst, srst, high_output, high_direction);
+}
+
+int ft2232_execute_queue()
+{
+       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
+       jtag_command_t *first_unsent = cmd;     /* next command that has to be sent */
+       u8 *buffer;
+       int scan_size;  /* size of IR or DR scan */
+       enum scan_type type;
+       int i;
+       int predicted_size = 0;
+       int require_send = 0;
+       int retval;
+       
+       /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check
+        * that wasn't handled by a caller-provided error handler
+        */ 
+       retval = ERROR_OK;
+
+       ft2232_buffer_size = 0;
+       ft2232_expect_read = 0;
+       
+       /* blink, if the current layout has that feature */
+       if (layout->blink)
+               layout->blink();
+
+       while (cmd)
+       {
+               switch(cmd->type)
+               {
+                       case JTAG_END_STATE:
+                               if (cmd->cmd.end_state->end_state != -1)
+                                       ft2232_end_state(cmd->cmd.end_state->end_state);
+                               break;
+                       case JTAG_RESET:
+                               /* only send the maximum buffer size that FT2232C can handle */
+                               predicted_size = 3;
+                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               {
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       require_send = 0;
+                                       first_unsent = cmd;
+                               }
+
+                               layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               require_send = 1;
+                               
+#ifdef _DEBUG_JTAG_IO_                         
+                               DEBUG("trst: %i, srst: %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+                               break;
+                       case JTAG_RUNTEST:
+                               /* only send the maximum buffer size that FT2232C can handle */
+                               predicted_size = 0;
+                               if (cur_state != TAP_RTI)
+                                       predicted_size += 3;
+                               predicted_size += 3 * CEIL(cmd->cmd.runtest->num_cycles, 7);
+                               if ((cmd->cmd.runtest->end_state != -1) && (cmd->cmd.runtest->end_state != TAP_RTI))
+                                       predicted_size += 3;
+                               if ((cmd->cmd.runtest->end_state == -1) && (end_state != TAP_RTI))
+                                       predicted_size += 3;
+                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               {
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       require_send = 0;
+                                       first_unsent = cmd;
+                               }
+                               if (cur_state != TAP_RTI)
+                               {
+                                       /* command "Clock Data to TMS/CS Pin (no Read)" */
+                                       BUFFER_ADD = 0x4b;
+                                       /* scan 7 bit */
+                                       BUFFER_ADD = 0x6;
+                                       /* TMS data bits */
+                                       BUFFER_ADD = TAP_MOVE(cur_state, TAP_RTI);
+                                       cur_state = TAP_RTI;
+                                       require_send = 1;
+                               }
+                               i = cmd->cmd.runtest->num_cycles;
+                               while (i > 0)
+                               {
+                                       /* command "Clock Data to TMS/CS Pin (no Read)" */
+                                       BUFFER_ADD = 0x4b;
+                                       /* scan 7 bit */
+                                       BUFFER_ADD = (i > 7) ? 6 : (i - 1);
+                                       /* TMS data bits */
+                                       BUFFER_ADD = 0x0;
+                                       cur_state = TAP_RTI;
+                                       i -= (i > 7) ? 7 : i;
+                                       //DEBUG("added TMS scan (no read)");
+                               }
+                               if (cmd->cmd.runtest->end_state != -1)
+                                       ft2232_end_state(cmd->cmd.runtest->end_state);
+                               if (cur_state != end_state)
+                               {
+                                       /* command "Clock Data to TMS/CS Pin (no Read)" */
+                                       BUFFER_ADD = 0x4b;
+                                       /* scan 7 bit */
+                                       BUFFER_ADD = 0x6;
+                                       /* TMS data bits */
+                                       BUFFER_ADD = TAP_MOVE(cur_state, end_state);
+                                       cur_state = end_state;
+                                       //DEBUG("added TMS scan (no read)");
+                               }
+                               require_send = 1;
+#ifdef _DEBUG_JTAG_IO_                         
+                               DEBUG("runtest: %i, end in %i", cmd->cmd.runtest->num_cycles, end_state);
+#endif
+                               break;
+                       case JTAG_STATEMOVE:
+                               /* only send the maximum buffer size that FT2232C can handle */
+                               predicted_size = 3;
+                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               {
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       require_send = 0;
+                                       first_unsent = cmd;
+                               }
+                               if (cmd->cmd.statemove->end_state != -1)
+                                       ft2232_end_state(cmd->cmd.statemove->end_state);
+                               /* command "Clock Data to TMS/CS Pin (no Read)" */
+                               BUFFER_ADD = 0x4b;
+                               /* scan 7 bit */
+                               BUFFER_ADD = 0x6;
+                               /* TMS data bits */
+                               BUFFER_ADD = TAP_MOVE(cur_state, end_state);
+                               //DEBUG("added TMS scan (no read)");
+                               cur_state = end_state;
+                               require_send = 1;
+#ifdef _DEBUG_JTAG_IO_                         
+                               DEBUG("statemove: %i", end_state);
+#endif
+                               break;
+                       case JTAG_PATHMOVE:
+                               /* only send the maximum buffer size that FT2232C can handle */
+                               predicted_size = 3 * CEIL(cmd->cmd.pathmove->num_states, 7);
+                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               {
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       require_send = 0;
+                                       first_unsent = cmd;
+                               }
+                               ft2232_add_pathmove(cmd->cmd.pathmove);
+                               require_send = 1;
+#ifdef _DEBUG_JTAG_IO_                         
+                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+#endif
+                               break;
+                       case JTAG_SCAN:
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+                               type = jtag_scan_type(cmd->cmd.scan);
+                               predicted_size = ft2232_predict_scan_out(scan_size, type);
+                               if ((predicted_size + 1) > FT2232_BUFFER_SIZE)
+                               {
+                                       DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");
+                                       /* unsent commands before this */
+                                       if (first_unsent != cmd)
+                                               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                                       retval = ERROR_JTAG_QUEUE_FAILED;
+                                       
+                                       /* current command */
+                                       if (cmd->cmd.scan->end_state != -1)
+                                               ft2232_end_state(cmd->cmd.scan->end_state);
+                                       ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size);
+                                       require_send = 0;
+                                       first_unsent = cmd->next;
+                                       if (buffer)
+                                               free(buffer);
+                                       break;
+                               }
+                               else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               {
+                                       DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", first_unsent, cmd);
+                                       if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       require_send = 0;
+                                       first_unsent = cmd;
+                               }
+                               ft2232_expect_read += ft2232_predict_scan_in(scan_size, type);
+                               //DEBUG("new read size: %i", ft2232_expect_read);
+                               if (cmd->cmd.scan->end_state != -1)
+                                       ft2232_end_state(cmd->cmd.scan->end_state);
+                               ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+                               require_send = 1;
+                               if (buffer)
+                                       free(buffer);
+#ifdef _DEBUG_JTAG_IO_                         
+                               DEBUG("%s scan, %i bit, end in %i", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, end_state);
+#endif
+                               break;
+                       case JTAG_SLEEP:
+                               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                                       retval = ERROR_JTAG_QUEUE_FAILED;
+                               first_unsent = cmd->next;
+                               jtag_sleep(cmd->cmd.sleep->us);
+#ifdef _DEBUG_JTAG_IO_                         
+                               DEBUG("sleep %i usec", cmd->cmd.sleep->us);
+#endif
+                               break;
+                       default:
+                               ERROR("BUG: unknown JTAG command type encountered");
+                               exit(-1);
+               }
+               cmd = cmd->next;
+       }
+
+       if (require_send > 0)
+               if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK)
+                       retval = ERROR_JTAG_QUEUE_FAILED;
+
+       return retval;
+}
+
+#if BUILD_FT2232_FTD2XX == 1
+static int ft2232_init_ftd2xx(u16 vid, u16 pid, int more, int *try_more)
+{
+       FT_STATUS status;
+       DWORD openex_flags = 0;
+       char *openex_string = NULL;
+       u8 latency_timer;
+
+       DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)",
+           ft2232_layout, vid, pid);
+
+#if IS_WIN32 == 0
+       /* Add non-standard Vid/Pid to the linux driver */
+       if ((status = FT_SetVIDPID(vid, pid)) != FT_OK)
+       {
+               WARNING("couldn't add %4.4x:%4.4x",
+                   vid, pid);
+       }
+#endif
+
+       if (ft2232_device_desc && ft2232_serial)
+       {
+               WARNING("can't open by device description and serial number, giving precedence to serial");
+               ft2232_device_desc = NULL;
+       }
+       
+       if (ft2232_device_desc)
+       {
+               openex_string = ft2232_device_desc;
+               openex_flags = FT_OPEN_BY_DESCRIPTION;
+       }
+       else if (ft2232_serial)
+       {
+               openex_string = ft2232_serial;
+               openex_flags = FT_OPEN_BY_SERIAL_NUMBER;
+       }
+       else
+       {
+               ERROR("neither device description nor serial number specified");
+               ERROR("please add \"ft2232_device_desc <string>\" or \"ft2232_serial <string>\" to your .cfg file");
+               
+               return ERROR_JTAG_INIT_FAILED;  
+       }
+
+       if ((status = FT_OpenEx(openex_string, openex_flags, &ftdih)) != FT_OK)
+       {
+               DWORD num_devices;
+               
+               if (more) {
+                       WARNING("unable to open ftdi device (trying more): %lu",
+                           status);
+                       *try_more = 1;
+                       return ERROR_JTAG_INIT_FAILED;
+               }
+               ERROR("unable to open ftdi device: %lu", status);
+               status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY);
+               if (status == FT_OK)
+               {
+                       char **desc_array = malloc(sizeof(char*) * (num_devices + 1));
+                       int i;
+
+                       for (i = 0; i < num_devices; i++)
+                               desc_array[i] = malloc(64);
+                       desc_array[num_devices] = NULL;
+
+                       status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags);
+
+                       if (status == FT_OK)
+                       {
+                               ERROR("ListDevices: %lu\n", num_devices);
+                               for (i = 0; i < num_devices; i++)
+                                       ERROR("%i: %s", i, desc_array[i]);
+                       }
+                       
+                       for (i = 0; i < num_devices; i++)
+                               free(desc_array[i]);
+                       free(desc_array);
+               }
+               else
+               {
+                       ERROR("ListDevices: NONE\n");
+               }
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if ((status = FT_SetLatencyTimer(ftdih, ft2232_latency)) != FT_OK)
+       {
+               ERROR("unable to set latency timer: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK)
+       {
+               ERROR("unable to get latency timer: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       else
+       {
+               DEBUG("current latency timer: %i", latency_timer);
+       }
+       
+       if ((status = FT_SetTimeouts(ftdih, 5000, 5000)) != FT_OK)
+       {
+               ERROR("unable to set timeouts: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if ((status = FT_SetBitMode(ftdih, 0x0b, 2)) != FT_OK)
+       {
+               ERROR("unable to enable bit i/o mode: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+static int ft2232_purge_ftd2xx(void)
+{
+       FT_STATUS status;
+
+       if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
+       {
+               ERROR("error purging ftd2xx device: %lu", status);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+#endif /* BUILD_FT2232_FTD2XX == 1 */
+
+#if BUILD_FT2232_LIBFTDI == 1
+static int ft2232_init_libftdi(u16 vid, u16 pid, int more, int *try_more)
+{
+       u8 latency_timer;
+
+       DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)",
+           ft2232_layout, vid, pid);
+
+       if (ftdi_init(&ftdic) < 0)
+               return ERROR_JTAG_INIT_FAILED;
+
+       /* context, vendor id, product id */
+       if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc,
+           ft2232_serial) < 0) {
+               if (more)
+                       WARNING("unable to open ftdi device (trying more): %s",
+                            ftdic.error_str);
+               else
+                       ERROR("unable to open ftdi device: %s", ftdic.error_str);
+               *try_more = 1;
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_set_interface(&ftdic, INTERFACE_A) < 0)
+       {
+               ERROR("unable to select FT2232 channel A: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_usb_reset(&ftdic) < 0)
+       {
+               ERROR("unable to reset ftdi device");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0)
+       {
+               ERROR("unable to set latency timer");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
+       {
+               ERROR("unable to get latency timer");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       else
+       {
+               DEBUG("current latency timer: %i", latency_timer);
+       }
+
+       ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */
+
+       return ERROR_OK;
+}
+
+static int ft2232_purge_libftdi(void)
+{
+       if (ftdi_usb_purge_buffers(&ftdic) < 0)
+       {
+               ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+#endif /* BUILD_FT2232_LIBFTDI == 1 */
+
+int ft2232_init(void)
+{
+       u8 buf[1];
+       int retval;
+       u32 bytes_written;
+       ft2232_layout_t *cur_layout = ft2232_layouts;
+       int i;
+       
+       if ((ft2232_layout == NULL) || (ft2232_layout[0] == 0))
+       {
+               ft2232_layout = "usbjtag";
+               WARNING("No ft2232 layout specified, using default 'usbjtag'");
+       }
+       
+       while (cur_layout->name)
+       {
+               if (strcmp(cur_layout->name, ft2232_layout) == 0)
+               {
+                       layout = cur_layout;
+                       break;
+               }
+               cur_layout++;
+       }
+
+       if (!layout)
+       {
+               ERROR("No matching layout found for %s", ft2232_layout);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       for (i = 0; 1; i++) {
+               /*
+                * "more indicates that there are more IDs to try, so we should
+                * not print an error for an ID mismatch (but for anything
+                * else, we should).
+                *
+                * try_more indicates that the error code returned indicates an
+                * ID mismatch (and nothing else) and that we should proceeed
+                * with the next ID pair.
+                */
+               int more = ft2232_vid[i+1] || ft2232_pid[i+1];
+               int try_more = 0;
+
+#if BUILD_FT2232_FTD2XX == 1
+               retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i],
+                   more, &try_more);
+#elif BUILD_FT2232_LIBFTDI == 1
+               retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i],
+                   more, &try_more);
+#endif 
+               if (retval >= 0)
+                       break;
+               if (!more || !try_more)
+                       return retval;
+       }
+
+       ft2232_buffer_size = 0;
+       ft2232_buffer = malloc(FT2232_BUFFER_SIZE);
+
+       if (layout->init() != ERROR_OK)
+               return ERROR_JTAG_INIT_FAILED;
+
+       ft2232_speed(jtag_speed);
+
+       buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */
+       if (((retval = ft2232_write(buf, 1, &bytes_written)) != ERROR_OK) || (bytes_written != 1))
+       {
+               ERROR("couldn't write to FT2232 to disable loopback");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+#if BUILD_FT2232_FTD2XX == 1
+       return ft2232_purge_ftd2xx();
+#elif BUILD_FT2232_LIBFTDI == 1
+       return ft2232_purge_libftdi();
+#endif 
+
+       return ERROR_OK;
+}
+
+int usbjtag_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x08;
+       low_direction = 0x0b;
+       
+       if (strcmp(ft2232_layout, "usbjtag") == 0)
+       {
+               nTRST = 0x10;
+               nTRSTnOE = 0x10;
+               nSRST = 0x40;
+               nSRSTnOE = 0x40;
+       }
+       else if (strcmp(ft2232_layout, "signalyzer") == 0)
+       {
+               nTRST = 0x10;
+               nTRSTnOE = 0x10;
+               nSRST = 0x20;
+               nSRSTnOE = 0x20;
+       }
+       else if (strcmp(ft2232_layout, "evb_lm3s811") == 0)
+       {
+               nTRST = 0x0;
+               nTRSTnOE = 0x00;
+               nSRST = 0x20;
+               nSRSTnOE = 0x20;
+               low_output = 0x88;
+               low_direction = 0x8b;
+       }
+       else
+       {
+               ERROR("BUG: usbjtag_init called for unknown layout '%s'", ft2232_layout);
+               return ERROR_JTAG_INIT_FAILED;  
+       }
+       
+       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+       {
+               low_direction &= ~nTRSTnOE; /* nTRST input */
+               low_output &= ~nTRST; /* nTRST = 0 */
+       }
+       else
+       {
+               low_direction |= nTRSTnOE; /* nTRST output */
+               low_output |= nTRST; /* nTRST = 1 */
+       }
+       
+       if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+       {
+               low_direction |= nSRSTnOE; /* nSRST output */
+               low_output |= nSRST; /* nSRST = 1 */
+       }
+       else
+       {
+               low_direction &= ~nSRSTnOE; /* nSRST input */
+               low_output &= ~nSRST; /* nSRST = 0 */
+       }
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, xRST high) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'USBJTAG' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       return ERROR_OK;
+}
+
+int jtagkey_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x08;
+       low_direction = 0x1b;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       if (strcmp(layout->name, "jtagkey") == 0)
+       {
+               nTRST = 0x01;
+               nTRSTnOE = 0x4;
+               nSRST = 0x02;
+               nSRSTnOE = 0x08;
+       }
+       else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) ||
+               (strcmp(layout->name, "oocdlink") == 0))
+       {
+               nTRST = 0x02;
+               nTRSTnOE = 0x1;
+               nSRST = 0x08;
+               nSRSTnOE = 0x04;
+       }
+       else
+       {
+               ERROR("BUG: jtagkey_init called for non jtagkey layout");
+               exit(-1);
+       }
+       
+       high_output = 0x0;
+       high_direction = 0x0f;
+
+       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+       {
+               high_output |= nTRSTnOE;
+               high_output &= ~nTRST;
+       }
+       else
+       {
+               high_output &= ~nTRSTnOE;
+               high_output |= nTRST;
+       }
+       
+       if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+       {
+               high_output &= ~nSRSTnOE;
+               high_output |= nSRST;
+       }
+       else
+       {
+               high_output |= nSRSTnOE;
+               high_output &= ~nSRST;
+       }
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output; /* value */
+       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int olimex_jtag_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x08;
+       low_direction = 0x1b;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       nTRST = 0x01;
+       nTRSTnOE = 0x4;
+       nSRST = 0x02;
+       nSRSTnOE = 0x00; /* no output enable for nSRST */
+
+       high_output = 0x0;
+       high_direction = 0x0f;
+
+       if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+       {
+               high_output |= nTRSTnOE;
+               high_output &= ~nTRST;
+       }
+       else
+       {
+               high_output &= ~nTRSTnOE;
+               high_output |= nTRST;
+       }
+       
+       if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+       {
+               ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD");
+       }
+       else
+       {
+               high_output &= ~nSRST;
+       }
+       
+       /* turn red LED on */
+       high_output |= 0x08;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output; /* value */
+       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int flyswatter_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x18;
+       low_direction = 0xfb;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE[12]=out, n[ST]srst=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       nTRST = 0x10;
+       nTRSTnOE = 0x0; /* not output enable for nTRST */
+       nSRST = 0x20;
+       nSRSTnOE = 0x00; /* no output enable for nSRST */
+
+       high_output = 0x00;
+       high_direction = 0x0c;
+
+       /* turn red LED1 on, LED2 off */
+       high_output |= 0x08;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output; /* value */
+       buf[2] = high_direction;   /* all outputs (xRST and xRSTnOE) */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int turtle_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x08;
+       low_direction = 0x5b;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       nSRST = 0x40;
+       
+       high_output = 0x00;
+       high_direction = 0x0C;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output;
+       buf[2] = high_direction;
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int comstick_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x08;
+       low_direction = 0x0b;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'comstick' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       nTRST = 0x01;
+       nTRSTnOE = 0x00; /* no output enable for nTRST */
+       nSRST = 0x02;
+       nSRSTnOE = 0x00; /* no output enable for nSRST */
+       
+       high_output = 0x03;
+       high_direction = 0x03;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output;
+       buf[2] = high_direction;
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'comstick' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int stm32stick_init(void)
+{
+       u8 buf[3];
+       u32 bytes_written;
+       
+       low_output = 0x88;
+       low_direction = 0x8b;
+       
+       /* initialize low byte for jtag */
+       buf[0] = 0x80; /* command "set data bits low byte" */
+       buf[1] = low_output; /* value (TMS=1,TCK=0, TDI=0, nOE=0) */
+       buf[2] = low_direction; /* dir (output=1), TCK/TDI/TMS=out, TDO=in, nOE=out */
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+               
+       nTRST = 0x01;
+       nTRSTnOE = 0x00; /* no output enable for nTRST */
+       nSRST = 0x80;
+       nSRSTnOE = 0x00; /* no output enable for nSRST */
+       
+       high_output = 0x01;
+       high_direction = 0x03;
+       
+       /* initialize high port */
+       buf[0] = 0x82; /* command "set data bits high byte" */
+       buf[1] = high_output;
+       buf[2] = high_direction;
+       DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]);
+       
+       if (((ft2232_write(buf, 3, &bytes_written)) != ERROR_OK) || (bytes_written != 3))
+       {
+               ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); 
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+void olimex_jtag_blink(void)
+{
+       /* Olimex ARM-USB-OCD has a LED connected to ACBUS3
+        * ACBUS3 is bit 3 of the GPIOH port
+        */
+       if (high_output & 0x08)
+       {
+               /* set port pin high */
+               high_output &= 0x07;
+       }
+       else
+       {
+               /* set port pin low */
+               high_output |= 0x08;
+       }
+       
+       BUFFER_ADD = 0x82;
+       BUFFER_ADD = high_output;
+       BUFFER_ADD = high_direction;
+}
+
+void turtle_jtag_blink(void)
+{
+       /* 
+   * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3
+        */
+       if (high_output & 0x08)
+       {
+               high_output = 0x04;
+       }
+       else
+       {
+               high_output = 0x08;
+       }
+       
+       BUFFER_ADD = 0x82;
+       BUFFER_ADD = high_output;
+       BUFFER_ADD = high_direction;
+}
+
+
+int ft2232_quit(void)
+{
+#if BUILD_FT2232_FTD2XX == 1
+       FT_STATUS status;
+
+       status = FT_Close(ftdih);
+#elif BUILD_FT2232_LIBFTDI == 1
+       ftdi_disable_bitbang(&ftdic);
+       
+       ftdi_usb_close(&ftdic);
+       
+       ftdi_deinit(&ftdic);
+#endif
+
+       free(ft2232_buffer);
+       ft2232_buffer = NULL;
+
+       return ERROR_OK;
+}
+
+int ft2232_handle_device_desc_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               ft2232_device_desc = strdup(args[0]);
+       }
+       else
+       {
+               ERROR("expected exactly one argument to ft2232_device_desc <description>");
+       }
+       
+       return ERROR_OK;
+}
+
+int ft2232_handle_serial_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               ft2232_serial = strdup(args[0]);
+       }
+       else
+       {
+               ERROR("expected exactly one argument to ft2232_serial <serial-number>");
+       }
+       
+       return ERROR_OK;
+}
+
+int ft2232_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               return ERROR_OK;
+
+       ft2232_layout = malloc(strlen(args[0]) + 1);
+       strcpy(ft2232_layout, args[0]);
+
+       return ERROR_OK;
+}
+
+int ft2232_handle_vid_pid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int i;
+
+       if (argc > MAX_USB_IDS*2) {
+               WARNING("ignoring extra IDs in ft2232_vid_pid "
+                   "(maximum is %d pairs)", MAX_USB_IDS);
+               argc = MAX_USB_IDS*2;
+       }
+       if (argc < 2 || (argc & 1))
+       {
+               WARNING("incomplete ft2232_vid_pid configuration directive");
+               if (argc < 2)
+                       return ERROR_OK;
+       }
+
+       for (i = 0; i+1 < argc; i += 2) {
+               ft2232_vid[i >> 1] = strtol(args[i], NULL, 0);
+               ft2232_pid[i >> 1] = strtol(args[i+1], NULL, 0);
+       }
+       /*
+        * Explicitly terminate, in case there are multiples instances of
+        * ft2232_vid_pid.
+        */
+       ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0;
+
+       return ERROR_OK;
+}
+
+int ft2232_handle_latency_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               ft2232_latency = atoi(args[0]);
+       }
+       else
+       {
+               ERROR("expected exactly one argument to ft2232_latency <ms>");
+       }
+       
+       return ERROR_OK;
+}
+
+
index 77c4b3f26477c2bb340c7ec87e6c45befbf535cf..600fe19a0c67f48213499b09c2cf20303bcf7ade 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "jtag.h"\r
-\r
-#include "command.h"\r
-#include "log.h"\r
-#include "interpreter.h"\r
-\r
-#include "stdlib.h"\r
-#include "string.h"\r
-#include <unistd.h>\r
-\r
-char* tap_state_strings[16] =\r
-{\r
-       "tlr", \r
-       "sds", "cd", "sd", "e1d", "pd", "e2d", "ud",\r
-       "rti",\r
-       "sis", "ci", "si", "e1i", "pi", "e2i", "ui"\r
-};\r
-\r
-typedef struct cmd_queue_page_s\r
-{\r
-       void *address;\r
-       size_t used;\r
-       struct cmd_queue_page_s *next;\r
-} cmd_queue_page_t;\r
-\r
-#define CMD_QUEUE_PAGE_SIZE (1024 * 1024)\r
-static cmd_queue_page_t *cmd_queue_pages = NULL;\r
-\r
-/* tap_move[i][j]: tap movement command to go from state i to state j\r
- * 0: Test-Logic-Reset\r
- * 1: Run-Test/Idle\r
- * 2: Shift-DR\r
- * 3: Pause-DR\r
- * 4: Shift-IR\r
- * 5: Pause-IR\r
- * \r
- * SD->SD and SI->SI have to be caught in interface specific code\r
- */\r
-u8 tap_move[6][6] =\r
-{\r
-/*       TLR   RTI   SD    PD    SI    PI             */\r
-       {0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16},   /* TLR */\r
-       {0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b},   /* RTI */\r
-       {0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f},   /* SD  */\r
-       {0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f},   /* PD  */\r
-       {0x7f, 0x31, 0x07, 0x17, 0x00, 0x01},   /* SI  */\r
-       {0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f}    /* PI  */\r
-};\r
-\r
-int tap_move_map[16] = {\r
-       0, -1, -1,  2, -1,  3, -1, -1,\r
-       1, -1, -1,  4, -1,  5, -1, -1\r
-};\r
-\r
-tap_transition_t tap_transitions[16] =\r
-{\r
-       {TAP_TLR, TAP_RTI},             /* TLR */\r
-       {TAP_SIS, TAP_CD},              /* SDS */\r
-       {TAP_E1D, TAP_SD},              /* CD  */\r
-       {TAP_E1D, TAP_SD},              /* SD  */\r
-       {TAP_UD,  TAP_PD},              /* E1D */\r
-       {TAP_E2D, TAP_PD},              /* PD  */\r
-       {TAP_UD,  TAP_SD},              /* E2D */\r
-       {TAP_SDS, TAP_RTI},             /* UD  */\r
-       {TAP_SDS, TAP_RTI},             /* RTI */\r
-       {TAP_TLR, TAP_CI},              /* SIS */\r
-       {TAP_E1I, TAP_SI},              /* CI  */\r
-       {TAP_E1I, TAP_SI},              /* SI  */\r
-       {TAP_UI,  TAP_PI},              /* E1I */\r
-       {TAP_E2I, TAP_PI},              /* PI  */\r
-       {TAP_UI,  TAP_SI},              /* E2I */\r
-       {TAP_SDS, TAP_RTI}              /* UI  */\r
-};\r
-\r
-char* jtag_event_strings[] =\r
-{\r
-       "SRST asserted",\r
-       "TRST asserted",\r
-       "SRST released",\r
-       "TRST released"\r
-};\r
-\r
-enum tap_state end_state = TAP_TLR;\r
-enum tap_state cur_state = TAP_TLR;\r
-int jtag_trst = 0;\r
-int jtag_srst = 0;\r
-\r
-jtag_command_t *jtag_command_queue = NULL;\r
-jtag_command_t **last_comand_pointer = &jtag_command_queue;\r
-jtag_device_t *jtag_devices = NULL;\r
-int jtag_num_devices = 0;\r
-int jtag_ir_scan_size = 0;\r
-enum reset_types jtag_reset_config = RESET_NONE;\r
-enum tap_state cmd_queue_end_state = TAP_TLR;\r
-enum tap_state cmd_queue_cur_state = TAP_TLR;\r
-\r
-int jtag_verify_capture_ir = 1;\r
-\r
-/* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */\r
-int jtag_nsrst_delay = 0; /* default to no nSRST delay */\r
-int jtag_ntrst_delay = 0; /* default to no nTRST delay */ \r
-\r
-/* maximum number of JTAG devices expected in the chain\r
- */\r
-#define JTAG_MAX_CHAIN_SIZE 20 \r
-\r
-/* callbacks to inform high-level handlers about JTAG state changes */\r
-jtag_event_callback_t *jtag_event_callbacks;\r
-\r
-/* jtag interfaces (parport, FTDI-USB, TI-USB, ...)\r
- */\r
-#if BUILD_PARPORT == 1\r
-       extern jtag_interface_t parport_interface;\r
-#endif\r
-\r
-#if BUILD_FT2232_FTD2XX == 1\r
-       extern jtag_interface_t ft2232_interface;\r
-#endif\r
-\r
-#if BUILD_FT2232_LIBFTDI == 1\r
-       extern jtag_interface_t ft2232_interface;\r
-#endif\r
-\r
-#if BUILD_AMTJTAGACCEL == 1\r
-       extern jtag_interface_t amt_jtagaccel_interface;\r
-#endif\r
-\r
-#if BUILD_EP93XX == 1\r
-       extern jtag_interface_t ep93xx_interface;\r
-#endif\r
-\r
-#if BUILD_AT91RM9200 == 1\r
-       extern jtag_interface_t at91rm9200_interface;\r
-#endif\r
-\r
-#if BUILD_GW16012 == 1\r
-       extern jtag_interface_t gw16012_interface;\r
-#endif\r
-\r
-#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1\r
-       extern jtag_interface_t presto_interface;\r
-#endif\r
-\r
-#if BUILD_USBPROG == 1\r
-       extern jtag_interface_t usbprog_interface;\r
-#endif\r
-\r
-jtag_interface_t *jtag_interfaces[] = {\r
-#if BUILD_PARPORT == 1\r
-       &parport_interface,\r
-#endif\r
-#if BUILD_FT2232_FTD2XX == 1\r
-       &ft2232_interface,\r
-#endif\r
-#if BUILD_FT2232_LIBFTDI == 1\r
-       &ft2232_interface,\r
-#endif\r
-#if BUILD_AMTJTAGACCEL == 1\r
-       &amt_jtagaccel_interface,\r
-#endif\r
-#if BUILD_EP93XX == 1\r
-       &ep93xx_interface,\r
-#endif\r
-#if BUILD_AT91RM9200 == 1\r
-       &at91rm9200_interface,\r
-#endif\r
-#if BUILD_GW16012 == 1\r
-       &gw16012_interface,\r
-#endif\r
-#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1\r
-       &presto_interface,\r
-#endif\r
-#if BUILD_USBPROG == 1\r
-       &usbprog_interface,\r
-#endif\r
-       NULL,\r
-};\r
-\r
-jtag_interface_t *jtag = NULL;\r
-\r
-/* configuration */\r
-jtag_interface_t *jtag_interface = NULL;\r
-int jtag_speed = 0;\r
-\r
-\r
-/* forward declarations */\r
-int jtag_add_statemove(enum tap_state endstate);\r
-int jtag_add_pathmove(int num_states, enum tap_state *path);\r
-int jtag_add_runtest(int num_cycles, enum tap_state endstate);\r
-int jtag_add_reset(int trst, int srst);\r
-int jtag_add_end_state(enum tap_state endstate);\r
-int jtag_add_sleep(u32 us);\r
-int jtag_execute_queue(void);\r
-int jtag_cancel_queue(void);\r
-\r
-/* jtag commands */\r
-int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv)\r
-{\r
-       jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;\r
-       \r
-       if (callback == NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-       \r
-       if (*callbacks_p)\r
-       {\r
-               while ((*callbacks_p)->next)\r
-                       callbacks_p = &((*callbacks_p)->next);\r
-               callbacks_p = &((*callbacks_p)->next);\r
-       }\r
-       \r
-       (*callbacks_p) = malloc(sizeof(jtag_event_callback_t));\r
-       (*callbacks_p)->callback = callback;\r
-       (*callbacks_p)->priv = priv;\r
-       (*callbacks_p)->next = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_unregister_event_callback(int (*callback)(enum jtag_event event, void *priv))\r
-{\r
-       jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;\r
-       \r
-       if (callback == NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-               \r
-       while (*callbacks_p)\r
-       {\r
-               jtag_event_callback_t **next = &((*callbacks_p)->next);\r
-               if ((*callbacks_p)->callback == callback)\r
-               {\r
-                       free(*callbacks_p);\r
-                       *callbacks_p = *next;\r
-               }\r
-               callbacks_p = next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_call_event_callbacks(enum jtag_event event)\r
-{\r
-       jtag_event_callback_t *callback = jtag_event_callbacks;\r
-       \r
-       DEBUG("jtag event: %s", jtag_event_strings[event]);\r
-       \r
-       while (callback)\r
-       {\r
-               callback->callback(event, callback->priv);\r
-               callback = callback->next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/* returns a pointer to the pointer of the last command in queue\r
- * this may be a pointer to the root pointer (jtag_command_queue)\r
- * or to the next member of the last but one command\r
- */\r
-jtag_command_t** jtag_get_last_command_p(void)\r
-{\r
-/*     jtag_command_t *cmd = jtag_command_queue;\r
-       \r
-       if (cmd)\r
-               while (cmd->next)\r
-                       cmd = cmd->next;\r
-       else\r
-               return &jtag_command_queue;\r
-       \r
-       return &cmd->next;*/\r
-       \r
-       return last_comand_pointer;\r
-}\r
-\r
-/* returns a pointer to the n-th device in the scan chain */\r
-jtag_device_t* jtag_get_device(int num)\r
-{\r
-       jtag_device_t *device = jtag_devices;\r
-       int i = 0;\r
-\r
-       while (device)\r
-       {\r
-               if (num == i)\r
-                       return device;\r
-               device = device->next;\r
-               i++;\r
-       }\r
-       \r
-       ERROR("jtag device number %d not defined", num);\r
-       exit(-1);\r
-}\r
-\r
-void* cmd_queue_alloc(size_t size)\r
-{\r
-       cmd_queue_page_t **p_page = &cmd_queue_pages;\r
-       int offset;\r
-\r
-       if (*p_page)\r
-       {\r
-               while ((*p_page)->next)\r
-                       p_page = &((*p_page)->next);\r
-               if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)\r
-                       p_page = &((*p_page)->next);\r
-       }\r
-\r
-       if (!*p_page)\r
-       {\r
-               *p_page = malloc(sizeof(cmd_queue_page_t));\r
-               (*p_page)->used = 0;\r
-               (*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);\r
-               (*p_page)->next = NULL;\r
-       }\r
-\r
-       offset = (*p_page)->used;\r
-       (*p_page)->used += size;\r
-       \r
-       u8 *t=(u8 *)((*p_page)->address);\r
-       return t + offset;\r
-}\r
-\r
-void cmd_queue_free()\r
-{\r
-       cmd_queue_page_t *page = cmd_queue_pages;\r
-\r
-       while (page)\r
-       {\r
-               cmd_queue_page_t *last = page;\r
-               free(page->address);\r
-               page = page->next;\r
-               free(last);\r
-       }\r
-\r
-       cmd_queue_pages = NULL;\r
-}\r
-\r
-int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
-{\r
-       jtag_command_t **last_cmd;\r
-       jtag_device_t *device;\r
-       int i, j;\r
-       int scan_size = 0;\r
-\r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-\r
-       last_cmd = jtag_get_last_command_p();\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       (*last_cmd)->next = NULL;\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->type = JTAG_SCAN;\r
-\r
-       /* allocate memory for ir scan command */\r
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));\r
-       (*last_cmd)->cmd.scan->ir_scan = 1;\r
-       (*last_cmd)->cmd.scan->num_fields = jtag_num_devices;   /* one field per device */\r
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(jtag_num_devices * sizeof(scan_field_t));\r
-       (*last_cmd)->cmd.scan->end_state = state;\r
-               \r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-       \r
-       cmd_queue_cur_state = cmd_queue_end_state;\r
-               \r
-       for (i = 0; i < jtag_num_devices; i++)\r
-       {\r
-               int found = 0;\r
-               device = jtag_get_device(i);\r
-               scan_size = device->ir_length;\r
-               (*last_cmd)->cmd.scan->fields[i].device = i;\r
-               (*last_cmd)->cmd.scan->fields[i].num_bits = scan_size;\r
-               (*last_cmd)->cmd.scan->fields[i].in_value = NULL;\r
-               (*last_cmd)->cmd.scan->fields[i].in_handler = NULL;     /* disable verification by default */\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
-                               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);\r
-                               (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);\r
-                       \r
-                               if (jtag_verify_capture_ir)\r
-                               {\r
-                                       if (fields[j].in_handler==NULL)\r
-                                       {\r
-                                               jtag_set_check_value((*last_cmd)->cmd.scan->fields+i, device->expected, device->expected_mask, NULL);\r
-                                       } else\r
-                                       {\r
-                                               (*last_cmd)->cmd.scan->fields[i].in_handler = fields[j].in_handler;\r
-                                               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[j].in_handler_priv;\r
-                                               (*last_cmd)->cmd.scan->fields[i].in_check_value = device->expected; \r
-                                               (*last_cmd)->cmd.scan->fields[i].in_check_mask = device->expected_mask;\r
-                                       }\r
-                               }\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
-                       (*last_cmd)->cmd.scan->fields[i].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);\r
-                       (*last_cmd)->cmd.scan->fields[i].out_mask = NULL;\r
-                       device->bypass = 1;\r
-               \r
-               }\r
-               \r
-               /* update device information */\r
-               buf_cpy((*last_cmd)->cmd.scan->fields[i].out_value, jtag_get_device(i)->cur_instr, scan_size);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
-{\r
-       jtag_command_t **last_cmd;\r
-       int i;\r
-\r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-\r
-       last_cmd = jtag_get_last_command_p();\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       (*last_cmd)->next = NULL;\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->type = JTAG_SCAN;\r
-\r
-       /* allocate memory for ir scan command */\r
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));\r
-       (*last_cmd)->cmd.scan->ir_scan = 1;\r
-       (*last_cmd)->cmd.scan->num_fields = num_fields;\r
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));\r
-       (*last_cmd)->cmd.scan->end_state = state;\r
-\r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-               \r
-       cmd_queue_cur_state = cmd_queue_end_state;\r
-       \r
-       for (i = 0; i < num_fields; i++)\r
-       {\r
-               int num_bits = fields[i].num_bits;\r
-               int num_bytes = CEIL(fields[i].num_bits, 8);\r
-               (*last_cmd)->cmd.scan->fields[i].device = fields[i].device;\r
-               (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;\r
-               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);\r
-               (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);\r
-               (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;\r
-               (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;\r
-               (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;\r
-               (*last_cmd)->cmd.scan->fields[i].in_handler = NULL;\r
-               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = NULL;\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
-{\r
-       int i, j;\r
-       int bypass_devices = 0;\r
-       int field_count = 0;\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       jtag_device_t *device = jtag_devices;\r
-       int scan_size;\r
-\r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-\r
-       /* count devices in bypass */\r
-       while (device)\r
-       {\r
-               if (device->bypass)\r
-                       bypass_devices++;\r
-               device = device->next;\r
-       }\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->next = NULL;\r
-       (*last_cmd)->type = JTAG_SCAN;\r
-\r
-       /* allocate memory for dr scan command */\r
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));\r
-       (*last_cmd)->cmd.scan->ir_scan = 0;\r
-       (*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;\r
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));\r
-       (*last_cmd)->cmd.scan->end_state = state;\r
-       \r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-                       \r
-       cmd_queue_cur_state = cmd_queue_end_state;\r
-       \r
-       for (i = 0; i < jtag_num_devices; i++)\r
-       {\r
-               int found = 0;\r
-               (*last_cmd)->cmd.scan->fields[field_count].device = i;\r
-       \r
-               for (j = 0; j < num_fields; j++)\r
-               {\r
-                       if (i == fields[j].device)\r
-                       {\r
-                               found = 1;\r
-                               scan_size = fields[j].num_bits;\r
-                               (*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size;\r
-                               (*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);\r
-                               (*last_cmd)->cmd.scan->fields[field_count].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);\r
-                               (*last_cmd)->cmd.scan->fields[field_count].in_value = fields[j].in_value;\r
-                               (*last_cmd)->cmd.scan->fields[field_count].in_check_value = fields[j].in_check_value;\r
-                               (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = fields[j].in_check_mask;\r
-                               (*last_cmd)->cmd.scan->fields[field_count].in_handler = fields[j].in_handler;\r
-                               (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = fields[j].in_handler_priv;\r
-                       }\r
-               }\r
-               if (!found)\r
-               {\r
-                       /* if a device isn't listed, the BYPASS register should be selected */\r
-                       if (!jtag_get_device(i)->bypass)\r
-                       {\r
-                               ERROR("BUG: no scan data for a device not in BYPASS");\r
-                               exit(-1);\r
-                       }\r
-       \r
-                       /* program the scan field to 1 bit length, and ignore it's value */\r
-                       (*last_cmd)->cmd.scan->fields[field_count].num_bits = 1;\r
-                       (*last_cmd)->cmd.scan->fields[field_count].out_value = NULL;\r
-                       (*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL;\r
-                       (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;\r
-                       (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;\r
-                       (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;\r
-                       (*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;\r
-                       (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;\r
-               }\r
-               else\r
-               {\r
-                       /* if a device is listed, the BYPASS register must not be selected */\r
-                       if (jtag_get_device(i)->bypass)\r
-                       {\r
-                               WARNING("scan data for a device in BYPASS");\r
-                       }\r
-               }\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)\r
-{\r
-       int i;\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       \r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-\r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->next = NULL;\r
-       (*last_cmd)->type = JTAG_SCAN;\r
-\r
-       /* allocate memory for scan command */\r
-       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));\r
-       (*last_cmd)->cmd.scan->ir_scan = 0;\r
-       (*last_cmd)->cmd.scan->num_fields = num_fields;\r
-       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));\r
-       (*last_cmd)->cmd.scan->end_state = state;\r
-               \r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-                       \r
-       cmd_queue_cur_state = cmd_queue_end_state;\r
-       \r
-       for (i = 0; i < num_fields; i++)\r
-       {\r
-               int num_bits = fields[i].num_bits;\r
-               int num_bytes = CEIL(fields[i].num_bits, 8);\r
-               (*last_cmd)->cmd.scan->fields[i].device = fields[i].device;\r
-               (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;\r
-               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);\r
-               (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);\r
-               (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;\r
-               (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;\r
-               (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;\r
-               (*last_cmd)->cmd.scan->fields[i].in_handler = fields[i].in_handler;\r
-               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[i].in_handler_priv;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-int jtag_add_statemove(enum tap_state state)\r
-{\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       \r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-\r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->next = NULL;\r
-       (*last_cmd)->type = JTAG_STATEMOVE;\r
-\r
-       (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));\r
-       (*last_cmd)->cmd.statemove->end_state = state;\r
-       \r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-                       \r
-       cmd_queue_cur_state = cmd_queue_end_state;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_pathmove(int num_states, enum tap_state *path)\r
-{\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       int i;\r
-       \r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-       \r
-       /* the last state has to be a stable state */\r
-       if (tap_move_map[path[num_states - 1]] == -1)\r
-       {\r
-               ERROR("TAP path doesn't finish in a stable state");\r
-               return ERROR_JTAG_NOT_IMPLEMENTED;\r
-       }\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->next = NULL;\r
-       (*last_cmd)->type = JTAG_PATHMOVE;\r
-\r
-       (*last_cmd)->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t));\r
-       (*last_cmd)->cmd.pathmove->num_states = num_states;\r
-       (*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states);\r
-       \r
-       for (i = 0; i < num_states; i++)\r
-               (*last_cmd)->cmd.pathmove->path[i] = path[i];\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-       \r
-       cmd_queue_cur_state = path[num_states - 1];\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_runtest(int num_cycles, enum tap_state state)\r
-{\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       \r
-       if (jtag_trst == 1)\r
-       {\r
-               WARNING("JTAG command queued, while TRST is low (TAP in reset)");\r
-               return ERROR_JTAG_TRST_ASSERTED;\r
-       }\r
-\r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       (*last_cmd)->next = NULL;\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->type = JTAG_RUNTEST;\r
-\r
-       (*last_cmd)->cmd.runtest = cmd_queue_alloc(sizeof(runtest_command_t));\r
-       (*last_cmd)->cmd.runtest->num_cycles = num_cycles;\r
-       (*last_cmd)->cmd.runtest->end_state = state;\r
-       \r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-\r
-       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_RELEASED);\r
-       \r
-       if (cmd_queue_end_state == TAP_TLR)\r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-                       \r
-       cmd_queue_cur_state = cmd_queue_end_state;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_reset(int req_trst, int req_srst)\r
-{\r
-       int trst_with_tms = 0;\r
-       \r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       \r
-       if (req_trst == -1)\r
-               req_trst = jtag_trst;\r
-       \r
-       if (req_srst == -1)\r
-               req_srst = jtag_srst;\r
-\r
-       /* Make sure that jtag_reset_config allows the requested reset */\r
-       /* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */\r
-       if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (req_trst == 0))\r
-               return ERROR_JTAG_RESET_WOULD_ASSERT_TRST;\r
-               \r
-       /* if TRST pulls SRST, we reset with TAP T-L-R */\r
-       if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_trst == 1)) && (req_srst == 0))\r
-       {\r
-               req_trst = 0;\r
-               trst_with_tms = 1;\r
-       }\r
-       \r
-       if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))\r
-       {\r
-               ERROR("requested nSRST assertion, but the current configuration doesn't support this");\r
-               return ERROR_JTAG_RESET_CANT_SRST;\r
-       }\r
-       \r
-       if (req_trst && !(jtag_reset_config & RESET_HAS_TRST))\r
-       {\r
-               req_trst = 0;\r
-               trst_with_tms = 1;\r
-       }\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       (*last_cmd)->next = NULL;\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->type = JTAG_RESET;\r
-\r
-       (*last_cmd)->cmd.reset = cmd_queue_alloc(sizeof(reset_command_t));\r
-       (*last_cmd)->cmd.reset->trst = req_trst;\r
-       (*last_cmd)->cmd.reset->srst = req_srst;\r
-\r
-       jtag_trst = req_trst;\r
-       jtag_srst = req_srst;\r
-\r
-       if (jtag_srst)\r
-       {\r
-               jtag_call_event_callbacks(JTAG_SRST_ASSERTED);\r
-       }\r
-       else\r
-       {\r
-               jtag_call_event_callbacks(JTAG_SRST_RELEASED);\r
-               if (jtag_nsrst_delay)\r
-                       jtag_add_sleep(jtag_nsrst_delay * 1000);\r
-       }\r
-       \r
-       if (trst_with_tms)\r
-       {\r
-               last_cmd = &((*last_cmd)->next);\r
-               \r
-               /* allocate memory for a new list member */\r
-               *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-               (*last_cmd)->next = NULL;\r
-               last_comand_pointer = &((*last_cmd)->next);\r
-               (*last_cmd)->type = JTAG_STATEMOVE;\r
-\r
-               (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));\r
-               (*last_cmd)->cmd.statemove->end_state = TAP_TLR;\r
-               \r
-               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-               cmd_queue_cur_state = TAP_TLR;\r
-               cmd_queue_end_state = TAP_TLR;\r
-               \r
-               return ERROR_OK;\r
-       }\r
-       else\r
-       {\r
-               if (jtag_trst)\r
-               {\r
-                       /* we just asserted nTRST, so we're now in Test-Logic-Reset,\r
-                        * and inform possible listeners about this\r
-                        */\r
-                       cmd_queue_cur_state = TAP_TLR;\r
-                       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);\r
-               }\r
-               else\r
-               {\r
-                       /* the nTRST line got deasserted, so we're still in Test-Logic-Reset,\r
-                        * but we might want to add a delay to give the TAP time to settle\r
-                        */\r
-                       if (jtag_ntrst_delay)\r
-                               jtag_add_sleep(jtag_ntrst_delay * 1000);\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_end_state(enum tap_state state)\r
-{\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       (*last_cmd)->next = NULL;\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->type = JTAG_END_STATE;\r
-\r
-       (*last_cmd)->cmd.end_state = cmd_queue_alloc(sizeof(end_state_command_t));\r
-       (*last_cmd)->cmd.end_state->end_state = state;\r
-\r
-       if (state != -1)\r
-               cmd_queue_end_state = state;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_add_sleep(u32 us)\r
-{\r
-       jtag_command_t **last_cmd = jtag_get_last_command_p();\r
-       \r
-       /* allocate memory for a new list member */\r
-       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));\r
-       (*last_cmd)->next = NULL;\r
-       last_comand_pointer = &((*last_cmd)->next);\r
-       (*last_cmd)->type = JTAG_SLEEP;\r
-\r
-       (*last_cmd)->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));\r
-       (*last_cmd)->cmd.sleep->us = us;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_scan_size(scan_command_t *cmd)\r
-{\r
-       int bit_count = 0;\r
-       int i;\r
-\r
-       /* count bits in scan command */\r
-       for (i = 0; i < cmd->num_fields; i++)\r
-       {\r
-               bit_count += cmd->fields[i].num_bits;\r
-       }\r
-\r
-       return bit_count;\r
-}\r
-\r
-int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)\r
-{\r
-       int bit_count = 0;\r
-       int i;\r
-       \r
-       bit_count = jtag_scan_size(cmd);\r
-       *buffer = malloc(CEIL(bit_count, 8));\r
-       \r
-       bit_count = 0;\r
-\r
-       for (i = 0; i < cmd->num_fields; i++)\r
-       {\r
-               if (cmd->fields[i].out_value)\r
-               {\r
-#ifdef _DEBUG_JTAG_IO_\r
-                       char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16);\r
-#endif\r
-                       buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);\r
-#ifdef _DEBUG_JTAG_IO_\r
-                       DEBUG("fields[%i].out_value: 0x%s", i, char_buf);\r
-                       free(char_buf);\r
-#endif\r
-               }\r
-               \r
-               bit_count += cmd->fields[i].num_bits;\r
-       }\r
-\r
-       return bit_count;\r
-\r
-}\r
-\r
-int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)\r
-{\r
-       int i;\r
-       int bit_count = 0;\r
-       int retval;\r
-       \r
-       /* we return ERROR_OK, unless a check fails, or a handler reports a problem */\r
-       retval = ERROR_OK;\r
-       \r
-       for (i = 0; i < cmd->num_fields; i++)\r
-       {\r
-               /* if neither in_value nor in_handler\r
-                * are specified we don't have to examine this field\r
-                */\r
-               if (cmd->fields[i].in_value || cmd->fields[i].in_handler)\r
-               {\r
-                       int num_bits = cmd->fields[i].num_bits;\r
-                       u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);\r
-                       \r
-#ifdef _DEBUG_JTAG_IO_\r
-                       char *char_buf;\r
-\r
-                       char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);\r
-                       DEBUG("fields[%i].in_value: 0x%s", i, char_buf);\r
-                       free(char_buf);\r
-#endif\r
-                       \r
-                       if (cmd->fields[i].in_value)\r
-                       {\r
-                               buf_cpy(captured, cmd->fields[i].in_value, num_bits);\r
-                               \r
-                               if (cmd->fields[i].in_handler)\r
-                               {\r
-                                       if (cmd->fields[i].in_handler(cmd->fields[i].in_value, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)\r
-                                       {\r
-                                               WARNING("in_handler reported a failed check");\r
-                                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       /* no in_value specified, but a handler takes care of the scanned data */\r
-                       if (cmd->fields[i].in_handler && (!cmd->fields[i].in_value))\r
-                       {\r
-                               if (cmd->fields[i].in_handler(captured, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)\r
-                               {\r
-                                       /* We're going to call the error:handler later, but if the in_handler\r
-                                        * reported an error we report this failure upstream\r
-                                        */\r
-                                       WARNING("in_handler reported a failed check");\r
-                                       retval = ERROR_JTAG_QUEUE_FAILED;\r
-                               }\r
-                       }\r
-\r
-                       free(captured);\r
-               }\r
-               bit_count += cmd->fields[i].num_bits;\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)\r
-{\r
-       int retval = ERROR_OK;\r
-       int num_bits = field->num_bits;\r
-       \r
-       int compare_failed = 0;\r
-       \r
-       if (field->in_check_mask)\r
-               compare_failed = buf_cmp_mask(captured, field->in_check_value, field->in_check_mask, num_bits);\r
-       else\r
-               compare_failed = buf_cmp(captured, field->in_check_value, num_bits);\r
-       \r
-       if (compare_failed)\r
-               {\r
-               /* An error handler could have caught the failing check\r
-                * only report a problem when there wasn't a handler, or if the handler\r
-                * acknowledged the error\r
-                */ \r
-               if (compare_failed)\r
-               {\r
-                       char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);\r
-                       char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > 64) ? 64 : num_bits, 16);\r
-\r
-                       if (field->in_check_mask)\r
-                       {\r
-                               char *in_check_mask_char;\r
-                               in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16);\r
-                               WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char);\r
-                               free(in_check_mask_char);\r
-                       }\r
-                       else\r
-                       {\r
-                               WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char);\r
-                       }\r
-\r
-                       free(captured_char);\r
-                       free(in_check_value_char);\r
-                       \r
-                       retval = ERROR_JTAG_QUEUE_FAILED;\r
-               }\r
-               \r
-       }\r
-       return retval;\r
-}\r
-\r
-/* \r
-  set up checking of this field using the in_handler. The values passed in must be valid until\r
-  after jtag_execute() has completed.\r
- */\r
-void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handler_t *in_error_handler)\r
-{\r
-       if (value)\r
-               field->in_handler = jtag_check_value;\r
-       else\r
-               field->in_handler = NULL;       /* No check, e.g. embeddedice uses value==NULL to indicate no check */\r
-       field->in_handler_priv = NULL;  /* this will be filled in at the invocation site to point to the field duplicate */ \r
-       field->in_check_value = value;\r
-       field->in_check_mask = mask;\r
-}\r
-\r
-enum scan_type jtag_scan_type(scan_command_t *cmd)\r
-{\r
-       int i;\r
-       int type = 0;\r
-       \r
-       for (i = 0; i < cmd->num_fields; i++)\r
-       {\r
-               if (cmd->fields[i].in_value || cmd->fields[i].in_handler)\r
-                       type |= SCAN_IN;\r
-               if (cmd->fields[i].out_value)\r
-                       type |= SCAN_OUT;\r
-       }\r
-\r
-       return type;\r
-}\r
-\r
-int jtag_execute_queue(void)\r
-{\r
-       int retval;\r
-\r
-       retval = jtag->execute_queue();\r
-       \r
-       cmd_queue_free();\r
-\r
-       jtag_command_queue = NULL;\r
-       last_comand_pointer = &jtag_command_queue;\r
-\r
-       return retval;\r
-}\r
-\r
-int jtag_reset_callback(enum jtag_event event, void *priv)\r
-{\r
-       jtag_device_t *device = priv;\r
-\r
-       DEBUG("-");\r
-       \r
-       if (event == JTAG_TRST_ASSERTED)\r
-       {\r
-               buf_set_ones(device->cur_instr, device->ir_length);\r
-               device->bypass = 1;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-void jtag_sleep(u32 us)\r
-{\r
-       usleep(us);\r
-}\r
-\r
-/* Try to examine chain layout according to IEEE 1149.1 Â§12\r
- */\r
-int jtag_examine_chain()\r
-{\r
-       jtag_device_t *device = jtag_devices;\r
-       scan_field_t field;\r
-       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];\r
-       int i;\r
-       int bit_count;\r
-       int device_count = 0;\r
-       u8 zero_check = 0x0;\r
-       u8 one_check = 0xff;\r
-       \r
-       field.device = 0;\r
-       field.num_bits = sizeof(idcode_buffer) * 8;\r
-       field.out_value = idcode_buffer;\r
-       field.out_mask = NULL;\r
-       field.in_value = idcode_buffer;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)\r
-       {\r
-               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);\r
-       }\r
-       \r
-       jtag_add_plain_dr_scan(1, &field, TAP_TLR);\r
-       jtag_execute_queue();\r
-       \r
-       for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)\r
-       {\r
-               zero_check |= idcode_buffer[i];\r
-               one_check &= idcode_buffer[i];\r
-       }\r
-       \r
-       /* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */\r
-       if ((zero_check == 0x00) || (one_check == 0xff))\r
-       {\r
-               ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)\r
-       {\r
-               u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);\r
-               if ((idcode & 1) == 0)\r
-               {\r
-                       /* LSB must not be 0, this indicates a device in bypass */\r
-                       device_count++;\r
-                       \r
-                       bit_count += 1;\r
-               }\r
-               else\r
-               {\r
-                       u32 manufacturer;\r
-                       u32 part;\r
-                       u32 version;\r
-                       \r
-                       if (idcode == 0x000000FF)\r
-                       {\r
-                               /* End of chain (invalid manufacturer ID) */\r
-                               break;\r
-                       }\r
-                       \r
-                       if (device)\r
-                       {\r
-                               device->idcode = idcode;\r
-                               device = device->next;\r
-                       }\r
-                       device_count++;\r
-                       \r
-                       manufacturer = (idcode & 0xffe) >> 1;\r
-                       part = (idcode & 0xffff000) >> 12;\r
-                       version = (idcode & 0xf0000000) >> 28;\r
-\r
-                       INFO("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)", \r
-                               idcode, manufacturer, part, version);\r
-                       \r
-                       bit_count += 32;\r
-               }\r
-       }\r
-       \r
-       /* see if number of discovered devices matches configuration */\r
-       if (device_count != jtag_num_devices)\r
-       {\r
-               ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", \r
-                       device_count, jtag_num_devices);\r
-               ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_validate_chain()\r
-{\r
-       jtag_device_t *device = jtag_devices;\r
-       int total_ir_length = 0;\r
-       u8 *ir_test = NULL;\r
-       scan_field_t field;\r
-       int chain_pos = 0;\r
-       \r
-       while (device)\r
-       {\r
-               total_ir_length += device->ir_length;\r
-               device = device->next;\r
-       }\r
-       \r
-       total_ir_length += 2;\r
-       ir_test = malloc(CEIL(total_ir_length, 8));\r
-       buf_set_ones(ir_test, total_ir_length);\r
-       \r
-       field.device = 0;\r
-       field.num_bits = total_ir_length;\r
-       field.out_value = ir_test;\r
-       field.out_mask = NULL;\r
-       field.in_value = ir_test;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       jtag_add_plain_ir_scan(1, &field, TAP_TLR);\r
-       jtag_execute_queue();\r
-       \r
-       device = jtag_devices;\r
-       while (device)\r
-       {\r
-               if (buf_get_u32(ir_test, chain_pos, 2) != 0x1)\r
-               {\r
-                       char *cbuf = buf_to_str(ir_test, total_ir_length, 16);\r
-                       ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);\r
-                       free(cbuf);\r
-                       free(ir_test);\r
-                       return ERROR_JTAG_INIT_FAILED;\r
-               }\r
-               chain_pos += device->ir_length;\r
-               device = device->next;\r
-       }\r
-       \r
-       if (buf_get_u32(ir_test, chain_pos, 2) != 0x3)\r
-       {\r
-               char *cbuf = buf_to_str(ir_test, total_ir_length, 16);\r
-               ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);\r
-               free(cbuf);\r
-               free(ir_test);\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-       \r
-       free(ir_test);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, NULL, "interface", handle_interface_command,\r
-               COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,\r
-               COMMAND_ANY, "set jtag speed (if supported) <speed>");\r
-       register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,\r
-               COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");\r
-       register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,\r
-               COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,\r
-               COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,\r
-               COMMAND_CONFIG, NULL);\r
-               \r
-       register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,\r
-               COMMAND_EXEC, "print current scan chain configuration");\r
-\r
-       register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,\r
-               COMMAND_EXEC, "finish JTAG operations in <tap_state>");\r
-       register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,\r
-               COMMAND_EXEC, "toggle reset lines <trst> <srst>");\r
-       register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,\r
-               COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");\r
-       register_command(cmd_ctx, NULL, "statemove", handle_statemove_command,\r
-               COMMAND_EXEC, "move to current endstate or [tap_state]");\r
-       register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,\r
-               COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");\r
-       register_command(cmd_ctx, NULL, "drscan", handle_drscan_command,\r
-               COMMAND_EXEC, "execute DR scan <device> <var> [dev2] [var2] ...");\r
-\r
-       register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,\r
-               COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");\r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_interface_init(struct command_context_s *cmd_ctx)\r
-{\r
-       if (!jtag_interface)\r
-       {\r
-               /* nothing was previously specified by "interface" command */\r
-               ERROR("JTAG interface has to be specified, see \"interface\" command");\r
-               return ERROR_JTAG_INVALID_INTERFACE;\r
-       }\r
-\r
-       if (jtag_interface->init() != ERROR_OK)\r
-               return ERROR_JTAG_INIT_FAILED;\r
-\r
-       jtag = jtag_interface;\r
-       return ERROR_OK;\r
-}\r
-\r
-int jtag_init(struct command_context_s *cmd_ctx)\r
-{\r
-       int i, validate_tries = 0;\r
-       jtag_device_t *device;\r
-\r
-       DEBUG("-");\r
-       \r
-       if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)\r
-               return ERROR_JTAG_INIT_FAILED;\r
-\r
-       device = jtag_devices;\r
-       jtag_ir_scan_size = 0;\r
-       jtag_num_devices = 0;\r
-       while (device != NULL)\r
-       {\r
-               jtag_ir_scan_size += device->ir_length;\r
-               jtag_num_devices++;\r
-               device = device->next;\r
-       }\r
-       \r
-       jtag_add_statemove(TAP_TLR);\r
-       jtag_execute_queue();\r
-\r
-       /* examine chain first, as this could discover the real chain layout */\r
-       if (jtag_examine_chain() != ERROR_OK)\r
-       {\r
-               ERROR("trying to validate configured JTAG chain anyway...");\r
-       }\r
-       \r
-       while (jtag_validate_chain() != ERROR_OK)\r
-       {\r
-               validate_tries++;\r
-               if (validate_tries > 5)\r
-               {\r
-                       ERROR("Could not validate JTAG chain, exit");\r
-                       jtag = NULL;\r
-                       return ERROR_JTAG_INVALID_INTERFACE;\r
-               }\r
-               usleep(10000);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int i;\r
-\r
-       /* check whether the interface is already configured */\r
-       if (jtag_interface)\r
-       {\r
-               WARNING("Interface already configured, ignoring");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       /* interface name is a mandatory argument */\r
-       if (argc < 1 || args[0][0] == '\0')\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       for (i=0; jtag_interfaces[i]; i++)\r
-       {\r
-               if (strcmp(args[0], jtag_interfaces[i]->name) == 0)\r
-               {\r
-                       if (jtag_interfaces[i]->register_commands(cmd_ctx) != ERROR_OK)\r
-                               exit(-1);\r
-\r
-                       jtag_interface = jtag_interfaces[i];\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-\r
-       /* no valid interface was found (i.e. the configuration option,\r
-        * didn't match one of the compiled-in interfaces\r
-        */\r
-       ERROR("No valid jtag interface found (%s)", args[0]);\r
-       ERROR("compiled-in jtag interfaces:");\r
-       for (i = 0; jtag_interfaces[i]; i++)\r
-       {\r
-               ERROR("%i: %s", i, jtag_interfaces[i]->name);\r
-       }\r
-\r
-       return ERROR_JTAG_INVALID_INTERFACE;\r
-}\r
-\r
-int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       jtag_device_t **last_device_p = &jtag_devices;\r
-\r
-       if (*last_device_p)\r
-       {\r
-               while ((*last_device_p)->next)\r
-                       last_device_p = &((*last_device_p)->next);\r
-               last_device_p = &((*last_device_p)->next);\r
-       }\r
-\r
-       if (argc < 3)\r
-               return ERROR_OK;\r
-\r
-       *last_device_p = malloc(sizeof(jtag_device_t));\r
-       (*last_device_p)->ir_length = strtoul(args[0], NULL, 0);\r
-\r
-       (*last_device_p)->expected = malloc((*last_device_p)->ir_length);\r
-       buf_set_u32((*last_device_p)->expected, 0, (*last_device_p)->ir_length, strtoul(args[1], NULL, 0));\r
-       (*last_device_p)->expected_mask = malloc((*last_device_p)->ir_length);\r
-       buf_set_u32((*last_device_p)->expected_mask, 0, (*last_device_p)->ir_length, strtoul(args[2], NULL, 0));\r
-\r
-       (*last_device_p)->cur_instr = malloc((*last_device_p)->ir_length);\r
-       (*last_device_p)->bypass = 1;\r
-       buf_set_ones((*last_device_p)->cur_instr, (*last_device_p)->ir_length);\r
-       \r
-       (*last_device_p)->next = NULL;\r
-       \r
-       jtag_register_event_callback(jtag_reset_callback, (*last_device_p));\r
-       \r
-       jtag_num_devices++;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       jtag_device_t *device = jtag_devices;\r
-       int device_count = 0;\r
-       \r
-       while (device)\r
-       {\r
-               u32 expected, expected_mask, cur_instr;\r
-               expected = buf_get_u32(device->expected, 0, device->ir_length);\r
-               expected_mask = buf_get_u32(device->expected_mask, 0, device->ir_length);\r
-               cur_instr = buf_get_u32(device->cur_instr, 0, device->ir_length);\r
-               command_print(cmd_ctx, "%i: idcode: 0x%8.8x ir length %i, ir capture 0x%x, ir mask 0x%x, current instruction 0x%x", device_count, device->idcode, device->ir_length, expected, expected_mask, cur_instr);\r
-               device = device->next;\r
-               device_count++;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc >= 1)\r
-       {\r
-               if (strcmp(args[0], "none") == 0)\r
-                       jtag_reset_config = RESET_NONE;\r
-               else if (strcmp(args[0], "trst_only") == 0)\r
-                       jtag_reset_config = RESET_HAS_TRST;\r
-               else if (strcmp(args[0], "srst_only") == 0)\r
-                       jtag_reset_config = RESET_HAS_SRST;\r
-               else if (strcmp(args[0], "trst_and_srst") == 0)\r
-                       jtag_reset_config = RESET_TRST_AND_SRST;\r
-               else\r
-               {\r
-                       ERROR("invalid reset_config argument, defaulting to none");\r
-                       jtag_reset_config = RESET_NONE;\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-       }\r
-       \r
-       if (argc >= 2)\r
-       {\r
-               if (strcmp(args[1], "srst_pulls_trst") == 0)\r
-                       jtag_reset_config |= RESET_SRST_PULLS_TRST;\r
-               else if (strcmp(args[1], "trst_pulls_srst") == 0)\r
-                       jtag_reset_config |= RESET_TRST_PULLS_SRST;\r
-               else if (strcmp(args[1], "combined") == 0)\r
-                       jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;\r
-               else if (strcmp(args[1], "separate") == 0)\r
-                       jtag_reset_config &= ~(RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST);\r
-               else\r
-               {\r
-                       ERROR("invalid reset_config argument, defaulting to none");\r
-                       jtag_reset_config = RESET_NONE;\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-       }\r
-       \r
-       if (argc >= 3)\r
-       {\r
-               if (strcmp(args[2], "trst_open_drain") == 0)\r
-                       jtag_reset_config |= RESET_TRST_OPEN_DRAIN;\r
-               else if (strcmp(args[2], "trst_push_pull") == 0)\r
-                       jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN;\r
-               else\r
-               {\r
-                       ERROR("invalid reset_config argument, defaulting to none");\r
-                       jtag_reset_config = RESET_NONE;\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-       }\r
-\r
-       if (argc >= 4)\r
-       {\r
-               if (strcmp(args[3], "srst_push_pull") == 0)\r
-                       jtag_reset_config |= RESET_SRST_PUSH_PULL;\r
-               else if (strcmp(args[3], "srst_open_drain") == 0)\r
-                       jtag_reset_config &= ~RESET_SRST_PUSH_PULL;\r
-               else\r
-               {\r
-                       ERROR("invalid reset_config argument, defaulting to none");\r
-                       jtag_reset_config = RESET_NONE;\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc < 1)\r
-       {\r
-               ERROR("jtag_nsrst_delay <ms> command takes one required argument");\r
-               exit(-1);\r
-       }\r
-       else\r
-       {\r
-               jtag_nsrst_delay = strtoul(args[0], NULL, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc < 1)\r
-       {\r
-               ERROR("jtag_ntrst_delay <ms> command takes one required argument");\r
-               exit(-1);\r
-       }\r
-       else\r
-       {\r
-               jtag_ntrst_delay = strtoul(args[0], NULL, 0);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 0)\r
-               command_print(cmd_ctx, "jtag_speed: %i", jtag_speed);\r
-\r
-       if (argc > 0)\r
-       {\r
-               /* this command can be called during CONFIG, \r
-                * in which case jtag isn't initialized */\r
-               if (jtag)\r
-                       jtag->speed(strtoul(args[0], NULL, 0));\r
-               else\r
-                       jtag_speed = strtoul(args[0], NULL, 0);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       enum tap_state state;\r
-\r
-       if (argc < 1)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       else\r
-       {\r
-               for (state = 0; state < 16; state++)\r
-               {\r
-                       if (strcmp(args[0], tap_state_strings[state]) == 0)\r
-                       {\r
-                               jtag_add_end_state(state);\r
-                               jtag_execute_queue();\r
-                       }\r
-               }\r
-       }\r
-       command_print(cmd_ctx, "current endstate: %s", tap_state_strings[end_state]);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int trst = -1;\r
-       int srst = -1;\r
-       int retval;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-\r
-       }\r
-\r
-       if (args[0][0] == '1')\r
-               trst = 1;\r
-       else if (args[0][0] == '0')\r
-               trst = 0;\r
-       else\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       if (args[1][0] == '1')\r
-               srst = 1;\r
-       else if (args[1][0] == '0')\r
-               srst = 0;\r
-       else\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)\r
-               return ERROR_JTAG_INIT_FAILED;\r
-\r
-       if ((retval = jtag_add_reset(trst, srst)) != ERROR_OK)\r
-       {\r
-               switch (retval)\r
-               {\r
-                       case ERROR_JTAG_RESET_WOULD_ASSERT_TRST:\r
-                               command_print(cmd_ctx, "requested reset would assert trst\nif this is acceptable, use jtag_reset 1 %c", args[1][0]);\r
-                               break;\r
-                       case ERROR_JTAG_RESET_CANT_SRST:\r
-                               command_print(cmd_ctx, "can't assert srst because the current reset_config doesn't support it");\r
-                               break;\r
-                       default:\r
-                               command_print(cmd_ctx, "unknown error");\r
-               }\r
-       }\r
-       jtag_execute_queue();\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc < 1)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       jtag_add_runtest(strtol(args[0], NULL, 0), -1);\r
-       jtag_execute_queue();\r
-\r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       enum tap_state state;\r
-\r
-       state = -1;\r
-       if (argc == 1)\r
-       {\r
-               for (state = 0; state < 16; state++)\r
-               {\r
-                       if (strcmp(args[0], tap_state_strings[state]) == 0)\r
-                       {\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-       jtag_add_statemove(state);\r
-       jtag_execute_queue();\r
-\r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int i;\r
-       scan_field_t *fields;\r
-       \r
-       if ((argc < 2) || (argc % 2))\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       fields = malloc(sizeof(scan_field_t) * argc / 2);\r
-       \r
-       for (i = 0; i < argc / 2; i++)\r
-       {\r
-               int device = strtoul(args[i*2], NULL, 0);\r
-               int field_size = jtag_get_device(device)->ir_length;\r
-               fields[i].device = device;\r
-               fields[i].out_value = malloc(CEIL(field_size, 8));\r
-               buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0));\r
-               fields[i].out_mask = NULL;\r
-               fields[i].in_value = NULL;\r
-               fields[i].in_check_mask = NULL;\r
-               fields[i].in_handler = NULL;\r
-               fields[i].in_handler_priv = NULL;\r
-       }\r
-\r
-       jtag_add_ir_scan(argc / 2, fields, -1);\r
-       jtag_execute_queue();\r
-\r
-       for (i = 0; i < argc / 2; i++)\r
-               free(fields[i].out_value);\r
-\r
-       free (fields);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       scan_field_t *fields;\r
-       int num_fields = 0;\r
-       int field_count = 0;\r
-       var_t *var;\r
-       int i, j;\r
-       \r
-       if ((argc < 2) || (argc % 2))\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       for (i = 0; i < argc; i+=2)\r
-       {\r
-               var = get_var_by_namenum(args[i+1]);\r
-               if (var)\r
-               {\r
-                       num_fields += var->num_fields;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "variable %s doesn't exist", args[i+1]);\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-\r
-       fields = malloc(sizeof(scan_field_t) * num_fields);\r
-\r
-       for (i = 0; i < argc; i+=2)\r
-       {\r
-               var = get_var_by_namenum(args[i+1]);\r
-       \r
-               for (j = 0; j < var->num_fields; j++)\r
-               {\r
-                       fields[field_count].device = strtol(args[i], NULL, 0);\r
-                       fields[field_count].num_bits = var->fields[j].num_bits;\r
-                       fields[field_count].out_value = malloc(CEIL(var->fields[j].num_bits, 8));\r
-                       buf_set_u32(fields[field_count].out_value, 0, var->fields[j].num_bits, var->fields[j].value);\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 = field_le_to_host;\r
-                       fields[field_count++].in_handler_priv = &(var->fields[j]);\r
-               }\r
-       }\r
-\r
-       jtag_add_dr_scan(num_fields, fields, -1);\r
-       jtag_execute_queue();\r
-       \r
-       for (i = 0; i < argc / 2; i++)\r
-               free(fields[i].out_value);\r
-\r
-       free(fields);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "enable") == 0)\r
-               {\r
-                       jtag_verify_capture_ir = 1;\r
-               }\r
-               else if (strcmp(args[0], "disable") == 0)\r
-               {\r
-                       jtag_verify_capture_ir = 0;\r
-               } else\r
-               {\r
-                       return ERROR_COMMAND_SYNTAX_ERROR;\r
-               }\r
-       } else if (argc != 0)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       \r
-       command_print(cmd_ctx, "verify Capture-IR is %s", (jtag_verify_capture_ir) ? "enabled": "disabled");\r
-       \r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "jtag.h"
+
+#include "command.h"
+#include "log.h"
+#include "interpreter.h"
+
+#include "stdlib.h"
+#include "string.h"
+#include <unistd.h>
+
+char* tap_state_strings[16] =
+{
+       "tlr", 
+       "sds", "cd", "sd", "e1d", "pd", "e2d", "ud",
+       "rti",
+       "sis", "ci", "si", "e1i", "pi", "e2i", "ui"
+};
+
+typedef struct cmd_queue_page_s
+{
+       void *address;
+       size_t used;
+       struct cmd_queue_page_s *next;
+} cmd_queue_page_t;
+
+#define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
+static cmd_queue_page_t *cmd_queue_pages = NULL;
+
+/* tap_move[i][j]: tap movement command to go from state i to state j
+ * 0: Test-Logic-Reset
+ * 1: Run-Test/Idle
+ * 2: Shift-DR
+ * 3: Pause-DR
+ * 4: Shift-IR
+ * 5: Pause-IR
+ * 
+ * SD->SD and SI->SI have to be caught in interface specific code
+ */
+u8 tap_move[6][6] =
+{
+/*       TLR   RTI   SD    PD    SI    PI             */
+       {0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16},   /* TLR */
+       {0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b},   /* RTI */
+       {0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f},   /* SD  */
+       {0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f},   /* PD  */
+       {0x7f, 0x31, 0x07, 0x17, 0x00, 0x01},   /* SI  */
+       {0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f}    /* PI  */
+};
+
+int tap_move_map[16] = {
+       0, -1, -1,  2, -1,  3, -1, -1,
+       1, -1, -1,  4, -1,  5, -1, -1
+};
+
+tap_transition_t tap_transitions[16] =
+{
+       {TAP_TLR, TAP_RTI},             /* TLR */
+       {TAP_SIS, TAP_CD},              /* SDS */
+       {TAP_E1D, TAP_SD},              /* CD  */
+       {TAP_E1D, TAP_SD},              /* SD  */
+       {TAP_UD,  TAP_PD},              /* E1D */
+       {TAP_E2D, TAP_PD},              /* PD  */
+       {TAP_UD,  TAP_SD},              /* E2D */
+       {TAP_SDS, TAP_RTI},             /* UD  */
+       {TAP_SDS, TAP_RTI},             /* RTI */
+       {TAP_TLR, TAP_CI},              /* SIS */
+       {TAP_E1I, TAP_SI},              /* CI  */
+       {TAP_E1I, TAP_SI},              /* SI  */
+       {TAP_UI,  TAP_PI},              /* E1I */
+       {TAP_E2I, TAP_PI},              /* PI  */
+       {TAP_UI,  TAP_SI},              /* E2I */
+       {TAP_SDS, TAP_RTI}              /* UI  */
+};
+
+char* jtag_event_strings[] =
+{
+       "SRST asserted",
+       "TRST asserted",
+       "SRST released",
+       "TRST released"
+};
+
+enum tap_state end_state = TAP_TLR;
+enum tap_state cur_state = TAP_TLR;
+int jtag_trst = 0;
+int jtag_srst = 0;
+
+jtag_command_t *jtag_command_queue = NULL;
+jtag_command_t **last_comand_pointer = &jtag_command_queue;
+jtag_device_t *jtag_devices = NULL;
+int jtag_num_devices = 0;
+int jtag_ir_scan_size = 0;
+enum reset_types jtag_reset_config = RESET_NONE;
+enum tap_state cmd_queue_end_state = TAP_TLR;
+enum tap_state cmd_queue_cur_state = TAP_TLR;
+
+int jtag_verify_capture_ir = 1;
+
+/* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */
+int jtag_nsrst_delay = 0; /* default to no nSRST delay */
+int jtag_ntrst_delay = 0; /* default to no nTRST delay */ 
+
+/* maximum number of JTAG devices expected in the chain
+ */
+#define JTAG_MAX_CHAIN_SIZE 20 
+
+/* callbacks to inform high-level handlers about JTAG state changes */
+jtag_event_callback_t *jtag_event_callbacks;
+
+/* jtag interfaces (parport, FTDI-USB, TI-USB, ...)
+ */
+#if BUILD_PARPORT == 1
+       extern jtag_interface_t parport_interface;
+#endif
+
+#if BUILD_FT2232_FTD2XX == 1
+       extern jtag_interface_t ft2232_interface;
+#endif
+
+#if BUILD_FT2232_LIBFTDI == 1
+       extern jtag_interface_t ft2232_interface;
+#endif
+
+#if BUILD_AMTJTAGACCEL == 1
+       extern jtag_interface_t amt_jtagaccel_interface;
+#endif
+
+#if BUILD_EP93XX == 1
+       extern jtag_interface_t ep93xx_interface;
+#endif
+
+#if BUILD_AT91RM9200 == 1
+       extern jtag_interface_t at91rm9200_interface;
+#endif
+
+#if BUILD_GW16012 == 1
+       extern jtag_interface_t gw16012_interface;
+#endif
+
+#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
+       extern jtag_interface_t presto_interface;
+#endif
+
+#if BUILD_USBPROG == 1
+       extern jtag_interface_t usbprog_interface;
+#endif
+
+jtag_interface_t *jtag_interfaces[] = {
+#if BUILD_PARPORT == 1
+       &parport_interface,
+#endif
+#if BUILD_FT2232_FTD2XX == 1
+       &ft2232_interface,
+#endif
+#if BUILD_FT2232_LIBFTDI == 1
+       &ft2232_interface,
+#endif
+#if BUILD_AMTJTAGACCEL == 1
+       &amt_jtagaccel_interface,
+#endif
+#if BUILD_EP93XX == 1
+       &ep93xx_interface,
+#endif
+#if BUILD_AT91RM9200 == 1
+       &at91rm9200_interface,
+#endif
+#if BUILD_GW16012 == 1
+       &gw16012_interface,
+#endif
+#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
+       &presto_interface,
+#endif
+#if BUILD_USBPROG == 1
+       &usbprog_interface,
+#endif
+       NULL,
+};
+
+jtag_interface_t *jtag = NULL;
+
+/* configuration */
+jtag_interface_t *jtag_interface = NULL;
+int jtag_speed = 0;
+
+
+/* forward declarations */
+int jtag_add_statemove(enum tap_state endstate);
+int jtag_add_pathmove(int num_states, enum tap_state *path);
+int jtag_add_runtest(int num_cycles, enum tap_state endstate);
+int jtag_add_reset(int trst, int srst);
+int jtag_add_end_state(enum tap_state endstate);
+int jtag_add_sleep(u32 us);
+int jtag_execute_queue(void);
+int jtag_cancel_queue(void);
+
+/* jtag commands */
+int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv)
+{
+       jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
+       
+       if (callback == NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       
+       if (*callbacks_p)
+       {
+               while ((*callbacks_p)->next)
+                       callbacks_p = &((*callbacks_p)->next);
+               callbacks_p = &((*callbacks_p)->next);
+       }
+       
+       (*callbacks_p) = malloc(sizeof(jtag_event_callback_t));
+       (*callbacks_p)->callback = callback;
+       (*callbacks_p)->priv = priv;
+       (*callbacks_p)->next = NULL;
+       
+       return ERROR_OK;
+}
+
+int jtag_unregister_event_callback(int (*callback)(enum jtag_event event, void *priv))
+{
+       jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
+       
+       if (callback == NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+               
+       while (*callbacks_p)
+       {
+               jtag_event_callback_t **next = &((*callbacks_p)->next);
+               if ((*callbacks_p)->callback == callback)
+               {
+                       free(*callbacks_p);
+                       *callbacks_p = *next;
+               }
+               callbacks_p = next;
+       }
+       
+       return ERROR_OK;
+}
+
+int jtag_call_event_callbacks(enum jtag_event event)
+{
+       jtag_event_callback_t *callback = jtag_event_callbacks;
+       
+       DEBUG("jtag event: %s", jtag_event_strings[event]);
+       
+       while (callback)
+       {
+               callback->callback(event, callback->priv);
+               callback = callback->next;
+       }
+       
+       return ERROR_OK;
+}
+
+/* returns a pointer to the pointer of the last command in queue
+ * this may be a pointer to the root pointer (jtag_command_queue)
+ * or to the next member of the last but one command
+ */
+jtag_command_t** jtag_get_last_command_p(void)
+{
+/*     jtag_command_t *cmd = jtag_command_queue;
+       
+       if (cmd)
+               while (cmd->next)
+                       cmd = cmd->next;
+       else
+               return &jtag_command_queue;
+       
+       return &cmd->next;*/
+       
+       return last_comand_pointer;
+}
+
+/* returns a pointer to the n-th device in the scan chain */
+jtag_device_t* jtag_get_device(int num)
+{
+       jtag_device_t *device = jtag_devices;
+       int i = 0;
+
+       while (device)
+       {
+               if (num == i)
+                       return device;
+               device = device->next;
+               i++;
+       }
+       
+       ERROR("jtag device number %d not defined", num);
+       exit(-1);
+}
+
+void* cmd_queue_alloc(size_t size)
+{
+       cmd_queue_page_t **p_page = &cmd_queue_pages;
+       int offset;
+
+       if (*p_page)
+       {
+               while ((*p_page)->next)
+                       p_page = &((*p_page)->next);
+               if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
+                       p_page = &((*p_page)->next);
+       }
+
+       if (!*p_page)
+       {
+               *p_page = malloc(sizeof(cmd_queue_page_t));
+               (*p_page)->used = 0;
+               (*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
+               (*p_page)->next = NULL;
+       }
+
+       offset = (*p_page)->used;
+       (*p_page)->used += size;
+       
+       u8 *t=(u8 *)((*p_page)->address);
+       return t + offset;
+}
+
+void cmd_queue_free()
+{
+       cmd_queue_page_t *page = cmd_queue_pages;
+
+       while (page)
+       {
+               cmd_queue_page_t *last = page;
+               free(page->address);
+               page = page->next;
+               free(last);
+       }
+
+       cmd_queue_pages = NULL;
+}
+
+int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+       jtag_command_t **last_cmd;
+       jtag_device_t *device;
+       int i, j;
+       int scan_size = 0;
+
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+
+       last_cmd = jtag_get_last_command_p();
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       (*last_cmd)->next = NULL;
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->type = JTAG_SCAN;
+
+       /* allocate memory for ir scan command */
+       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       (*last_cmd)->cmd.scan->ir_scan = 1;
+       (*last_cmd)->cmd.scan->num_fields = jtag_num_devices;   /* one field per device */
+       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(jtag_num_devices * sizeof(scan_field_t));
+       (*last_cmd)->cmd.scan->end_state = state;
+               
+       if (state != -1)
+               cmd_queue_end_state = state;
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+       
+       cmd_queue_cur_state = cmd_queue_end_state;
+               
+       for (i = 0; i < jtag_num_devices; i++)
+       {
+               int found = 0;
+               device = jtag_get_device(i);
+               scan_size = device->ir_length;
+               (*last_cmd)->cmd.scan->fields[i].device = i;
+               (*last_cmd)->cmd.scan->fields[i].num_bits = scan_size;
+               (*last_cmd)->cmd.scan->fields[i].in_value = NULL;
+               (*last_cmd)->cmd.scan->fields[i].in_handler = NULL;     /* disable verification by default */
+
+               /* search the list */
+               for (j = 0; j < num_fields; j++)
+               {
+                       if (i == fields[j].device)
+                       {
+                               found = 1;
+                               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                               (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                       
+                               if (jtag_verify_capture_ir)
+                               {
+                                       if (fields[j].in_handler==NULL)
+                                       {
+                                               jtag_set_check_value((*last_cmd)->cmd.scan->fields+i, device->expected, device->expected_mask, NULL);
+                                       } else
+                                       {
+                                               (*last_cmd)->cmd.scan->fields[i].in_handler = fields[j].in_handler;
+                                               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[j].in_handler_priv;
+                                               (*last_cmd)->cmd.scan->fields[i].in_check_value = device->expected; 
+                                               (*last_cmd)->cmd.scan->fields[i].in_check_mask = device->expected_mask;
+                                       }
+                               }
+                               
+                               device->bypass = 0;
+                               break;
+                       }
+               }
+       
+               if (!found)
+               {
+                       /* if a device isn't listed, set it to BYPASS */
+                       (*last_cmd)->cmd.scan->fields[i].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                       (*last_cmd)->cmd.scan->fields[i].out_mask = NULL;
+                       device->bypass = 1;
+               
+               }
+               
+               /* update device information */
+               buf_cpy((*last_cmd)->cmd.scan->fields[i].out_value, jtag_get_device(i)->cur_instr, scan_size);
+       }
+       
+       return ERROR_OK;
+}
+
+int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+       jtag_command_t **last_cmd;
+       int i;
+
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+
+       last_cmd = jtag_get_last_command_p();
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       (*last_cmd)->next = NULL;
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->type = JTAG_SCAN;
+
+       /* allocate memory for ir scan command */
+       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       (*last_cmd)->cmd.scan->ir_scan = 1;
+       (*last_cmd)->cmd.scan->num_fields = num_fields;
+       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
+       (*last_cmd)->cmd.scan->end_state = state;
+
+       if (state != -1)
+               cmd_queue_end_state = state;
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+               
+       cmd_queue_cur_state = cmd_queue_end_state;
+       
+       for (i = 0; i < num_fields; i++)
+       {
+               int num_bits = fields[i].num_bits;
+               int num_bytes = CEIL(fields[i].num_bits, 8);
+               (*last_cmd)->cmd.scan->fields[i].device = fields[i].device;
+               (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
+               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
+               (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);
+               (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
+               (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
+               (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
+               (*last_cmd)->cmd.scan->fields[i].in_handler = NULL;
+               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = NULL;
+       }
+       return ERROR_OK;
+}
+
+int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+       int i, j;
+       int bypass_devices = 0;
+       int field_count = 0;
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       jtag_device_t *device = jtag_devices;
+       int scan_size;
+
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+
+       /* count devices in bypass */
+       while (device)
+       {
+               if (device->bypass)
+                       bypass_devices++;
+               device = device->next;
+       }
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->next = NULL;
+       (*last_cmd)->type = JTAG_SCAN;
+
+       /* allocate memory for dr scan command */
+       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       (*last_cmd)->cmd.scan->ir_scan = 0;
+       (*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;
+       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
+       (*last_cmd)->cmd.scan->end_state = state;
+       
+       if (state != -1)
+               cmd_queue_end_state = state;
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+                       
+       cmd_queue_cur_state = cmd_queue_end_state;
+       
+       for (i = 0; i < jtag_num_devices; i++)
+       {
+               int found = 0;
+               (*last_cmd)->cmd.scan->fields[field_count].device = i;
+       
+               for (j = 0; j < num_fields; j++)
+               {
+                       if (i == fields[j].device)
+                       {
+                               found = 1;
+                               scan_size = fields[j].num_bits;
+                               (*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size;
+                               (*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                               (*last_cmd)->cmd.scan->fields[field_count].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+                               (*last_cmd)->cmd.scan->fields[field_count].in_value = fields[j].in_value;
+                               (*last_cmd)->cmd.scan->fields[field_count].in_check_value = fields[j].in_check_value;
+                               (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = fields[j].in_check_mask;
+                               (*last_cmd)->cmd.scan->fields[field_count].in_handler = fields[j].in_handler;
+                               (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = fields[j].in_handler_priv;
+                       }
+               }
+               if (!found)
+               {
+                       /* if a device isn't listed, the BYPASS register should be selected */
+                       if (!jtag_get_device(i)->bypass)
+                       {
+                               ERROR("BUG: no scan data for a device not in BYPASS");
+                               exit(-1);
+                       }
+       
+                       /* program the scan field to 1 bit length, and ignore it's value */
+                       (*last_cmd)->cmd.scan->fields[field_count].num_bits = 1;
+                       (*last_cmd)->cmd.scan->fields[field_count].out_value = NULL;
+                       (*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL;
+                       (*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;
+                       (*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;
+                       (*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;
+                       (*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;
+                       (*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;
+               }
+               else
+               {
+                       /* if a device is listed, the BYPASS register must not be selected */
+                       if (jtag_get_device(i)->bypass)
+                       {
+                               WARNING("scan data for a device in BYPASS");
+                       }
+               }
+       }
+       return ERROR_OK;
+}
+
+
+int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+       int i;
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->next = NULL;
+       (*last_cmd)->type = JTAG_SCAN;
+
+       /* allocate memory for scan command */
+       (*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+       (*last_cmd)->cmd.scan->ir_scan = 0;
+       (*last_cmd)->cmd.scan->num_fields = num_fields;
+       (*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
+       (*last_cmd)->cmd.scan->end_state = state;
+               
+       if (state != -1)
+               cmd_queue_end_state = state;
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+                       
+       cmd_queue_cur_state = cmd_queue_end_state;
+       
+       for (i = 0; i < num_fields; i++)
+       {
+               int num_bits = fields[i].num_bits;
+               int num_bytes = CEIL(fields[i].num_bits, 8);
+               (*last_cmd)->cmd.scan->fields[i].device = fields[i].device;
+               (*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
+               (*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
+               (*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);
+               (*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
+               (*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
+               (*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
+               (*last_cmd)->cmd.scan->fields[i].in_handler = fields[i].in_handler;
+               (*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[i].in_handler_priv;
+       }
+
+       return ERROR_OK;
+}
+int jtag_add_statemove(enum tap_state state)
+{
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->next = NULL;
+       (*last_cmd)->type = JTAG_STATEMOVE;
+
+       (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+       (*last_cmd)->cmd.statemove->end_state = state;
+       
+       if (state != -1)
+               cmd_queue_end_state = state;
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+                       
+       cmd_queue_cur_state = cmd_queue_end_state;
+       
+       return ERROR_OK;
+}
+
+int jtag_add_pathmove(int num_states, enum tap_state *path)
+{
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       int i;
+       
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+       
+       /* the last state has to be a stable state */
+       if (tap_move_map[path[num_states - 1]] == -1)
+       {
+               ERROR("TAP path doesn't finish in a stable state");
+               return ERROR_JTAG_NOT_IMPLEMENTED;
+       }
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->next = NULL;
+       (*last_cmd)->type = JTAG_PATHMOVE;
+
+       (*last_cmd)->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t));
+       (*last_cmd)->cmd.pathmove->num_states = num_states;
+       (*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states);
+       
+       for (i = 0; i < num_states; i++)
+               (*last_cmd)->cmd.pathmove->path[i] = path[i];
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+       
+       cmd_queue_cur_state = path[num_states - 1];
+       
+       return ERROR_OK;
+}
+
+int jtag_add_runtest(int num_cycles, enum tap_state state)
+{
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       
+       if (jtag_trst == 1)
+       {
+               WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+               return ERROR_JTAG_TRST_ASSERTED;
+       }
+
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       (*last_cmd)->next = NULL;
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->type = JTAG_RUNTEST;
+
+       (*last_cmd)->cmd.runtest = cmd_queue_alloc(sizeof(runtest_command_t));
+       (*last_cmd)->cmd.runtest->num_cycles = num_cycles;
+       (*last_cmd)->cmd.runtest->end_state = state;
+       
+       if (state != -1)
+               cmd_queue_end_state = state;
+
+       if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+       
+       if (cmd_queue_end_state == TAP_TLR)
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+                       
+       cmd_queue_cur_state = cmd_queue_end_state;
+       
+       return ERROR_OK;
+}
+
+int jtag_add_reset(int req_trst, int req_srst)
+{
+       int trst_with_tms = 0;
+       
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       
+       if (req_trst == -1)
+               req_trst = jtag_trst;
+       
+       if (req_srst == -1)
+               req_srst = jtag_srst;
+
+       /* Make sure that jtag_reset_config allows the requested reset */
+       /* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */
+       if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (req_trst == 0))
+               return ERROR_JTAG_RESET_WOULD_ASSERT_TRST;
+               
+       /* if TRST pulls SRST, we reset with TAP T-L-R */
+       if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_trst == 1)) && (req_srst == 0))
+       {
+               req_trst = 0;
+               trst_with_tms = 1;
+       }
+       
+       if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
+       {
+               ERROR("requested nSRST assertion, but the current configuration doesn't support this");
+               return ERROR_JTAG_RESET_CANT_SRST;
+       }
+       
+       if (req_trst && !(jtag_reset_config & RESET_HAS_TRST))
+       {
+               req_trst = 0;
+               trst_with_tms = 1;
+       }
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       (*last_cmd)->next = NULL;
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->type = JTAG_RESET;
+
+       (*last_cmd)->cmd.reset = cmd_queue_alloc(sizeof(reset_command_t));
+       (*last_cmd)->cmd.reset->trst = req_trst;
+       (*last_cmd)->cmd.reset->srst = req_srst;
+
+       jtag_trst = req_trst;
+       jtag_srst = req_srst;
+
+       if (jtag_srst)
+       {
+               jtag_call_event_callbacks(JTAG_SRST_ASSERTED);
+       }
+       else
+       {
+               jtag_call_event_callbacks(JTAG_SRST_RELEASED);
+               if (jtag_nsrst_delay)
+                       jtag_add_sleep(jtag_nsrst_delay * 1000);
+       }
+       
+       if (trst_with_tms)
+       {
+               last_cmd = &((*last_cmd)->next);
+               
+               /* allocate memory for a new list member */
+               *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+               (*last_cmd)->next = NULL;
+               last_comand_pointer = &((*last_cmd)->next);
+               (*last_cmd)->type = JTAG_STATEMOVE;
+
+               (*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+               (*last_cmd)->cmd.statemove->end_state = TAP_TLR;
+               
+               jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+               cmd_queue_cur_state = TAP_TLR;
+               cmd_queue_end_state = TAP_TLR;
+               
+               return ERROR_OK;
+       }
+       else
+       {
+               if (jtag_trst)
+               {
+                       /* we just asserted nTRST, so we're now in Test-Logic-Reset,
+                        * and inform possible listeners about this
+                        */
+                       cmd_queue_cur_state = TAP_TLR;
+                       jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+               }
+               else
+               {
+                       /* the nTRST line got deasserted, so we're still in Test-Logic-Reset,
+                        * but we might want to add a delay to give the TAP time to settle
+                        */
+                       if (jtag_ntrst_delay)
+                               jtag_add_sleep(jtag_ntrst_delay * 1000);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int jtag_add_end_state(enum tap_state state)
+{
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       (*last_cmd)->next = NULL;
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->type = JTAG_END_STATE;
+
+       (*last_cmd)->cmd.end_state = cmd_queue_alloc(sizeof(end_state_command_t));
+       (*last_cmd)->cmd.end_state->end_state = state;
+
+       if (state != -1)
+               cmd_queue_end_state = state;
+       
+       return ERROR_OK;
+}
+
+int jtag_add_sleep(u32 us)
+{
+       jtag_command_t **last_cmd = jtag_get_last_command_p();
+       
+       /* allocate memory for a new list member */
+       *last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+       (*last_cmd)->next = NULL;
+       last_comand_pointer = &((*last_cmd)->next);
+       (*last_cmd)->type = JTAG_SLEEP;
+
+       (*last_cmd)->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
+       (*last_cmd)->cmd.sleep->us = us;
+       
+       return ERROR_OK;
+}
+
+int jtag_scan_size(scan_command_t *cmd)
+{
+       int bit_count = 0;
+       int i;
+
+       /* count bits in scan command */
+       for (i = 0; i < cmd->num_fields; i++)
+       {
+               bit_count += cmd->fields[i].num_bits;
+       }
+
+       return bit_count;
+}
+
+int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
+{
+       int bit_count = 0;
+       int i;
+       
+       bit_count = jtag_scan_size(cmd);
+       *buffer = malloc(CEIL(bit_count, 8));
+       
+       bit_count = 0;
+
+       for (i = 0; i < cmd->num_fields; i++)
+       {
+               if (cmd->fields[i].out_value)
+               {
+#ifdef _DEBUG_JTAG_IO_
+                       char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16);
+#endif
+                       buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
+#ifdef _DEBUG_JTAG_IO_
+                       DEBUG("fields[%i].out_value: 0x%s", i, char_buf);
+                       free(char_buf);
+#endif
+               }
+               
+               bit_count += cmd->fields[i].num_bits;
+       }
+
+       return bit_count;
+
+}
+
+int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
+{
+       int i;
+       int bit_count = 0;
+       int retval;
+       
+       /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
+       retval = ERROR_OK;
+       
+       for (i = 0; i < cmd->num_fields; i++)
+       {
+               /* if neither in_value nor in_handler
+                * are specified we don't have to examine this field
+                */
+               if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
+               {
+                       int num_bits = cmd->fields[i].num_bits;
+                       u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
+                       
+#ifdef _DEBUG_JTAG_IO_
+                       char *char_buf;
+
+                       char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
+                       DEBUG("fields[%i].in_value: 0x%s", i, char_buf);
+                       free(char_buf);
+#endif
+                       
+                       if (cmd->fields[i].in_value)
+                       {
+                               buf_cpy(captured, cmd->fields[i].in_value, num_bits);
+                               
+                               if (cmd->fields[i].in_handler)
+                               {
+                                       if (cmd->fields[i].in_handler(cmd->fields[i].in_value, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
+                                       {
+                                               WARNING("in_handler reported a failed check");
+                                               retval = ERROR_JTAG_QUEUE_FAILED;
+                                       }
+                               }
+                       }
+                       
+                       /* no in_value specified, but a handler takes care of the scanned data */
+                       if (cmd->fields[i].in_handler && (!cmd->fields[i].in_value))
+                       {
+                               if (cmd->fields[i].in_handler(captured, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
+                               {
+                                       /* We're going to call the error:handler later, but if the in_handler
+                                        * reported an error we report this failure upstream
+                                        */
+                                       WARNING("in_handler reported a failed check");
+                                       retval = ERROR_JTAG_QUEUE_FAILED;
+                               }
+                       }
+
+                       free(captured);
+               }
+               bit_count += cmd->fields[i].num_bits;
+       }
+
+       return retval;
+}
+
+int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)
+{
+       int retval = ERROR_OK;
+       int num_bits = field->num_bits;
+       
+       int compare_failed = 0;
+       
+       if (field->in_check_mask)
+               compare_failed = buf_cmp_mask(captured, field->in_check_value, field->in_check_mask, num_bits);
+       else
+               compare_failed = buf_cmp(captured, field->in_check_value, num_bits);
+       
+       if (compare_failed)
+               {
+               /* An error handler could have caught the failing check
+                * only report a problem when there wasn't a handler, or if the handler
+                * acknowledged the error
+                */ 
+               if (compare_failed)
+               {
+                       char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
+                       char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > 64) ? 64 : num_bits, 16);
+
+                       if (field->in_check_mask)
+                       {
+                               char *in_check_mask_char;
+                               in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16);
+                               WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char);
+                               free(in_check_mask_char);
+                       }
+                       else
+                       {
+                               WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char);
+                       }
+
+                       free(captured_char);
+                       free(in_check_value_char);
+                       
+                       retval = ERROR_JTAG_QUEUE_FAILED;
+               }
+               
+       }
+       return retval;
+}
+
+/* 
+  set up checking of this field using the in_handler. The values passed in must be valid until
+  after jtag_execute() has completed.
+ */
+void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handler_t *in_error_handler)
+{
+       if (value)
+               field->in_handler = jtag_check_value;
+       else
+               field->in_handler = NULL;       /* No check, e.g. embeddedice uses value==NULL to indicate no check */
+       field->in_handler_priv = NULL;  /* this will be filled in at the invocation site to point to the field duplicate */ 
+       field->in_check_value = value;
+       field->in_check_mask = mask;
+}
+
+enum scan_type jtag_scan_type(scan_command_t *cmd)
+{
+       int i;
+       int type = 0;
+       
+       for (i = 0; i < cmd->num_fields; i++)
+       {
+               if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
+                       type |= SCAN_IN;
+               if (cmd->fields[i].out_value)
+                       type |= SCAN_OUT;
+       }
+
+       return type;
+}
+
+int jtag_execute_queue(void)
+{
+       int retval;
+
+       retval = jtag->execute_queue();
+       
+       cmd_queue_free();
+
+       jtag_command_queue = NULL;
+       last_comand_pointer = &jtag_command_queue;
+
+       return retval;
+}
+
+int jtag_reset_callback(enum jtag_event event, void *priv)
+{
+       jtag_device_t *device = priv;
+
+       DEBUG("-");
+       
+       if (event == JTAG_TRST_ASSERTED)
+       {
+               buf_set_ones(device->cur_instr, device->ir_length);
+               device->bypass = 1;
+       }
+       
+       return ERROR_OK;
+}
+
+void jtag_sleep(u32 us)
+{
+       usleep(us);
+}
+
+/* Try to examine chain layout according to IEEE 1149.1 Â§12
+ */
+int jtag_examine_chain()
+{
+       jtag_device_t *device = jtag_devices;
+       scan_field_t field;
+       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+       int i;
+       int bit_count;
+       int device_count = 0;
+       u8 zero_check = 0x0;
+       u8 one_check = 0xff;
+       
+       field.device = 0;
+       field.num_bits = sizeof(idcode_buffer) * 8;
+       field.out_value = idcode_buffer;
+       field.out_mask = NULL;
+       field.in_value = idcode_buffer;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+       {
+               buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+       }
+       
+       jtag_add_plain_dr_scan(1, &field, TAP_TLR);
+       jtag_execute_queue();
+       
+       for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
+       {
+               zero_check |= idcode_buffer[i];
+               one_check &= idcode_buffer[i];
+       }
+       
+       /* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */
+       if ((zero_check == 0x00) || (one_check == 0xff))
+       {
+               ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
+       {
+               u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
+               if ((idcode & 1) == 0)
+               {
+                       /* LSB must not be 0, this indicates a device in bypass */
+                       device_count++;
+                       
+                       bit_count += 1;
+               }
+               else
+               {
+                       u32 manufacturer;
+                       u32 part;
+                       u32 version;
+                       
+                       if (idcode == 0x000000FF)
+                       {
+                               /* End of chain (invalid manufacturer ID) */
+                               break;
+                       }
+                       
+                       if (device)
+                       {
+                               device->idcode = idcode;
+                               device = device->next;
+                       }
+                       device_count++;
+                       
+                       manufacturer = (idcode & 0xffe) >> 1;
+                       part = (idcode & 0xffff000) >> 12;
+                       version = (idcode & 0xf0000000) >> 28;
+
+                       INFO("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)", 
+                               idcode, manufacturer, part, version);
+                       
+                       bit_count += 32;
+               }
+       }
+       
+       /* see if number of discovered devices matches configuration */
+       if (device_count != jtag_num_devices)
+       {
+               ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", 
+                       device_count, jtag_num_devices);
+               ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int jtag_validate_chain()
+{
+       jtag_device_t *device = jtag_devices;
+       int total_ir_length = 0;
+       u8 *ir_test = NULL;
+       scan_field_t field;
+       int chain_pos = 0;
+       
+       while (device)
+       {
+               total_ir_length += device->ir_length;
+               device = device->next;
+       }
+       
+       total_ir_length += 2;
+       ir_test = malloc(CEIL(total_ir_length, 8));
+       buf_set_ones(ir_test, total_ir_length);
+       
+       field.device = 0;
+       field.num_bits = total_ir_length;
+       field.out_value = ir_test;
+       field.out_mask = NULL;
+       field.in_value = ir_test;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       jtag_add_plain_ir_scan(1, &field, TAP_TLR);
+       jtag_execute_queue();
+       
+       device = jtag_devices;
+       while (device)
+       {
+               if (buf_get_u32(ir_test, chain_pos, 2) != 0x1)
+               {
+                       char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
+                       ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);
+                       free(cbuf);
+                       free(ir_test);
+                       return ERROR_JTAG_INIT_FAILED;
+               }
+               chain_pos += device->ir_length;
+               device = device->next;
+       }
+       
+       if (buf_get_u32(ir_test, chain_pos, 2) != 0x3)
+       {
+               char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
+               ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);
+               free(cbuf);
+               free(ir_test);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       
+       free(ir_test);
+       
+       return ERROR_OK;
+}
+
+int jtag_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "interface", handle_interface_command,
+               COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
+               COMMAND_ANY, "set jtag speed (if supported) <speed>");
+       register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
+               COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");
+       register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
+               COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
+               COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
+               COMMAND_CONFIG, NULL);
+               
+       register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
+               COMMAND_EXEC, "print current scan chain configuration");
+
+       register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,
+               COMMAND_EXEC, "finish JTAG operations in <tap_state>");
+       register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
+               COMMAND_EXEC, "toggle reset lines <trst> <srst>");
+       register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
+               COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
+       register_command(cmd_ctx, NULL, "statemove", handle_statemove_command,
+               COMMAND_EXEC, "move to current endstate or [tap_state]");
+       register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
+               COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
+       register_command(cmd_ctx, NULL, "drscan", handle_drscan_command,
+               COMMAND_EXEC, "execute DR scan <device> <var> [dev2] [var2] ...");
+
+       register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
+               COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
+       return ERROR_OK;
+}
+
+int jtag_interface_init(struct command_context_s *cmd_ctx)
+{
+       if (!jtag_interface)
+       {
+               /* nothing was previously specified by "interface" command */
+               ERROR("JTAG interface has to be specified, see \"interface\" command");
+               return ERROR_JTAG_INVALID_INTERFACE;
+       }
+
+       if (jtag_interface->init() != ERROR_OK)
+               return ERROR_JTAG_INIT_FAILED;
+
+       jtag = jtag_interface;
+       return ERROR_OK;
+}
+
+int jtag_init(struct command_context_s *cmd_ctx)
+{
+       int i, validate_tries = 0;
+       jtag_device_t *device;
+
+       DEBUG("-");
+       
+       if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)
+               return ERROR_JTAG_INIT_FAILED;
+
+       device = jtag_devices;
+       jtag_ir_scan_size = 0;
+       jtag_num_devices = 0;
+       while (device != NULL)
+       {
+               jtag_ir_scan_size += device->ir_length;
+               jtag_num_devices++;
+               device = device->next;
+       }
+       
+       jtag_add_statemove(TAP_TLR);
+       jtag_execute_queue();
+
+       /* examine chain first, as this could discover the real chain layout */
+       if (jtag_examine_chain() != ERROR_OK)
+       {
+               ERROR("trying to validate configured JTAG chain anyway...");
+       }
+       
+       while (jtag_validate_chain() != ERROR_OK)
+       {
+               validate_tries++;
+               if (validate_tries > 5)
+               {
+                       ERROR("Could not validate JTAG chain, exit");
+                       jtag = NULL;
+                       return ERROR_JTAG_INVALID_INTERFACE;
+               }
+               usleep(10000);
+       }
+
+       return ERROR_OK;
+}
+
+int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int i;
+
+       /* check whether the interface is already configured */
+       if (jtag_interface)
+       {
+               WARNING("Interface already configured, ignoring");
+               return ERROR_OK;
+       }
+
+       /* interface name is a mandatory argument */
+       if (argc < 1 || args[0][0] == '\0')
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       for (i=0; jtag_interfaces[i]; i++)
+       {
+               if (strcmp(args[0], jtag_interfaces[i]->name) == 0)
+               {
+                       if (jtag_interfaces[i]->register_commands(cmd_ctx) != ERROR_OK)
+                               exit(-1);
+
+                       jtag_interface = jtag_interfaces[i];
+                       return ERROR_OK;
+               }
+       }
+
+       /* no valid interface was found (i.e. the configuration option,
+        * didn't match one of the compiled-in interfaces
+        */
+       ERROR("No valid jtag interface found (%s)", args[0]);
+       ERROR("compiled-in jtag interfaces:");
+       for (i = 0; jtag_interfaces[i]; i++)
+       {
+               ERROR("%i: %s", i, jtag_interfaces[i]->name);
+       }
+
+       return ERROR_JTAG_INVALID_INTERFACE;
+}
+
+int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       jtag_device_t **last_device_p = &jtag_devices;
+
+       if (*last_device_p)
+       {
+               while ((*last_device_p)->next)
+                       last_device_p = &((*last_device_p)->next);
+               last_device_p = &((*last_device_p)->next);
+       }
+
+       if (argc < 3)
+               return ERROR_OK;
+
+       *last_device_p = malloc(sizeof(jtag_device_t));
+       (*last_device_p)->ir_length = strtoul(args[0], NULL, 0);
+
+       (*last_device_p)->expected = malloc((*last_device_p)->ir_length);
+       buf_set_u32((*last_device_p)->expected, 0, (*last_device_p)->ir_length, strtoul(args[1], NULL, 0));
+       (*last_device_p)->expected_mask = malloc((*last_device_p)->ir_length);
+       buf_set_u32((*last_device_p)->expected_mask, 0, (*last_device_p)->ir_length, strtoul(args[2], NULL, 0));
+
+       (*last_device_p)->cur_instr = malloc((*last_device_p)->ir_length);
+       (*last_device_p)->bypass = 1;
+       buf_set_ones((*last_device_p)->cur_instr, (*last_device_p)->ir_length);
+       
+       (*last_device_p)->next = NULL;
+       
+       jtag_register_event_callback(jtag_reset_callback, (*last_device_p));
+       
+       jtag_num_devices++;
+
+       return ERROR_OK;
+}
+
+int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       jtag_device_t *device = jtag_devices;
+       int device_count = 0;
+       
+       while (device)
+       {
+               u32 expected, expected_mask, cur_instr;
+               expected = buf_get_u32(device->expected, 0, device->ir_length);
+               expected_mask = buf_get_u32(device->expected_mask, 0, device->ir_length);
+               cur_instr = buf_get_u32(device->cur_instr, 0, device->ir_length);
+               command_print(cmd_ctx, "%i: idcode: 0x%8.8x ir length %i, ir capture 0x%x, ir mask 0x%x, current instruction 0x%x", device_count, device->idcode, device->ir_length, expected, expected_mask, cur_instr);
+               device = device->next;
+               device_count++;
+       }
+
+       return ERROR_OK;
+}
+
+int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc >= 1)
+       {
+               if (strcmp(args[0], "none") == 0)
+                       jtag_reset_config = RESET_NONE;
+               else if (strcmp(args[0], "trst_only") == 0)
+                       jtag_reset_config = RESET_HAS_TRST;
+               else if (strcmp(args[0], "srst_only") == 0)
+                       jtag_reset_config = RESET_HAS_SRST;
+               else if (strcmp(args[0], "trst_and_srst") == 0)
+                       jtag_reset_config = RESET_TRST_AND_SRST;
+               else
+               {
+                       ERROR("invalid reset_config argument, defaulting to none");
+                       jtag_reset_config = RESET_NONE;
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+       }
+       
+       if (argc >= 2)
+       {
+               if (strcmp(args[1], "srst_pulls_trst") == 0)
+                       jtag_reset_config |= RESET_SRST_PULLS_TRST;
+               else if (strcmp(args[1], "trst_pulls_srst") == 0)
+                       jtag_reset_config |= RESET_TRST_PULLS_SRST;
+               else if (strcmp(args[1], "combined") == 0)
+                       jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
+               else if (strcmp(args[1], "separate") == 0)
+                       jtag_reset_config &= ~(RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST);
+               else
+               {
+                       ERROR("invalid reset_config argument, defaulting to none");
+                       jtag_reset_config = RESET_NONE;
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+       }
+       
+       if (argc >= 3)
+       {
+               if (strcmp(args[2], "trst_open_drain") == 0)
+                       jtag_reset_config |= RESET_TRST_OPEN_DRAIN;
+               else if (strcmp(args[2], "trst_push_pull") == 0)
+                       jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN;
+               else
+               {
+                       ERROR("invalid reset_config argument, defaulting to none");
+                       jtag_reset_config = RESET_NONE;
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+       }
+
+       if (argc >= 4)
+       {
+               if (strcmp(args[3], "srst_push_pull") == 0)
+                       jtag_reset_config |= RESET_SRST_PUSH_PULL;
+               else if (strcmp(args[3], "srst_open_drain") == 0)
+                       jtag_reset_config &= ~RESET_SRST_PUSH_PULL;
+               else
+               {
+                       ERROR("invalid reset_config argument, defaulting to none");
+                       jtag_reset_config = RESET_NONE;
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc < 1)
+       {
+               ERROR("jtag_nsrst_delay <ms> command takes one required argument");
+               exit(-1);
+       }
+       else
+       {
+               jtag_nsrst_delay = strtoul(args[0], NULL, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc < 1)
+       {
+               ERROR("jtag_ntrst_delay <ms> command takes one required argument");
+               exit(-1);
+       }
+       else
+       {
+               jtag_ntrst_delay = strtoul(args[0], NULL, 0);
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               command_print(cmd_ctx, "jtag_speed: %i", jtag_speed);
+
+       if (argc > 0)
+       {
+               /* this command can be called during CONFIG, 
+                * in which case jtag isn't initialized */
+               if (jtag)
+                       jtag->speed(strtoul(args[0], NULL, 0));
+               else
+                       jtag_speed = strtoul(args[0], NULL, 0);
+       }
+
+       return ERROR_OK;
+}
+
+int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       enum tap_state state;
+
+       if (argc < 1)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       else
+       {
+               for (state = 0; state < 16; state++)
+               {
+                       if (strcmp(args[0], tap_state_strings[state]) == 0)
+                       {
+                               jtag_add_end_state(state);
+                               jtag_execute_queue();
+                       }
+               }
+       }
+       command_print(cmd_ctx, "current endstate: %s", tap_state_strings[end_state]);
+       
+       return ERROR_OK;
+}
+
+int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int trst = -1;
+       int srst = -1;
+       int retval;
+       
+       if (argc < 2)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       }
+
+       if (args[0][0] == '1')
+               trst = 1;
+       else if (args[0][0] == '0')
+               trst = 0;
+       else
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if (args[1][0] == '1')
+               srst = 1;
+       else if (args[1][0] == '0')
+               srst = 0;
+       else
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if (!jtag && jtag_interface_init(cmd_ctx) != ERROR_OK)
+               return ERROR_JTAG_INIT_FAILED;
+
+       if ((retval = jtag_add_reset(trst, srst)) != ERROR_OK)
+       {
+               switch (retval)
+               {
+                       case ERROR_JTAG_RESET_WOULD_ASSERT_TRST:
+                               command_print(cmd_ctx, "requested reset would assert trst\nif this is acceptable, use jtag_reset 1 %c", args[1][0]);
+                               break;
+                       case ERROR_JTAG_RESET_CANT_SRST:
+                               command_print(cmd_ctx, "can't assert srst because the current reset_config doesn't support it");
+                               break;
+                       default:
+                               command_print(cmd_ctx, "unknown error");
+               }
+       }
+       jtag_execute_queue();
+
+       return ERROR_OK;
+}
+
+int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc < 1)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       jtag_add_runtest(strtol(args[0], NULL, 0), -1);
+       jtag_execute_queue();
+
+       return ERROR_OK;
+
+}
+
+int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       enum tap_state state;
+
+       state = -1;
+       if (argc == 1)
+       {
+               for (state = 0; state < 16; state++)
+               {
+                       if (strcmp(args[0], tap_state_strings[state]) == 0)
+                       {
+                               break;
+                       }
+               }
+       }
+
+       jtag_add_statemove(state);
+       jtag_execute_queue();
+
+       return ERROR_OK;
+
+}
+
+int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int i;
+       scan_field_t *fields;
+       
+       if ((argc < 2) || (argc % 2))
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       fields = malloc(sizeof(scan_field_t) * argc / 2);
+       
+       for (i = 0; i < argc / 2; i++)
+       {
+               int device = strtoul(args[i*2], NULL, 0);
+               int field_size = jtag_get_device(device)->ir_length;
+               fields[i].device = device;
+               fields[i].out_value = malloc(CEIL(field_size, 8));
+               buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0));
+               fields[i].out_mask = NULL;
+               fields[i].in_value = NULL;
+               fields[i].in_check_mask = NULL;
+               fields[i].in_handler = NULL;
+               fields[i].in_handler_priv = NULL;
+       }
+
+       jtag_add_ir_scan(argc / 2, fields, -1);
+       jtag_execute_queue();
+
+       for (i = 0; i < argc / 2; i++)
+               free(fields[i].out_value);
+
+       free (fields);
+
+       return ERROR_OK;
+}
+
+int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       scan_field_t *fields;
+       int num_fields = 0;
+       int field_count = 0;
+       var_t *var;
+       int i, j;
+       
+       if ((argc < 2) || (argc % 2))
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       for (i = 0; i < argc; i+=2)
+       {
+               var = get_var_by_namenum(args[i+1]);
+               if (var)
+               {
+                       num_fields += var->num_fields;
+               }
+               else
+               {
+                       command_print(cmd_ctx, "variable %s doesn't exist", args[i+1]);
+                       return ERROR_OK;
+               }
+       }
+
+       fields = malloc(sizeof(scan_field_t) * num_fields);
+
+       for (i = 0; i < argc; i+=2)
+       {
+               var = get_var_by_namenum(args[i+1]);
+       
+               for (j = 0; j < var->num_fields; j++)
+               {
+                       fields[field_count].device = strtol(args[i], NULL, 0);
+                       fields[field_count].num_bits = var->fields[j].num_bits;
+                       fields[field_count].out_value = malloc(CEIL(var->fields[j].num_bits, 8));
+                       buf_set_u32(fields[field_count].out_value, 0, var->fields[j].num_bits, var->fields[j].value);
+                       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 = field_le_to_host;
+                       fields[field_count++].in_handler_priv = &(var->fields[j]);
+               }
+       }
+
+       jtag_add_dr_scan(num_fields, fields, -1);
+       jtag_execute_queue();
+       
+       for (i = 0; i < argc / 2; i++)
+               free(fields[i].out_value);
+
+       free(fields);
+
+       return ERROR_OK;
+}
+
+int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "enable") == 0)
+               {
+                       jtag_verify_capture_ir = 1;
+               }
+               else if (strcmp(args[0], "disable") == 0)
+               {
+                       jtag_verify_capture_ir = 0;
+               } else
+               {
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+       } else if (argc != 0)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       
+       command_print(cmd_ctx, "verify Capture-IR is %s", (jtag_verify_capture_ir) ? "enabled": "disabled");
+       
+       return ERROR_OK;
+}
index 2ff785ab9a26784f752a6051b82c6e80fba0fed6..d0011f0ddfe51b5ec9bf22967b743620bc779374 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Benedikt Sauter sauter@ixbat.de                 *\r
- *   based on Dominic Rath's amt_jtagaccel.c                               *\r
- *                                                                         *\r
- *   usbprog is a free programming adapter. You can easily install         *\r
- *   different firmware versions from an "online pool" over USB.           *\r
- *   The adapter can be used for programming and debugging AVR and ARM     *\r
- *   processors, as USB to RS232 converter, as JTAG interface or as        *\r
- *   simple I/O interface (5 lines).                                       *\r
- *                                                                         *\r
- *   http://www.embedded-projects.net/usbprog                              *\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
-\r
-#include "jtag.h"\r
-#include <usb.h>\r
-\r
-/* system includes */\r
-\r
-#include "log.h"\r
-\r
-#define VID 0x1781\r
-#define PID 0x0c63\r
-\r
-/* Pins at usbprog */\r
-#define TDO_BIT         0\r
-#define TDI_BIT         3\r
-#define TCK_BIT         2\r
-#define TMS_BIT         1\r
-\r
-int usbprog_execute_queue(void);\r
-int usbprog_speed(int speed);\r
-int usbprog_register_commands(struct command_context_s *cmd_ctx);\r
-int usbprog_init(void);\r
-int usbprog_quit(void);\r
-\r
-void usbprog_end_state(enum tap_state state);\r
-void usbprog_state_move(void);\r
-void usbprog_path_move(pathmove_command_t *cmd);\r
-void usbprog_runtest(int num_cycles);\r
-void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size);\r
-\r
-jtag_interface_t usbprog_interface =\r
-{\r
-       .name = "usbprog",\r
-       .execute_queue = usbprog_execute_queue,\r
-       .speed = usbprog_speed,\r
-       .register_commands = usbprog_register_commands,\r
-       .init = usbprog_init,\r
-       .quit = usbprog_quit\r
-};\r
-\r
-#define UNKOWN_COMMAND  0x00\r
-#define PORT_DIRECTION  0x01\r
-#define PORT_SET        0x02\r
-#define PORT_GET        0x03\r
-#define PORT_SETBIT     0x04\r
-#define PORT_GETBIT     0x05\r
-#define WRITE_TDI      0x06\r
-#define READ_TDO       0x07\r
-#define WRITE_AND_READ         0x08\r
-#define WRITE_TMS      0x09\r
-#define WRITE_TMS_CHAIN 0x0A\r
-\r
-struct usbprog_jtag\r
-{\r
-       struct usb_dev_handle* usb_handle;\r
-};\r
-\r
-struct usbprog_jtag * usbprog_jtag_handle;\r
-\r
-struct usbprog_jtag* usbprog_jtag_open();\r
-void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);\r
-void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);\r
-unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);\r
-\r
-void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);\r
-void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);\r
-void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);\r
-void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);\r
-\r
-char tms_chain[64];\r
-int tms_chain_index;\r
-void usbprog_jtag_tms_collect(char tms_scan);\r
-void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);\r
-\r
-void usbprog_write(int tck, int tms, int tdi);\r
-void usbprog_reset(int trst, int srst);\r
-\r
-void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);\r
-void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value);\r
-unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag);\r
-void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value);\r
-int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit);\r
-\r
-int usbprog_speed(int speed)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_execute_queue(void)\r
-{\r
-       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */\r
-       int scan_size;\r
-       enum scan_type type;\r
-       u8 *buffer;\r
-\r
-       while (cmd)\r
-       {\r
-               switch (cmd->type)\r
-               {\r
-                       case JTAG_END_STATE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);\r
-#endif\r
-                               if (cmd->cmd.end_state->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.end_state->end_state);\r
-                               break;\r
-                       case JTAG_RESET:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-#endif\r
-                               if (cmd->cmd.reset->trst == 1)\r
-                               {\r
-                                       cur_state = TAP_TLR;\r
-                               }\r
-                               usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);\r
-                               break;\r
-                       case JTAG_RUNTEST:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);\r
-#endif\r
-                               if (cmd->cmd.runtest->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.runtest->end_state);\r
-                               usbprog_runtest(cmd->cmd.runtest->num_cycles);\r
-                               break;\r
-                       case JTAG_STATEMOVE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);\r
-#endif\r
-                               if (cmd->cmd.statemove->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.statemove->end_state);\r
-                               usbprog_state_move();\r
-                               break;\r
-                       case JTAG_PATHMOVE:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,\r
-                                       cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);\r
-#endif\r
-                               usbprog_path_move(cmd->cmd.pathmove);\r
-                               break;\r
-                       case JTAG_SCAN:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);\r
-#endif\r
-                               if (cmd->cmd.scan->end_state != -1)\r
-                                       usbprog_end_state(cmd->cmd.scan->end_state);\r
-                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);\r
-                               type = jtag_scan_type(cmd->cmd.scan);\r
-                               usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);\r
-                               if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)\r
-                                       return ERROR_JTAG_QUEUE_FAILED;\r
-                               if (buffer)\r
-                                       free(buffer);\r
-                               break;\r
-                       case JTAG_SLEEP:\r
-#ifdef _DEBUG_JTAG_IO_\r
-                               DEBUG("sleep %i", cmd->cmd.sleep->us);\r
-#endif\r
-                               jtag_sleep(cmd->cmd.sleep->us);\r
-                                       break;\r
-                       default:\r
-                               ERROR("BUG: unknown JTAG command type encountered");\r
-                               exit(-1);\r
-               }\r
-\r
-               cmd = cmd->next;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_init(void)\r
-{\r
-       usbprog_jtag_handle = usbprog_jtag_open();\r
-\r
-       tms_chain_index = 0;\r
-       if (usbprog_jtag_handle == 0)\r
-       {\r
-               ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");\r
-               return ERROR_JTAG_INIT_FAILED;\r
-       }\r
-\r
-       INFO("USB JTAG Interface ready!");\r
-\r
-       usbprog_jtag_init(usbprog_jtag_handle);\r
-       usbprog_reset(0, 0);\r
-       usbprog_write(0, 0, 0);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int usbprog_quit(void)\r
-{\r
-       return ERROR_OK;\r
-}\r
-\r
-/*************** jtag execute commands **********************/\r
-void usbprog_end_state(enum tap_state state)\r
-{\r
-       if (tap_move_map[state] != -1)\r
-               end_state = state;\r
-       else\r
-       {\r
-               ERROR("BUG: %i is not a valid end state", state);\r
-               exit(-1);\r
-       }\r
-}\r
-\r
-void usbprog_state_move(void)\r
-{\r
-       int i = 0, tms = 0;\r
-       u8 tms_scan = TAP_MOVE(cur_state, end_state);\r
-\r
-       usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);\r
-       for (i = 0; i < 7; i++)\r
-       {\r
-               tms = (tms_scan >> i) & 1;\r
-       }\r
-\r
-       cur_state = end_state;\r
-}\r
-\r
-void usbprog_path_move(pathmove_command_t *cmd)\r
-{\r
-       int num_states = cmd->num_states;\r
-       int state_count;\r
-\r
-       state_count = 0;\r
-       while (num_states)\r
-       {\r
-               if (tap_transitions[cur_state].low == cmd->path[state_count])\r
-               {\r
-                       //INFO("1");\r
-                       usbprog_write(0, 0, 0);\r
-                       usbprog_write(1, 0, 0);\r
-               }\r
-               else if (tap_transitions[cur_state].high == cmd->path[state_count])\r
-               {\r
-                       //INFO("2");\r
-                       usbprog_write(0, 1, 0);\r
-                       usbprog_write(1, 1, 0);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);\r
-                       exit(-1);\r
-               }\r
-\r
-               cur_state = cmd->path[state_count];\r
-               state_count++;\r
-               num_states--;\r
-       }\r
-\r
-       end_state = cur_state;\r
-}\r
-\r
-void usbprog_runtest(int num_cycles)\r
-{\r
-       int i;\r
-\r
-       /* only do a state_move when we're not already in RTI */\r
-       if (cur_state != TAP_RTI)\r
-       {\r
-               usbprog_end_state(TAP_RTI);\r
-               usbprog_state_move();\r
-       }\r
-\r
-       /* execute num_cycles */\r
-       if (num_cycles > 0)\r
-       {\r
-               usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-               usbprog_write(0, 0, 0);\r
-       }\r
-       else\r
-       {\r
-               usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-               //INFO("NUM CYCLES %i",num_cycles);\r
-       }\r
-\r
-       for (i = 0; i < num_cycles; i++)\r
-       {\r
-               usbprog_write(1, 0, 0);\r
-               usbprog_write(0, 0, 0);\r
-       }\r
-\r
-       /* finish in end_state */\r
-       /*\r
-       usbprog_end_state(saved_end_state);\r
-       if (cur_state != end_state)\r
-               usbprog_state_move();\r
-       */\r
-}\r
-\r
-void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)\r
-{\r
-       enum tap_state saved_end_state = end_state;\r
-\r
-       if (ir_scan)\r
-               usbprog_end_state(TAP_SI);\r
-       else\r
-               usbprog_end_state(TAP_SD);\r
-\r
-       //usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-\r
-       usbprog_state_move();\r
-       usbprog_end_state(saved_end_state);\r
-\r
-       usbprog_jtag_tms_send(usbprog_jtag_handle);\r
-\r
-       if (type == SCAN_OUT)\r
-       {\r
-               usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size);\r
-       }\r
-       if (type == SCAN_IN)\r
-       {\r
-               usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size);\r
-       }\r
-       if (type == SCAN_IO)\r
-       {\r
-               usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size);\r
-       }\r
-\r
-       if (ir_scan)\r
-               cur_state = TAP_PI;\r
-       else\r
-               cur_state = TAP_PD;\r
-\r
-       if (cur_state != end_state)\r
-               usbprog_state_move();\r
-}\r
-\r
-/*************** jtag wrapper functions *********************/\r
-\r
-void usbprog_write(int tck, int tms, int tdi)\r
-{\r
-       unsigned char output_value=0x00;\r
-\r
-       if (tms)\r
-               output_value |= (1<<TMS_BIT);\r
-       if (tdi)\r
-               output_value |= (1<<TDI_BIT);\r
-       if (tck)\r
-               output_value |= (1<<TCK_BIT);\r
-\r
-       usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);\r
-}\r
-\r
-/* (1) assert or (0) deassert reset lines */\r
-void usbprog_reset(int trst, int srst)\r
-{\r
-       DEBUG("trst: %i, srst: %i", trst, srst);\r
-\r
-       if (trst)\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);\r
-       else\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);\r
-\r
-       if (srst)\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);\r
-       else\r
-               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);\r
-}\r
-\r
-/*************** jtag lowlevel functions ********************/\r
-\r
-struct usb_bus *busses;\r
-\r
-struct usbprog_jtag* usbprog_jtag_open()\r
-{\r
-       struct usb_bus *bus;\r
-       struct usb_device *dev;\r
-\r
-       struct usbprog_jtag *tmp;\r
-\r
-       tmp = (struct usbprog_jtag*)malloc(sizeof(struct usbprog_jtag));\r
-\r
-       usb_set_debug(10);\r
-       usb_init();\r
-       usb_find_busses();\r
-       usb_find_devices();\r
-\r
-       busses = usb_get_busses();\r
-\r
-       /* find usbprog_jtag device in usb bus */\r
-\r
-       for (bus = busses; bus; bus = bus->next)\r
-       {\r
-               for (dev = bus->devices; dev; dev = dev->next)\r
-               {\r
-                       /* condition for sucessfully hit (too bad, I only check the vendor id)*/\r
-                       if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)\r
-                       {\r
-                               tmp->usb_handle = usb_open(dev);\r
-                               usb_set_configuration(tmp->usb_handle, 1);\r
-                               usb_claim_interface(tmp->usb_handle, 0);\r
-                               usb_set_altinterface(tmp->usb_handle, 0);\r
-                               return tmp;\r
-                       }\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       usb_close(usbprog_jtag->usb_handle);\r
-       free(usbprog_jtag);\r
-}\r
-\r
-unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)\r
-{\r
-       int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);\r
-       if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \\r
-                       (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))\r
-               return 1;\r
-       if (res == msglen)\r
-       {\r
-               //INFO("HALLLLOOO %i",(int)msg[0]);\r
-               res =  usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);\r
-               if (res > 0)\r
-                       return (unsigned char)msg[1];\r
-               else\r
-                       return -1;\r
-       }\r
-       else\r
-               return -1;\r
-       return 0;\r
-}\r
-\r
-void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       usbprog_jtag_set_direction(usbprog_jtag, 0xFE);\r
-}\r
-\r
-void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)\r
-{\r
-       char tmp[64];   /* fastes packet size for usb controller */\r
-       int send_bits, bufindex = 0, fillindex = 0, i, loops;\r
-\r
-       char swap;\r
-       /* 61 byte can be transfered (488 bit) */\r
-\r
-       while (size > 0)\r
-       {\r
-               if (size > 488)\r
-               {\r
-                       send_bits = 488;\r
-                       size = size - 488;\r
-                       loops = 61;\r
-               }\r
-               else\r
-               {\r
-                       send_bits = size;\r
-                       loops = size / 8;\r
-                       loops++;\r
-                       size = 0;\r
-               }\r
-               tmp[0] = WRITE_AND_READ;\r
-               tmp[1] = (char)(send_bits >> 8);        /* high */\r
-               tmp[2] = (char)(send_bits);                     /* low */\r
-               i = 0;\r
-\r
-               for (i = 0; i < loops; i++)\r
-               {\r
-                       tmp[3 + i] = buffer[bufindex];\r
-                       bufindex++;\r
-               }\r
-\r
-               if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)\r
-               {\r
-                       //INFO("HALLLLOOO2 %i",(int)tmp[0]);\r
-                       usleep(1);\r
-                       int timeout = 0;\r
-                       while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)\r
-                       {\r
-                               timeout++;\r
-                               if (timeout > 10)\r
-                                       break;\r
-                       }\r
-\r
-                       for (i = 0; i < loops; i++)\r
-                       {\r
-                               swap =  tmp[3 + i];\r
-                               buffer[fillindex++] = swap;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)\r
-{\r
-       char tmp[64];   /* fastes packet size for usb controller */\r
-       int send_bits, fillindex = 0, i, loops;\r
-\r
-       char swap;\r
-       /* 61 byte can be transfered (488 bit) */\r
-\r
-       while (size > 0)\r
-       {\r
-               if (size > 488)\r
-               {\r
-                       send_bits = 488;\r
-                       size = size - 488;\r
-                       loops = 61;\r
-               }\r
-               else\r
-               {\r
-                       send_bits = size;\r
-                       loops = size / 8;\r
-                       loops++;\r
-                       size = 0;\r
-               }\r
-               tmp[0] = WRITE_AND_READ;\r
-               tmp[1] = (char)(send_bits >> 8);        /* high */\r
-               tmp[2] = (char)(send_bits);                     /* low */\r
-\r
-               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);\r
-\r
-               //INFO("HALLLLOOO3 %i",(int)tmp[0]);\r
-               int timeout = 0;\r
-               usleep(1);\r
-               while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)\r
-               {\r
-                       timeout++;\r
-                       if (timeout > 10)\r
-                               break;\r
-               }\r
-\r
-               for (i = 0; i < loops; i++)\r
-               {\r
-                       swap = tmp[3 + i];\r
-                       buffer[fillindex++] = swap;\r
-               }\r
-       }\r
-}\r
-\r
-void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)\r
-{\r
-       char tmp[64];   /* fastes packet size for usb controller */\r
-       int send_bits, bufindex = 0, i, loops;\r
-\r
-       /* 61 byte can be transfered (488 bit) */\r
-       while (size > 0)\r
-       {\r
-               if (size > 488)\r
-               {\r
-                       send_bits = 488;\r
-                       size = size - 488;\r
-                       loops = 61;\r
-               }\r
-               else\r
-               {\r
-                       send_bits = size;\r
-                       loops = size/8;\r
-                       //if(loops==0)\r
-                       loops++;\r
-                       size = 0;\r
-               }\r
-               tmp[0] = WRITE_TDI;\r
-               tmp[1] = (char)(send_bits >> 8);        /* high */\r
-               tmp[2] = (char)(send_bits);                     /* low */\r
-               i = 0;\r
-\r
-               for (i = 0; i < loops; i++)\r
-               {\r
-                       tmp[3 + i] = buffer[bufindex];\r
-                       bufindex++;\r
-               }\r
-               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);\r
-       }\r
-}\r
-\r
-void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)\r
-{\r
-       usbprog_jtag_tms_collect(tms_scan);\r
-}\r
-\r
-void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_DIRECTION;\r
-       tmp[1] = (char)direction;\r
-       usbprog_jtag_message(usbprog_jtag, tmp, 2);\r
-}\r
-\r
-void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_SET;\r
-       tmp[1] = (char)value;\r
-       usbprog_jtag_message(usbprog_jtag, tmp, 2);\r
-}\r
-\r
-unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_GET;\r
-       tmp[1] = 0x00;\r
-       return usbprog_jtag_message(usbprog_jtag, tmp, 2);\r
-}\r
-\r
-void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)\r
-{\r
-       char tmp[3];\r
-       tmp[0] = PORT_SETBIT;\r
-       tmp[1] = (char)bit;\r
-       if (value == 1)\r
-               tmp[2] = 0x01;\r
-       else\r
-               tmp[2] = 0x00;\r
-       usbprog_jtag_message(usbprog_jtag, tmp, 3);\r
-}\r
-\r
-int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)\r
-{\r
-       char tmp[2];\r
-       tmp[0] = PORT_GETBIT;\r
-       tmp[1] = (char)bit;\r
-\r
-       if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)\r
-               return 1;\r
-       else\r
-               return 0;\r
-}\r
-\r
-void usbprog_jtag_tms_collect(char tms_scan)\r
-{\r
-       tms_chain[tms_chain_index] = tms_scan;\r
-       tms_chain_index++;\r
-}\r
-\r
-void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)\r
-{\r
-       int i;\r
-       //INFO("TMS SEND");\r
-       if (tms_chain_index > 0)\r
-       {\r
-               char tmp[tms_chain_index + 2];\r
-               tmp[0] = WRITE_TMS_CHAIN;\r
-               tmp[1] = (char)(tms_chain_index);\r
-               for (i = 0; i < tms_chain_index + 1; i++)\r
-                       tmp[2 + i] = tms_chain[i];\r
-               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);\r
-               tms_chain_index = 0;\r
-       }\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Benedikt Sauter sauter@ixbat.de                 *
+ *   based on Dominic Rath's amt_jtagaccel.c                               *
+ *                                                                         *
+ *   usbprog is a free programming adapter. You can easily install         *
+ *   different firmware versions from an "online pool" over USB.           *
+ *   The adapter can be used for programming and debugging AVR and ARM     *
+ *   processors, as USB to RS232 converter, as JTAG interface or as        *
+ *   simple I/O interface (5 lines).                                       *
+ *                                                                         *
+ *   http://www.embedded-projects.net/usbprog                              *
+ *                                                                         *
+ *   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 "jtag.h"
+#include <usb.h>
+
+/* system includes */
+
+#include "log.h"
+
+#define VID 0x1781
+#define PID 0x0c63
+
+/* Pins at usbprog */
+#define TDO_BIT         0
+#define TDI_BIT         3
+#define TCK_BIT         2
+#define TMS_BIT         1
+
+int usbprog_execute_queue(void);
+int usbprog_speed(int speed);
+int usbprog_register_commands(struct command_context_s *cmd_ctx);
+int usbprog_init(void);
+int usbprog_quit(void);
+
+void usbprog_end_state(enum tap_state state);
+void usbprog_state_move(void);
+void usbprog_path_move(pathmove_command_t *cmd);
+void usbprog_runtest(int num_cycles);
+void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size);
+
+jtag_interface_t usbprog_interface =
+{
+       .name = "usbprog",
+       .execute_queue = usbprog_execute_queue,
+       .speed = usbprog_speed,
+       .register_commands = usbprog_register_commands,
+       .init = usbprog_init,
+       .quit = usbprog_quit
+};
+
+#define UNKOWN_COMMAND  0x00
+#define PORT_DIRECTION  0x01
+#define PORT_SET        0x02
+#define PORT_GET        0x03
+#define PORT_SETBIT     0x04
+#define PORT_GETBIT     0x05
+#define WRITE_TDI      0x06
+#define READ_TDO       0x07
+#define WRITE_AND_READ         0x08
+#define WRITE_TMS      0x09
+#define WRITE_TMS_CHAIN 0x0A
+
+struct usbprog_jtag
+{
+       struct usb_dev_handle* usb_handle;
+};
+
+struct usbprog_jtag * usbprog_jtag_handle;
+
+struct usbprog_jtag* usbprog_jtag_open();
+void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);
+void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);
+unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);
+
+void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
+void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
+void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
+void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);
+
+char tms_chain[64];
+int tms_chain_index;
+void usbprog_jtag_tms_collect(char tms_scan);
+void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);
+
+void usbprog_write(int tck, int tms, int tdi);
+void usbprog_reset(int trst, int srst);
+
+void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);
+void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value);
+unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag);
+void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value);
+int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit);
+
+int usbprog_speed(int speed)
+{
+       return ERROR_OK;
+}
+
+int usbprog_register_commands(struct command_context_s *cmd_ctx)
+{
+       return ERROR_OK;
+}
+
+int usbprog_execute_queue(void)
+{
+       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
+       int scan_size;
+       enum scan_type type;
+       u8 *buffer;
+
+       while (cmd)
+       {
+               switch (cmd->type)
+               {
+                       case JTAG_END_STATE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
+#endif
+                               if (cmd->cmd.end_state->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.end_state->end_state);
+                               break;
+                       case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+                               if (cmd->cmd.reset->trst == 1)
+                               {
+                                       cur_state = TAP_TLR;
+                               }
+                               usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               break;
+                       case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+#endif
+                               if (cmd->cmd.runtest->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.runtest->end_state);
+                               usbprog_runtest(cmd->cmd.runtest->num_cycles);
+                               break;
+                       case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
+#endif
+                               if (cmd->cmd.statemove->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.statemove->end_state);
+                               usbprog_state_move();
+                               break;
+                       case JTAG_PATHMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
+                                       cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
+#endif
+                               usbprog_path_move(cmd->cmd.pathmove);
+                               break;
+                       case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);
+#endif
+                               if (cmd->cmd.scan->end_state != -1)
+                                       usbprog_end_state(cmd->cmd.scan->end_state);
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+                               type = jtag_scan_type(cmd->cmd.scan);
+                               usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+                               if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+                                       return ERROR_JTAG_QUEUE_FAILED;
+                               if (buffer)
+                                       free(buffer);
+                               break;
+                       case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("sleep %i", cmd->cmd.sleep->us);
+#endif
+                               jtag_sleep(cmd->cmd.sleep->us);
+                                       break;
+                       default:
+                               ERROR("BUG: unknown JTAG command type encountered");
+                               exit(-1);
+               }
+
+               cmd = cmd->next;
+       }
+
+       return ERROR_OK;
+}
+
+int usbprog_init(void)
+{
+       usbprog_jtag_handle = usbprog_jtag_open();
+
+       tms_chain_index = 0;
+       if (usbprog_jtag_handle == 0)
+       {
+               ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       INFO("USB JTAG Interface ready!");
+
+       usbprog_jtag_init(usbprog_jtag_handle);
+       usbprog_reset(0, 0);
+       usbprog_write(0, 0, 0);
+
+       return ERROR_OK;
+}
+
+int usbprog_quit(void)
+{
+       return ERROR_OK;
+}
+
+/*************** jtag execute commands **********************/
+void usbprog_end_state(enum tap_state state)
+{
+       if (tap_move_map[state] != -1)
+               end_state = state;
+       else
+       {
+               ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+}
+
+void usbprog_state_move(void)
+{
+       int i = 0, tms = 0;
+       u8 tms_scan = TAP_MOVE(cur_state, end_state);
+
+       usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);
+       for (i = 0; i < 7; i++)
+       {
+               tms = (tms_scan >> i) & 1;
+       }
+
+       cur_state = end_state;
+}
+
+void usbprog_path_move(pathmove_command_t *cmd)
+{
+       int num_states = cmd->num_states;
+       int state_count;
+
+       state_count = 0;
+       while (num_states)
+       {
+               if (tap_transitions[cur_state].low == cmd->path[state_count])
+               {
+                       //INFO("1");
+                       usbprog_write(0, 0, 0);
+                       usbprog_write(1, 0, 0);
+               }
+               else if (tap_transitions[cur_state].high == cmd->path[state_count])
+               {
+                       //INFO("2");
+                       usbprog_write(0, 1, 0);
+                       usbprog_write(1, 1, 0);
+               }
+               else
+               {
+                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
+                       exit(-1);
+               }
+
+               cur_state = cmd->path[state_count];
+               state_count++;
+               num_states--;
+       }
+
+       end_state = cur_state;
+}
+
+void usbprog_runtest(int num_cycles)
+{
+       int i;
+
+       /* only do a state_move when we're not already in RTI */
+       if (cur_state != TAP_RTI)
+       {
+               usbprog_end_state(TAP_RTI);
+               usbprog_state_move();
+       }
+
+       /* execute num_cycles */
+       if (num_cycles > 0)
+       {
+               usbprog_jtag_tms_send(usbprog_jtag_handle);
+               usbprog_write(0, 0, 0);
+       }
+       else
+       {
+               usbprog_jtag_tms_send(usbprog_jtag_handle);
+               //INFO("NUM CYCLES %i",num_cycles);
+       }
+
+       for (i = 0; i < num_cycles; i++)
+       {
+               usbprog_write(1, 0, 0);
+               usbprog_write(0, 0, 0);
+       }
+
+       /* finish in end_state */
+       /*
+       usbprog_end_state(saved_end_state);
+       if (cur_state != end_state)
+               usbprog_state_move();
+       */
+}
+
+void usbprog_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
+{
+       enum tap_state saved_end_state = end_state;
+
+       if (ir_scan)
+               usbprog_end_state(TAP_SI);
+       else
+               usbprog_end_state(TAP_SD);
+
+       //usbprog_jtag_tms_send(usbprog_jtag_handle);
+
+       usbprog_state_move();
+       usbprog_end_state(saved_end_state);
+
+       usbprog_jtag_tms_send(usbprog_jtag_handle);
+
+       if (type == SCAN_OUT)
+       {
+               usbprog_jtag_write_tdi(usbprog_jtag_handle,buffer, scan_size);
+       }
+       if (type == SCAN_IN)
+       {
+               usbprog_jtag_read_tdo(usbprog_jtag_handle,buffer, scan_size);
+       }
+       if (type == SCAN_IO)
+       {
+               usbprog_jtag_write_and_read(usbprog_jtag_handle,buffer, scan_size);
+       }
+
+       if (ir_scan)
+               cur_state = TAP_PI;
+       else
+               cur_state = TAP_PD;
+
+       if (cur_state != end_state)
+               usbprog_state_move();
+}
+
+/*************** jtag wrapper functions *********************/
+
+void usbprog_write(int tck, int tms, int tdi)
+{
+       unsigned char output_value=0x00;
+
+       if (tms)
+               output_value |= (1<<TMS_BIT);
+       if (tdi)
+               output_value |= (1<<TDI_BIT);
+       if (tck)
+               output_value |= (1<<TCK_BIT);
+
+       usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);
+}
+
+/* (1) assert or (0) deassert reset lines */
+void usbprog_reset(int trst, int srst)
+{
+       DEBUG("trst: %i, srst: %i", trst, srst);
+
+       if (trst)
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);
+       else
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);
+
+       if (srst)
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);
+       else
+               usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);
+}
+
+/*************** jtag lowlevel functions ********************/
+
+struct usb_bus *busses;
+
+struct usbprog_jtag* usbprog_jtag_open()
+{
+       struct usb_bus *bus;
+       struct usb_device *dev;
+
+       struct usbprog_jtag *tmp;
+
+       tmp = (struct usbprog_jtag*)malloc(sizeof(struct usbprog_jtag));
+
+       usb_set_debug(10);
+       usb_init();
+       usb_find_busses();
+       usb_find_devices();
+
+       busses = usb_get_busses();
+
+       /* find usbprog_jtag device in usb bus */
+
+       for (bus = busses; bus; bus = bus->next)
+       {
+               for (dev = bus->devices; dev; dev = dev->next)
+               {
+                       /* condition for sucessfully hit (too bad, I only check the vendor id)*/
+                       if (dev->descriptor.idVendor == VID && dev->descriptor.idProduct == PID)
+                       {
+                               tmp->usb_handle = usb_open(dev);
+                               usb_set_configuration(tmp->usb_handle, 1);
+                               usb_claim_interface(tmp->usb_handle, 0);
+                               usb_set_altinterface(tmp->usb_handle, 0);
+                               return tmp;
+                       }
+               }
+       }
+       return 0;
+}
+
+void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
+{
+       usb_close(usbprog_jtag->usb_handle);
+       free(usbprog_jtag);
+}
+
+unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
+{
+       int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);
+       if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
+                       (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
+               return 1;
+       if (res == msglen)
+       {
+               //INFO("HALLLLOOO %i",(int)msg[0]);
+               res =  usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
+               if (res > 0)
+                       return (unsigned char)msg[1];
+               else
+                       return -1;
+       }
+       else
+               return -1;
+       return 0;
+}
+
+void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)
+{
+       usbprog_jtag_set_direction(usbprog_jtag, 0xFE);
+}
+
+void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
+{
+       char tmp[64];   /* fastes packet size for usb controller */
+       int send_bits, bufindex = 0, fillindex = 0, i, loops;
+
+       char swap;
+       /* 61 byte can be transfered (488 bit) */
+
+       while (size > 0)
+       {
+               if (size > 488)
+               {
+                       send_bits = 488;
+                       size = size - 488;
+                       loops = 61;
+               }
+               else
+               {
+                       send_bits = size;
+                       loops = size / 8;
+                       loops++;
+                       size = 0;
+               }
+               tmp[0] = WRITE_AND_READ;
+               tmp[1] = (char)(send_bits >> 8);        /* high */
+               tmp[2] = (char)(send_bits);                     /* low */
+               i = 0;
+
+               for (i = 0; i < loops; i++)
+               {
+                       tmp[3 + i] = buffer[bufindex];
+                       bufindex++;
+               }
+
+               if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)
+               {
+                       //INFO("HALLLLOOO2 %i",(int)tmp[0]);
+                       usleep(1);
+                       int timeout = 0;
+                       while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)
+                       {
+                               timeout++;
+                               if (timeout > 10)
+                                       break;
+                       }
+
+                       for (i = 0; i < loops; i++)
+                       {
+                               swap =  tmp[3 + i];
+                               buffer[fillindex++] = swap;
+                       }
+               }
+       }
+}
+
+void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
+{
+       char tmp[64];   /* fastes packet size for usb controller */
+       int send_bits, fillindex = 0, i, loops;
+
+       char swap;
+       /* 61 byte can be transfered (488 bit) */
+
+       while (size > 0)
+       {
+               if (size > 488)
+               {
+                       send_bits = 488;
+                       size = size - 488;
+                       loops = 61;
+               }
+               else
+               {
+                       send_bits = size;
+                       loops = size / 8;
+                       loops++;
+                       size = 0;
+               }
+               tmp[0] = WRITE_AND_READ;
+               tmp[1] = (char)(send_bits >> 8);        /* high */
+               tmp[2] = (char)(send_bits);                     /* low */
+
+               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
+
+               //INFO("HALLLLOOO3 %i",(int)tmp[0]);
+               int timeout = 0;
+               usleep(1);
+               while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)
+               {
+                       timeout++;
+                       if (timeout > 10)
+                               break;
+               }
+
+               for (i = 0; i < loops; i++)
+               {
+                       swap = tmp[3 + i];
+                       buffer[fillindex++] = swap;
+               }
+       }
+}
+
+void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
+{
+       char tmp[64];   /* fastes packet size for usb controller */
+       int send_bits, bufindex = 0, i, loops;
+
+       /* 61 byte can be transfered (488 bit) */
+       while (size > 0)
+       {
+               if (size > 488)
+               {
+                       send_bits = 488;
+                       size = size - 488;
+                       loops = 61;
+               }
+               else
+               {
+                       send_bits = size;
+                       loops = size/8;
+                       //if(loops==0)
+                       loops++;
+                       size = 0;
+               }
+               tmp[0] = WRITE_TDI;
+               tmp[1] = (char)(send_bits >> 8);        /* high */
+               tmp[2] = (char)(send_bits);                     /* low */
+               i = 0;
+
+               for (i = 0; i < loops; i++)
+               {
+                       tmp[3 + i] = buffer[bufindex];
+                       bufindex++;
+               }
+               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
+       }
+}
+
+void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)
+{
+       usbprog_jtag_tms_collect(tms_scan);
+}
+
+void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)
+{
+       char tmp[2];
+       tmp[0] = PORT_DIRECTION;
+       tmp[1] = (char)direction;
+       usbprog_jtag_message(usbprog_jtag, tmp, 2);
+}
+
+void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)
+{
+       char tmp[2];
+       tmp[0] = PORT_SET;
+       tmp[1] = (char)value;
+       usbprog_jtag_message(usbprog_jtag, tmp, 2);
+}
+
+unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
+{
+       char tmp[2];
+       tmp[0] = PORT_GET;
+       tmp[1] = 0x00;
+       return usbprog_jtag_message(usbprog_jtag, tmp, 2);
+}
+
+void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)
+{
+       char tmp[3];
+       tmp[0] = PORT_SETBIT;
+       tmp[1] = (char)bit;
+       if (value == 1)
+               tmp[2] = 0x01;
+       else
+               tmp[2] = 0x00;
+       usbprog_jtag_message(usbprog_jtag, tmp, 3);
+}
+
+int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
+{
+       char tmp[2];
+       tmp[0] = PORT_GETBIT;
+       tmp[1] = (char)bit;
+
+       if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)
+               return 1;
+       else
+               return 0;
+}
+
+void usbprog_jtag_tms_collect(char tms_scan)
+{
+       tms_chain[tms_chain_index] = tms_scan;
+       tms_chain_index++;
+}
+
+void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
+{
+       int i;
+       //INFO("TMS SEND");
+       if (tms_chain_index > 0)
+       {
+               char tmp[tms_chain_index + 2];
+               tmp[0] = WRITE_TMS_CHAIN;
+               tmp[1] = (char)(tms_chain_index);
+               for (i = 0; i < tms_chain_index + 1; i++)
+                       tmp[2 + i] = tms_chain[i];
+               usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
+               tms_chain_index = 0;
+       }
+}
index c2f877648f2acdf2ebf880ab62d54000a15c2bcd..d362c6490ab4c2e8d46cd6768d83f005834df0c3 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-#define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV\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 "interpreter.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 <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
-/* Give TELNET a way to find out what version this is */\r
-int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       command_print(cmd_ctx, OPENOCD_VERSION);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void exit_handler(void)\r
-{\r
-       /* close JTAG interface */\r
-       if (jtag && jtag->quit)\r
-               jtag->quit();\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-       /* initialize commandline interface */\r
-       command_context_t *cmd_ctx, *cfg_cmd_ctx;\r
-       cmd_ctx = command_init();\r
-\r
-       register_command(cmd_ctx, NULL, "version", handle_version_command,\r
-                                        COMMAND_EXEC, "show OpenOCD version");\r
-\r
-       /* register subsystem commands */\r
-       server_register_commands(cmd_ctx);\r
-       telnet_register_commands(cmd_ctx);\r
-       gdb_register_commands(cmd_ctx);\r
-       log_register_commands(cmd_ctx);\r
-       jtag_register_commands(cmd_ctx);\r
-       interpreter_register_commands(cmd_ctx);\r
-       xsvf_register_commands(cmd_ctx);\r
-       target_register_commands(cmd_ctx);\r
-       flash_register_commands(cmd_ctx);\r
-       nand_register_commands(cmd_ctx);\r
-       pld_register_commands(cmd_ctx);\r
-       \r
-       if (log_init(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("log init complete");\r
-       \r
-       printf( OPENOCD_VERSION );\r
-       printf( "\n$URL$\n");\r
-  \r
-       DEBUG( OPENOCD_VERSION );\r
-       DEBUG( "$URL$");\r
-\r
-       cfg_cmd_ctx = copy_command_context(cmd_ctx);\r
-       cfg_cmd_ctx->mode = COMMAND_CONFIG;\r
-       command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);\r
-       \r
-       if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-\r
-       if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       \r
-       command_done(cfg_cmd_ctx);\r
-\r
-       command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);\r
-\r
-       atexit(exit_handler);\r
-\r
-       if (jtag_init(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("jtag init complete");\r
-\r
-       if (target_init(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("target init complete");\r
-\r
-       if (flash_init_drivers(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("flash init complete");\r
-\r
-       if (nand_init(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("NAND init complete");\r
-\r
-       if (pld_init(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("pld init complete");\r
-\r
-       /* initialize tcp server */\r
-       server_init();\r
-\r
-       /* initialize telnet subsystem */\r
-       telnet_init("Open On-Chip Debugger");\r
-       gdb_init();\r
-\r
-       /* call any target resets */\r
-       if (target_init_reset(cmd_ctx) != ERROR_OK)\r
-               return EXIT_FAILURE;\r
-       DEBUG("target init reset complete");\r
-\r
-       /* handle network connections */\r
-       server_loop(cmd_ctx);\r
-\r
-       /* shut server down */\r
-       server_quit();\r
-\r
-       /* free commandline interface */\r
-       command_done(cmd_ctx);\r
-\r
-       return EXIT_SUCCESS;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+#define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "log.h"
+#include "types.h"
+#include "jtag.h"
+#include "configuration.h"
+#include "interpreter.h"
+#include "xsvf.h"
+#include "target.h"
+#include "flash.h"
+#include "nand.h"
+#include "pld.h"
+
+#include "command.h"
+#include "server.h"
+#include "telnet_server.h"
+#include "gdb_server.h"
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Give TELNET a way to find out what version this is */
+int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       command_print(cmd_ctx, OPENOCD_VERSION);
+
+       return ERROR_OK;
+}
+
+void exit_handler(void)
+{
+       /* close JTAG interface */
+       if (jtag && jtag->quit)
+               jtag->quit();
+}
+
+int main(int argc, char *argv[])
+{
+       /* initialize commandline interface */
+       command_context_t *cmd_ctx, *cfg_cmd_ctx;
+       cmd_ctx = command_init();
+
+       register_command(cmd_ctx, NULL, "version", handle_version_command,
+                                        COMMAND_EXEC, "show OpenOCD version");
+
+       /* register subsystem commands */
+       server_register_commands(cmd_ctx);
+       telnet_register_commands(cmd_ctx);
+       gdb_register_commands(cmd_ctx);
+       log_register_commands(cmd_ctx);
+       jtag_register_commands(cmd_ctx);
+       interpreter_register_commands(cmd_ctx);
+       xsvf_register_commands(cmd_ctx);
+       target_register_commands(cmd_ctx);
+       flash_register_commands(cmd_ctx);
+       nand_register_commands(cmd_ctx);
+       pld_register_commands(cmd_ctx);
+       
+       if (log_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("log init complete");
+       
+       printf( OPENOCD_VERSION );
+       printf( "\n$URL$\n");
+  
+       DEBUG( OPENOCD_VERSION );
+       DEBUG( "$URL$");
+
+       cfg_cmd_ctx = copy_command_context(cmd_ctx);
+       cfg_cmd_ctx->mode = COMMAND_CONFIG;
+       command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL);
+       
+       if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
+               return EXIT_FAILURE;
+
+       if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       
+       command_done(cfg_cmd_ctx);
+
+       command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
+
+       atexit(exit_handler);
+
+       if (jtag_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("jtag init complete");
+
+       if (target_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("target init complete");
+
+       if (flash_init_drivers(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("flash init complete");
+
+       if (nand_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("NAND init complete");
+
+       if (pld_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("pld init complete");
+
+       /* initialize tcp server */
+       server_init();
+
+       /* initialize telnet subsystem */
+       telnet_init("Open On-Chip Debugger");
+       gdb_init();
+
+       /* call any target resets */
+       if (target_init_reset(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("target init reset complete");
+
+       /* handle network connections */
+       server_loop(cmd_ctx);
+
+       /* shut server down */
+       server_quit();
+
+       /* free commandline interface */
+       command_done(cmd_ctx);
+
+       return EXIT_SUCCESS;
+}
index e0cd1a11aeb7081d5e523f17a190d05554fe0fa7..53acc5981aa86c2efbe6426d8c7cfb72bba1b594 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2006 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "virtex2.h"\r
-\r
-#include "pld.h"\r
-#include "xilinx_bit.h"\r
-#include "command.h"\r
-#include "log.h"\r
-#include "jtag.h"\r
-\r
-#include <stdlib.h>\r
-\r
-int virtex2_register_commands(struct command_context_s *cmd_ctx);\r
-int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);\r
-int virtex2_load(struct pld_device_s *pld_device, char *filename);\r
-\r
-pld_driver_t virtex2_pld =\r
-{\r
-       .name = "virtex2",\r
-       .register_commands = virtex2_register_commands,\r
-       .pld_device_command = virtex2_pld_device_command,\r
-       .load = virtex2_load,\r
-};\r
-\r
-int virtex2_set_instr(int chain_pos, u32 new_instr)\r
-{\r
-       jtag_device_t *device = jtag_get_device(chain_pos);\r
-       \r
-       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
-       {\r
-               scan_field_t field;\r
-       \r
-               field.device = chain_pos;\r
-               field.num_bits = device->ir_length;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-               \r
-               jtag_add_ir_scan(1, &field, TAP_RTI);\r
-               \r
-               free(field.out_value);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)\r
-{\r
-       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;\r
-       scan_field_t scan_field;\r
-       u8 *values;\r
-       int i;\r
-       \r
-       values = malloc(num_words * 4);\r
-\r
-       scan_field.device = virtex2_info->chain_pos;\r
-       scan_field.num_bits = num_words * 32;\r
-       scan_field.out_value = values;\r
-       scan_field.out_mask = NULL;\r
-       scan_field.in_value = NULL;\r
-       scan_field.in_check_value = NULL;\r
-       scan_field.in_check_mask = NULL;\r
-       scan_field.in_handler = NULL;\r
-       scan_field.in_handler_priv = NULL;\r
-       \r
-       for (i = 0; i < num_words; i++)\r
-               buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));\r
-       \r
-       virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */\r
-       \r
-       jtag_add_dr_scan(1, &scan_field, TAP_PD);\r
-       \r
-       free(values);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       u32 *dest = priv;\r
-       *dest = flip_u32(le_to_h_u32(in_buf), 32);\r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)\r
-{\r
-       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;\r
-       scan_field_t scan_field;\r
-       \r
-       scan_field.device = virtex2_info->chain_pos;\r
-       scan_field.num_bits = 32;\r
-       scan_field.out_value = NULL;\r
-       scan_field.out_mask = NULL;\r
-       scan_field.in_value = NULL;\r
-       scan_field.in_check_value = NULL;\r
-       scan_field.in_check_mask = NULL;\r
-       scan_field.in_handler = virtex2_jtag_buf_to_u32;\r
-       \r
-       virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */\r
-       \r
-       while (num_words--)\r
-       {\r
-               scan_field.in_handler_priv = words++;\r
-               jtag_add_dr_scan(1, &scan_field, TAP_PD);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)\r
-{\r
-       u32 data[5];\r
-       \r
-       jtag_add_statemove(TAP_TLR);\r
-       \r
-       data[0] = 0xaa995566; /* synch word */\r
-       data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */\r
-       data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */\r
-       data[3] = 0x20000000; /* NOOP */\r
-       data[4] = 0x20000000; /* NOOP */\r
-       virtex2_send_32(pld_device, 5, data);\r
-       \r
-       virtex2_receive_32(pld_device, 1, status);\r
-       \r
-       jtag_execute_queue();\r
-       \r
-       DEBUG("status: 0x%8.8x", *status);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_load(struct pld_device_s *pld_device, char *filename)\r
-{\r
-       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;\r
-       xilinx_bit_file_t bit_file;\r
-       int retval;\r
-       int i;\r
-\r
-       scan_field_t field;\r
-\r
-       field.device = virtex2_info->chain_pos;\r
-       field.out_mask = NULL;\r
-       field.in_value = NULL;\r
-       field.in_check_value = NULL;\r
-       field.in_check_mask = NULL;\r
-       field.in_handler = NULL;\r
-       field.in_handler_priv = NULL;\r
-       \r
-       if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)\r
-               return retval;\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */\r
-       jtag_execute_queue();\r
-       jtag_add_sleep(1000);\r
-       \r
-       virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */\r
-       jtag_execute_queue();\r
-       \r
-       for (i = 0; i < bit_file.length; i++)\r
-               bit_file.data[i] = flip_u32(bit_file.data[i], 8);\r
-       \r
-       field.num_bits = bit_file.length * 8;\r
-       field.out_value = bit_file.data;\r
-\r
-       jtag_add_dr_scan(1, &field, TAP_PD);\r
-       jtag_execute_queue();\r
-       \r
-       jtag_add_statemove(TAP_TLR);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */\r
-       jtag_add_runtest(13, TAP_RTI);\r
-       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */\r
-       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */\r
-       virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */\r
-       jtag_add_runtest(13, TAP_RTI);\r
-       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */\r
-       jtag_execute_queue();\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       pld_device_t *device;\r
-       virtex2_pld_device_t *virtex2_info;\r
-       u32 status;\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: virtex2 read_stat <num>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       device = get_pld_device_by_num(strtoul(args[0], NULL, 0));\r
-       if (!device)\r
-       {\r
-               command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       virtex2_info = device->driver_priv;\r
-       \r
-       virtex2_read_stat(device, &status);\r
-       \r
-       command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");\r
-\r
-       register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,\r
-                                        "read Virtex-II status register");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)\r
-{\r
-       virtex2_pld_device_t *virtex2_info;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               WARNING("incomplete pld device 'virtex2' configuration");\r
-               return ERROR_PLD_DEVICE_INVALID;\r
-       }\r
-       \r
-       virtex2_info = malloc(sizeof(virtex2_pld_device_t));\r
-       pld_device->driver_priv = virtex2_info;\r
-       \r
-       virtex2_info->chain_pos = strtoul(args[1], NULL, 0);\r
-       \r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "virtex2.h"
+
+#include "pld.h"
+#include "xilinx_bit.h"
+#include "command.h"
+#include "log.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+int virtex2_register_commands(struct command_context_s *cmd_ctx);
+int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
+int virtex2_load(struct pld_device_s *pld_device, char *filename);
+
+pld_driver_t virtex2_pld =
+{
+       .name = "virtex2",
+       .register_commands = virtex2_register_commands,
+       .pld_device_command = virtex2_pld_device_command,
+       .load = virtex2_load,
+};
+
+int virtex2_set_instr(int chain_pos, u32 new_instr)
+{
+       jtag_device_t *device = jtag_get_device(chain_pos);
+       
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+       
+               field.device = chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               jtag_add_ir_scan(1, &field, TAP_RTI);
+               
+               free(field.out_value);
+       }
+       
+       return ERROR_OK;
+}
+
+int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)
+{
+       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+       scan_field_t scan_field;
+       u8 *values;
+       int i;
+       
+       values = malloc(num_words * 4);
+
+       scan_field.device = virtex2_info->chain_pos;
+       scan_field.num_bits = num_words * 32;
+       scan_field.out_value = values;
+       scan_field.out_mask = NULL;
+       scan_field.in_value = NULL;
+       scan_field.in_check_value = NULL;
+       scan_field.in_check_mask = NULL;
+       scan_field.in_handler = NULL;
+       scan_field.in_handler_priv = NULL;
+       
+       for (i = 0; i < num_words; i++)
+               buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
+       
+       virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
+       
+       jtag_add_dr_scan(1, &scan_field, TAP_PD);
+       
+       free(values);
+       
+       return ERROR_OK;
+}
+
+int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       u32 *dest = priv;
+       *dest = flip_u32(le_to_h_u32(in_buf), 32);
+       return ERROR_OK;
+}
+
+int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)
+{
+       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+       scan_field_t scan_field;
+       
+       scan_field.device = virtex2_info->chain_pos;
+       scan_field.num_bits = 32;
+       scan_field.out_value = NULL;
+       scan_field.out_mask = NULL;
+       scan_field.in_value = NULL;
+       scan_field.in_check_value = NULL;
+       scan_field.in_check_mask = NULL;
+       scan_field.in_handler = virtex2_jtag_buf_to_u32;
+       
+       virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */
+       
+       while (num_words--)
+       {
+               scan_field.in_handler_priv = words++;
+               jtag_add_dr_scan(1, &scan_field, TAP_PD);
+       }
+       
+       return ERROR_OK;
+}
+
+int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)
+{
+       u32 data[5];
+       
+       jtag_add_statemove(TAP_TLR);
+       
+       data[0] = 0xaa995566; /* synch word */
+       data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
+       data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
+       data[3] = 0x20000000; /* NOOP */
+       data[4] = 0x20000000; /* NOOP */
+       virtex2_send_32(pld_device, 5, data);
+       
+       virtex2_receive_32(pld_device, 1, status);
+       
+       jtag_execute_queue();
+       
+       DEBUG("status: 0x%8.8x", *status);
+       
+       return ERROR_OK;
+}
+
+int virtex2_load(struct pld_device_s *pld_device, char *filename)
+{
+       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+       xilinx_bit_file_t bit_file;
+       int retval;
+       int i;
+
+       scan_field_t field;
+
+       field.device = virtex2_info->chain_pos;
+       field.out_mask = NULL;
+       field.in_value = NULL;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)
+               return retval;
+       
+       jtag_add_end_state(TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */
+       jtag_execute_queue();
+       jtag_add_sleep(1000);
+       
+       virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
+       jtag_execute_queue();
+       
+       for (i = 0; i < bit_file.length; i++)
+               bit_file.data[i] = flip_u32(bit_file.data[i], 8);
+       
+       field.num_bits = bit_file.length * 8;
+       field.out_value = bit_file.data;
+
+       jtag_add_dr_scan(1, &field, TAP_PD);
+       jtag_execute_queue();
+       
+       jtag_add_statemove(TAP_TLR);
+       
+       jtag_add_end_state(TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
+       jtag_add_runtest(13, TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+       virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
+       jtag_add_runtest(13, TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+       jtag_execute_queue();
+
+       return ERROR_OK;
+}
+
+int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       pld_device_t *device;
+       virtex2_pld_device_t *virtex2_info;
+       u32 status;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: virtex2 read_stat <num>");
+               return ERROR_OK;
+       }
+       
+       device = get_pld_device_by_num(strtoul(args[0], NULL, 0));
+       if (!device)
+       {
+               command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+
+       virtex2_info = device->driver_priv;
+       
+       virtex2_read_stat(device, &status);
+       
+       command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);
+       
+       return ERROR_OK;
+}
+
+int virtex2_register_commands(struct command_context_s *cmd_ctx)
+{
+       command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");
+
+       register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,
+                                        "read Virtex-II status register");
+
+       return ERROR_OK;
+}
+
+int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)
+{
+       virtex2_pld_device_t *virtex2_info;
+       
+       if (argc < 2)
+       {
+               WARNING("incomplete pld device 'virtex2' configuration");
+               return ERROR_PLD_DEVICE_INVALID;
+       }
+       
+       virtex2_info = malloc(sizeof(virtex2_pld_device_t));
+       pld_device->driver_priv = virtex2_info;
+       
+       virtex2_info->chain_pos = strtoul(args[1], NULL, 0);
+       
+       return ERROR_OK;
+}
index fa203e7a6ece8b29a015fa2bebe7646558f21e48..335a4cd2cee8fd1566f91ceada62eff9acddc62a 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "gdb_server.h"\r
-\r
-#include "server.h"\r
-#include "log.h"\r
-#include "binarybuffer.h"\r
-#include "jtag.h"\r
-#include "breakpoints.h"\r
-#include "flash.h"\r
-#include "target_request.h"\r
-#include "configuration.h"\r
-\r
-#include <string.h>\r
-#include <errno.h>\r
-#include <unistd.h>\r
-#include <stdlib.h>\r
-\r
-#if 0\r
-#define _DEBUG_GDB_IO_\r
-#endif\r
-\r
-static unsigned short gdb_port;\r
-static const char *DIGITS = "0123456789abcdef";\r
-\r
-static void gdb_log_callback(void *priv, const char *file, int line, \r
-               const char *function, const char *format, va_list args);\r
-\r
-enum gdb_detach_mode\r
-{\r
-       GDB_DETACH_RESUME,\r
-       GDB_DETACH_RESET,\r
-       GDB_DETACH_HALT,\r
-       GDB_DETACH_NOTHING\r
-};\r
-\r
-/* target behaviour on gdb detach */\r
-enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;\r
-\r
-/* set if we are sending a memory map to gdb\r
- * via qXfer:memory-map:read packet */\r
-int gdb_use_memory_map = 0;\r
-int gdb_flash_program = 0;\r
-\r
-/* if set, data aborts cause an error to be reported in memory read packets\r
- * see the code in gdb_read_memory_packet() for further explanations */\r
-int gdb_report_data_abort = 0;\r
-\r
-int gdb_last_signal(target_t *target)\r
-{\r
-       switch (target->debug_reason)\r
-       {\r
-               case DBG_REASON_DBGRQ:\r
-                       return 0x2; /* SIGINT */\r
-               case DBG_REASON_BREAKPOINT:\r
-               case DBG_REASON_WATCHPOINT:\r
-               case DBG_REASON_WPTANDBKPT:\r
-                       return 0x05; /* SIGTRAP */\r
-               case DBG_REASON_SINGLESTEP:\r
-                       return 0x05; /* SIGTRAP */\r
-               case DBG_REASON_NOTHALTED:\r
-                       return 0x0; /* no signal... shouldn't happen */\r
-               default:\r
-                       ERROR("BUG: undefined debug reason");\r
-                       exit(-1);\r
-       }\r
-}\r
-\r
-int gdb_get_char(connection_t *connection, int* next_char)\r
-{\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-       char *debug_buffer;\r
-#endif\r
-\r
-       if (gdb_con->buf_cnt-- > 0)\r
-       {\r
-               *next_char = *(gdb_con->buf_p++);\r
-               if (gdb_con->buf_cnt > 0)\r
-                       connection->input_pending = 1;\r
-               else\r
-                       connection->input_pending = 0;\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-               DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);\r
-#endif\r
-\r
-               return ERROR_OK;\r
-       }\r
-\r
-       for (;;)\r
-       {\r
-#ifndef _WIN32\r
-               /* a non-blocking socket will block if there is 0 bytes available on the socket,\r
-                * but return with as many bytes as are available immediately\r
-                */\r
-               struct timeval tv;\r
-               fd_set read_fds;\r
-               \r
-               FD_ZERO(&read_fds);\r
-               FD_SET(connection->fd, &read_fds);\r
-               \r
-               tv.tv_sec = 1;\r
-               tv.tv_usec = 0;\r
-               if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)\r
-               {\r
-                       /* This can typically be because a "monitor" command took too long\r
-                        * before printing any progress messages\r
-                        */\r
-                       return ERROR_GDB_TIMEOUT; \r
-               }\r
-#endif\r
-               gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);\r
-               if (gdb_con->buf_cnt > 0)\r
-               {\r
-                       break;\r
-               }\r
-               if (gdb_con->buf_cnt == 0)\r
-               {\r
-                       gdb_con->closed = 1;\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-\r
-#ifdef _WIN32\r
-               errno = WSAGetLastError();\r
-\r
-               switch(errno)\r
-               {\r
-                       case WSAEWOULDBLOCK:\r
-                               usleep(1000);\r
-                               break;\r
-                       case WSAECONNABORTED:\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       case WSAECONNRESET:\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       default:\r
-                               ERROR("read: %d", errno);\r
-                               exit(-1);\r
-               }\r
-#else\r
-               switch(errno)\r
-               {\r
-                       case EAGAIN:\r
-                               usleep(1000);\r
-                               break;\r
-                       case ECONNABORTED:\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       case ECONNRESET:\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       default:\r
-                               ERROR("read: %s", strerror(errno));\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-#endif\r
-       }\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-       debug_buffer = malloc(gdb_con->buf_cnt + 1);\r
-       memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);\r
-       debug_buffer[gdb_con->buf_cnt] = 0;\r
-       DEBUG("received '%s'", debug_buffer);\r
-       free(debug_buffer);\r
-#endif\r
-\r
-       gdb_con->buf_p = gdb_con->buffer;\r
-       gdb_con->buf_cnt--;\r
-       *next_char = *(gdb_con->buf_p++);\r
-       if (gdb_con->buf_cnt > 0)\r
-               connection->input_pending = 1;\r
-       else\r
-               connection->input_pending = 0;  \r
-#ifdef _DEBUG_GDB_IO_\r
-       DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_putback_char(connection_t *connection, int last_char)\r
-{\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-\r
-       if (gdb_con->buf_p > gdb_con->buffer)\r
-       {\r
-               *(--gdb_con->buf_p) = last_char;\r
-               gdb_con->buf_cnt++;\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: couldn't put character back");      \r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* The only way we can detect that the socket is closed is the first time\r
- * we write to it, we will fail. Subsequent write operations will\r
- * succeed. Shudder! */\r
-int gdb_write(connection_t *connection, void *data, int len)\r
-{\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-       if (gdb_con->closed)\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-\r
-       if (write_socket(connection->fd, data, len) == len)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-       gdb_con->closed = 1;\r
-       return ERROR_SERVER_REMOTE_CLOSED;\r
-}\r
-\r
-int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)\r
-{\r
-       int i;\r
-       unsigned char my_checksum = 0;\r
-#ifdef _DEBUG_GDB_IO_\r
-       char *debug_buffer;\r
-#endif\r
-       int reply;\r
-       int retval;\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-\r
-       for (i = 0; i < len; i++)\r
-               my_checksum += buffer[i];\r
-\r
-       while (1)\r
-       {\r
-#ifdef _DEBUG_GDB_IO_\r
-               debug_buffer = malloc(len + 1);\r
-               memcpy(debug_buffer, buffer, len);\r
-               debug_buffer[len] = 0;\r
-               DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);\r
-               free(debug_buffer);\r
-#endif\r
-#if 0\r
-               char checksum[3];\r
-               gdb_write(connection, "$", 1);\r
-               if (len > 0)\r
-                       gdb_write(connection, buffer, len);\r
-               gdb_write(connection, "#", 1);\r
-               \r
-               snprintf(checksum, 3, "%2.2x", my_checksum);\r
-               \r
-               gdb_write(connection, checksum, 2);\r
-#else\r
-               void *allocated = NULL;\r
-               char stackAlloc[1024];\r
-               char *t = stackAlloc;\r
-               int totalLen = 1 + len + 1 + 2;\r
-               if (totalLen > sizeof(stackAlloc))\r
-               {\r
-                       allocated = malloc(totalLen);\r
-                       t = allocated;\r
-                       if (allocated == NULL)\r
-                       {\r
-                               ERROR("Ran out of memory trying to reply packet %d\n", totalLen);\r
-                               exit(-1);\r
-                       }\r
-               }\r
-               t[0] = '$';\r
-               memcpy(t + 1, buffer, len);\r
-               t[1 + len] = '#';\r
-               t[1 + len + 1] = DIGITS[(my_checksum >> 4) & 0xf];\r
-               t[1 + len + 2] = DIGITS[my_checksum & 0xf];\r
-               \r
-               gdb_write(connection, t, totalLen);\r
-               \r
-               if (allocated)\r
-               {\r
-                       free(allocated);\r
-               }\r
-#endif\r
-               if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)\r
-                       return retval;\r
-\r
-               if (reply == '+')\r
-                       break;\r
-               else if (reply == '-')\r
-               {\r
-                       /* Stop sending output packets for now */\r
-                       log_remove_callback(gdb_log_callback, connection);\r
-                       WARNING("negative reply, retrying");\r
-               }\r
-               else if (reply == 0x3)\r
-               {\r
-                       gdb_con->ctrl_c = 1;\r
-                       if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)\r
-                               return retval;\r
-                       if (reply == '+')\r
-                               break;\r
-                       else if (reply == '-')\r
-                       {\r
-                               /* Stop sending output packets for now */\r
-                               log_remove_callback(gdb_log_callback, connection);\r
-                               WARNING("negative reply, retrying");\r
-                       }\r
-                       else\r
-                       {\r
-                               ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-       }\r
-       if (gdb_con->closed)\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_put_packet(connection_t *connection, char *buffer, int len)\r
-{\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-       gdb_con->busy = 1;\r
-       int retval = gdb_put_packet_inner(connection, buffer, len);\r
-       gdb_con->busy = 0;\r
-       return retval;\r
-}\r
-\r
-int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)\r
-{\r
-       int character;\r
-       int count = 0;\r
-       int retval;\r
-       char checksum[3];\r
-       unsigned char my_checksum = 0;\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-\r
-       while (1)\r
-       {\r
-               do\r
-               {\r
-                       if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)\r
-                               return retval;\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-                       DEBUG("character: '%c'", character);\r
-#endif\r
-\r
-                       switch (character)\r
-                       {\r
-                               case '$':\r
-                                       break;\r
-                               case '+':\r
-                                       WARNING("acknowledgment received, but no packet pending");\r
-                                       break;\r
-                               case '-':\r
-                                       WARNING("negative acknowledgment, but no packet pending");\r
-                                       break;\r
-                               case 0x3:\r
-                                       gdb_con->ctrl_c = 1;\r
-                                       *len = 0;\r
-                                       return ERROR_OK;\r
-                               default:\r
-                                       WARNING("ignoring character 0x%x", character);\r
-                                       break;\r
-                       }\r
-               } while (character != '$');\r
-\r
-               my_checksum = 0;\r
-               \r
-               count = 0;\r
-               gdb_connection_t *gdb_con = connection->priv;\r
-               for (;;)\r
-               {\r
-                       /* The common case is that we have an entire packet with no escape chars.\r
-                        * We need to leave at least 2 bytes in the buffer to have\r
-                        * gdb_get_char() update various bits and bobs correctly. \r
-                        */\r
-                       if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt+count) < *len))\r
-                       {\r
-                               /* The compiler will struggle a bit with constant propagation and\r
-                                * aliasing, so we help it by showing that these values do not\r
-                                * change inside the loop \r
-                                */ \r
-                               int i;\r
-                               char *buf = gdb_con->buf_p;\r
-                               int run = gdb_con->buf_cnt - 2;\r
-                               i = 0;\r
-                               int done = 0;\r
-                               while (i < run)\r
-                               {\r
-                                       character = *buf++;\r
-                                       i++;\r
-                                       if (character == '#')\r
-                                       {\r
-                                               /* Danger! character can be '#' when esc is \r
-                                                * used so we need an explicit boolean for done here.\r
-                                                */\r
-                                               done = 1;\r
-                                               break;\r
-                                       }\r
-                                       \r
-                                       if (character == '}')\r
-                                       {\r
-                                               /* data transmitted in binary mode (X packet)\r
-                                                * uses 0x7d as escape character */\r
-                                               my_checksum += character & 0xff;\r
-                                               character = *buf++;\r
-                                               i++;\r
-                                               my_checksum += character & 0xff;\r
-                                               buffer[count++] = (character ^ 0x20) & 0xff;\r
-                                       } else\r
-                                       {\r
-                                               my_checksum += character & 0xff;\r
-                                               buffer[count++] = character & 0xff;\r
-                                       }\r
-                               }\r
-                               gdb_con->buf_p += i;\r
-                               gdb_con->buf_cnt -= i;\r
-                               if (done) \r
-                                       break;\r
-                       } \r
-                       if (count > *len)\r
-                       {\r
-                               ERROR("packet buffer too small");\r
-                               return ERROR_GDB_BUFFER_TOO_SMALL;\r
-                       }\r
-                       \r
-                       if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)\r
-                               return retval;\r
-\r
-                       if (character == '#')\r
-                               break;\r
-\r
-                       if (character == '}')\r
-                       {\r
-                               /* data transmitted in binary mode (X packet)\r
-                                * uses 0x7d as escape character */\r
-                               my_checksum += character & 0xff;\r
-                               if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)\r
-                                       return retval;\r
-                               my_checksum += character & 0xff;\r
-                               buffer[count++] = (character ^ 0x20) & 0xff;\r
-                       }\r
-                       else\r
-                       {\r
-                               my_checksum += character & 0xff;\r
-                               buffer[count++] = character & 0xff;\r
-                       }\r
-\r
-               }\r
-\r
-               *len = count;\r
-\r
-               if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)\r
-                       return retval;\r
-               checksum[0] = character;\r
-               if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)\r
-                       return retval;\r
-               checksum[1] = character;\r
-               checksum[2] = 0;\r
-\r
-               if (my_checksum == strtoul(checksum, NULL, 16))\r
-               {\r
-                       gdb_write(connection, "+", 1);\r
-                       break;\r
-               }\r
-\r
-               WARNING("checksum error, requesting retransmission");\r
-               gdb_write(connection, "-", 1);\r
-       }\r
-       if (gdb_con->closed)\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_get_packet(connection_t *connection, char *buffer, int *len)\r
-{\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-       gdb_con->busy = 1;\r
-       int retval = gdb_get_packet_inner(connection, buffer, len);\r
-       gdb_con->busy = 0;\r
-       return retval;\r
-}\r
-       \r
-int gdb_output_con(connection_t *connection, char* line)\r
-{\r
-       char *hex_buffer;\r
-       int i, bin_size;\r
-\r
-       bin_size = strlen(line);\r
-\r
-       hex_buffer = malloc(bin_size*2 + 4);\r
-\r
-       hex_buffer[0] = 'O';\r
-       for (i=0; i<bin_size; i++)\r
-               snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]);\r
-       hex_buffer[bin_size*2+1] = '0';\r
-       hex_buffer[bin_size*2+2] = 'a';\r
-       hex_buffer[bin_size*2+3] = 0x0;\r
-\r
-       gdb_put_packet(connection, hex_buffer, bin_size*2 + 3);\r
-\r
-       free(hex_buffer);\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_output(struct command_context_s *context, char* line)\r
-{\r
-       /* this will be dumped to the log and also sent as an O packet if possible */\r
-       USER(line); \r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_program_handler(struct target_s *target, enum target_event event, void *priv)\r
-{\r
-       FILE *script;\r
-       struct command_context_s *cmd_ctx = priv;\r
-       \r
-       if (target->gdb_program_script)\r
-       {\r
-               script = open_file_from_path(cmd_ctx, target->gdb_program_script, "r");\r
-               if (!script)\r
-               {\r
-                       ERROR("couldn't open script file %s", target->gdb_program_script);\r
-                               return ERROR_OK;\r
-               }\r
-\r
-               INFO("executing gdb_program script '%s'", target->gdb_program_script);\r
-               command_run_file(cmd_ctx, script, COMMAND_EXEC);\r
-               fclose(script);\r
-               \r
-               jtag_execute_queue();\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)\r
-{\r
-       connection_t *connection = priv;\r
-       gdb_connection_t *gdb_connection = connection->priv;\r
-       char sig_reply[4];\r
-       int signal;\r
-\r
-       switch (event)\r
-       {\r
-               case TARGET_EVENT_HALTED:\r
-                       /* In the GDB protocol when we are stepping or coninuing execution,\r
-                        * we have a lingering reply. Upon receiving a halted event \r
-                        * when we have that lingering packet, we reply to the original\r
-                        * step or continue packet.\r
-                        * \r
-                        * Executing monitor commands can bring the target in and\r
-                        * out of the running state so we'll see lots of TARGET_EVENT_XXX\r
-                        * that are to be ignored.\r
-                        */\r
-                       if (gdb_connection->frontend_state == TARGET_RUNNING)\r
-                       {\r
-                               /* stop forwarding log packets! */\r
-                               log_remove_callback(gdb_log_callback, connection);\r
-                               \r
-                               if (gdb_connection->ctrl_c)\r
-                               {\r
-                                       signal = 0x2;\r
-                                       gdb_connection->ctrl_c = 0;\r
-                               }\r
-                               else\r
-                               {\r
-                                       signal = gdb_last_signal(target);\r
-                               }\r
-\r
-                               snprintf(sig_reply, 4, "T%2.2x", signal);\r
-                               gdb_put_packet(connection, sig_reply, 3);\r
-                               gdb_connection->frontend_state = TARGET_HALTED;\r
-                       }\r
-                       break;\r
-               case TARGET_EVENT_GDB_PROGRAM:\r
-                       gdb_program_handler(target, event, connection->cmd_ctx);\r
-                       break;\r
-               default:\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_new_connection(connection_t *connection)\r
-{\r
-       gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t));\r
-       gdb_service_t *gdb_service = connection->service->priv;\r
-       int retval;\r
-       int initial_ack;\r
-\r
-       connection->priv = gdb_connection;\r
-\r
-       /* initialize gdb connection information */\r
-       gdb_connection->buf_p = gdb_connection->buffer;\r
-       gdb_connection->buf_cnt = 0;\r
-       gdb_connection->ctrl_c = 0;\r
-       gdb_connection->frontend_state = TARGET_HALTED;\r
-       gdb_connection->vflash_image = NULL;\r
-       gdb_connection->closed = 0;\r
-       gdb_connection->busy = 0;\r
-       \r
-       /* output goes through gdb connection */\r
-       command_set_output_handler(connection->cmd_ctx, gdb_output, connection);\r
-\r
-       /* register callback to be informed about target events */\r
-       target_register_event_callback(gdb_target_callback_event_handler, connection);  \r
-\r
-       /* a gdb session just attached, put the target in halt mode */\r
-       if (((retval = gdb_service->target->type->halt(gdb_service->target)) != ERROR_OK) &&\r
-                       (retval != ERROR_TARGET_ALREADY_HALTED))\r
-       {\r
-               ERROR("error(%d) when trying to halt target, falling back to \"reset halt\"", retval);\r
-               command_run_line(connection->cmd_ctx, "reset halt");\r
-       }\r
-\r
-       /* This will time out after 1 second */\r
-       command_run_line(connection->cmd_ctx, "wait_halt 1");\r
-\r
-       /* remove the initial ACK from the incoming buffer */\r
-       if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)\r
-               return retval;\r
-\r
-       if (initial_ack != '+')\r
-               gdb_putback_char(connection, initial_ack);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_connection_closed(connection_t *connection)\r
-{\r
-       gdb_service_t *gdb_service = connection->service->priv;\r
-       gdb_connection_t *gdb_connection = connection->priv;\r
-\r
-       /* see if an image built with vFlash commands is left */\r
-       if (gdb_connection->vflash_image)\r
-       {\r
-               image_close(gdb_connection->vflash_image);\r
-               free(gdb_connection->vflash_image);\r
-               gdb_connection->vflash_image = NULL;\r
-       }\r
-\r
-       /* if this connection registered a debug-message receiver delete it */\r
-       delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target);\r
-       \r
-       if (connection->priv)\r
-       {\r
-               free(connection->priv);\r
-               connection->priv = NULL;\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: connection->priv == NULL");\r
-       }\r
-\r
-       target_unregister_event_callback(gdb_target_callback_event_handler, connection);\r
-       log_remove_callback(gdb_log_callback, connection);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void gdb_send_error(connection_t *connection, u8 the_error)\r
-{\r
-       char err[4];\r
-       snprintf(err, 4, "E%2.2X", the_error );\r
-       gdb_put_packet(connection, err, 3);\r
-}\r
-\r
-int gdb_last_signal_packet(connection_t *connection, target_t *target, char* packet, int packet_size)\r
-{\r
-       char sig_reply[4];\r
-       int signal;\r
-\r
-       signal = gdb_last_signal(target);\r
-\r
-       snprintf(sig_reply, 4, "S%2.2x", signal);\r
-       gdb_put_packet(connection, sig_reply, 3);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* Convert register to string of bits. NB! The # of bits in the\r
- * register might be non-divisible by 8(a byte), in which\r
- * case an entire byte is shown. */\r
-void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg)\r
-{\r
-       int i;\r
-\r
-       u8 *buf;\r
-       int buf_len;\r
-       buf = reg->value;\r
-       buf_len = CEIL(reg->size, 8); \r
-\r
-       if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-       {\r
-               for (i = 0; i < buf_len; i++)\r
-               {\r
-                       tstr[i*2]   = DIGITS[(buf[i]>>4) & 0xf];\r
-                       tstr[i*2+1] = DIGITS[buf[i]&0xf];\r
-               }\r
-       }\r
-       else\r
-       {\r
-               for (i = 0; i < buf_len; i++)\r
-               {\r
-                       tstr[(buf_len-1-i)*2]   = DIGITS[(buf[i]>>4)&0xf];\r
-                       tstr[(buf_len-1-i)*2+1] = DIGITS[buf[i]&0xf];\r
-               }\r
-       }       \r
-}\r
-\r
-void gdb_target_to_str(target_t *target, char *tstr, char *str)\r
-{\r
-       int str_len = strlen(tstr);\r
-       int i;\r
-\r
-       if (str_len % 2)\r
-       {\r
-               ERROR("BUG: gdb value with uneven number of characters encountered");\r
-               exit(-1);\r
-       }\r
-\r
-       if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-       {\r
-               for (i = 0; i < str_len; i+=2)\r
-               {\r
-                       str[str_len - i - 1] = tstr[i + 1];\r
-                       str[str_len - i - 2] = tstr[i];\r
-               }\r
-       }\r
-       else\r
-       {\r
-               for (i = 0; i < str_len; i++)\r
-               {\r
-                       str[i] = tstr[i];\r
-               }\r
-       }       \r
-}\r
-\r
-int gdb_get_registers_packet(connection_t *connection, target_t *target, char* packet, int packet_size)\r
-{\r
-       reg_t **reg_list;\r
-       int reg_list_size;\r
-       int retval;\r
-       int reg_packet_size = 0;\r
-       char *reg_packet;\r
-       char *reg_packet_p;\r
-       int i;\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-       DEBUG("-");\r
-#endif\r
-\r
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)\r
-       {\r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_NOT_HALTED:\r
-                               ERROR("gdb requested registers but we're not halted, dropping connection");\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       default:\r
-                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */\r
-                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");\r
-                               exit(-1);\r
-               }\r
-       }\r
-\r
-       for (i = 0; i < reg_list_size; i++)\r
-       {\r
-               reg_packet_size += reg_list[i]->size;\r
-       }\r
-\r
-       reg_packet = malloc(CEIL(reg_packet_size, 8) * 2);\r
-       reg_packet_p = reg_packet;\r
-\r
-       for (i = 0; i < reg_list_size; i++)\r
-       {\r
-               gdb_str_to_target(target, reg_packet_p, reg_list[i]);\r
-               reg_packet_p += CEIL(reg_list[i]->size, 8) * 2;\r
-       }\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-       {\r
-               char *reg_packet_p;\r
-               reg_packet_p = strndup(reg_packet, CEIL(reg_packet_size, 8) * 2);\r
-               DEBUG("reg_packet: %s", reg_packet_p);\r
-               free(reg_packet_p);\r
-       }\r
-#endif\r
-\r
-       gdb_put_packet(connection, reg_packet, CEIL(reg_packet_size, 8) * 2);\r
-       free(reg_packet);\r
-\r
-       free(reg_list);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_set_registers_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       int i;\r
-       reg_t **reg_list;\r
-       int reg_list_size;\r
-       int retval;\r
-       char *packet_p;\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-       DEBUG("-");\r
-#endif\r
-\r
-       /* skip command character */\r
-       packet++;\r
-       packet_size--;\r
-\r
-       if (packet_size % 2)\r
-       {\r
-               WARNING("GDB set_registers packet with uneven characters received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)\r
-       {\r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_NOT_HALTED:\r
-                               ERROR("gdb tried to registers but we're not halted, dropping connection");\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       default:\r
-                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */\r
-                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");\r
-                               exit(-1);\r
-               }\r
-       }\r
-\r
-       packet_p = packet;\r
-       for (i = 0; i < reg_list_size; i++)\r
-       {\r
-               u8 *bin_buf;\r
-               char *hex_buf;\r
-               reg_arch_type_t *arch_type;\r
-\r
-               /* convert from GDB-string (target-endian) to hex-string (big-endian) */\r
-               hex_buf = malloc(CEIL(reg_list[i]->size, 8) * 2);\r
-               gdb_target_to_str(target, packet_p, hex_buf);\r
-\r
-               /* convert hex-string to binary buffer */\r
-               bin_buf = malloc(CEIL(reg_list[i]->size, 8));\r
-               str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16);\r
-\r
-               /* get register arch_type, and call set method */       \r
-               arch_type = register_get_arch_type(reg_list[i]->arch_type);\r
-               if (arch_type == NULL)\r
-               {\r
-                       ERROR("BUG: encountered unregistered arch type");\r
-                       exit(-1);\r
-               }\r
-               arch_type->set(reg_list[i], bin_buf);\r
-\r
-               /* advance packet pointer */            \r
-               packet_p += (CEIL(reg_list[i]->size, 8) * 2);\r
-\r
-               free(bin_buf);\r
-               free(hex_buf);\r
-       }\r
-\r
-       /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */ \r
-       free(reg_list);\r
-\r
-       gdb_put_packet(connection, "OK", 2);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_get_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       char *reg_packet;\r
-       int reg_num = strtoul(packet + 1, NULL, 16);\r
-       reg_t **reg_list;\r
-       int reg_list_size;\r
-       int retval;\r
-\r
-#ifdef _DEBUG_GDB_IO_\r
-       DEBUG("-");\r
-#endif\r
-\r
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)\r
-       {\r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_NOT_HALTED:\r
-                               ERROR("gdb requested registers but we're not halted, dropping connection");\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       default:\r
-                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */\r
-                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");\r
-                               exit(-1);\r
-               }\r
-       }\r
-\r
-       if (reg_list_size <= reg_num)\r
-       {\r
-               ERROR("gdb requested a non-existing register");\r
-               exit(-1);\r
-       }\r
-\r
-       reg_packet = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);\r
-\r
-       gdb_str_to_target(target, reg_packet, reg_list[reg_num]);\r
-\r
-       gdb_put_packet(connection, reg_packet, CEIL(reg_list[reg_num]->size, 8) * 2);\r
-\r
-       free(reg_list);\r
-       free(reg_packet);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_set_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       char *separator;\r
-       char *hex_buf;\r
-       u8 *bin_buf;\r
-       int reg_num = strtoul(packet + 1, &separator, 16);\r
-       reg_t **reg_list;\r
-       int reg_list_size;\r
-       int retval;\r
-       reg_arch_type_t *arch_type;\r
-\r
-       DEBUG("-");\r
-\r
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)\r
-       {\r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_NOT_HALTED:\r
-                               ERROR("gdb tried to set a register but we're not halted, dropping connection");\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       default:\r
-                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */\r
-                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");\r
-                               exit(-1);\r
-               }\r
-       }\r
-\r
-       if (reg_list_size < reg_num)\r
-       {\r
-               ERROR("gdb requested a non-existing register");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       if (*separator != '=')\r
-       {\r
-               ERROR("GDB 'set register packet', but no '=' following the register number");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       /* convert from GDB-string (target-endian) to hex-string (big-endian) */\r
-       hex_buf = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);\r
-       gdb_target_to_str(target, separator + 1, hex_buf);\r
-\r
-       /* convert hex-string to binary buffer */\r
-       bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8));\r
-       str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16);\r
-\r
-       /* get register arch_type, and call set method */       \r
-       arch_type = register_get_arch_type(reg_list[reg_num]->arch_type);\r
-       if (arch_type == NULL)\r
-       {\r
-               ERROR("BUG: encountered unregistered arch type");\r
-               exit(-1);\r
-       }\r
-       arch_type->set(reg_list[reg_num], bin_buf);\r
-\r
-       gdb_put_packet(connection, "OK", 2);\r
-\r
-       free(bin_buf);\r
-       free(hex_buf);\r
-       free(reg_list);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_memory_packet_error(connection_t *connection, int retval)\r
-{\r
-       switch (retval)\r
-       {\r
-               case ERROR_TARGET_NOT_HALTED:\r
-                       ERROR("gdb tried to read memory but we're not halted, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               case ERROR_TARGET_DATA_ABORT:\r
-                       gdb_send_error(connection, EIO);\r
-                       break;\r
-               case ERROR_TARGET_TRANSLATION_FAULT:\r
-                       gdb_send_error(connection, EFAULT);\r
-                       break;\r
-               case ERROR_TARGET_UNALIGNED_ACCESS:\r
-                       gdb_send_error(connection, EFAULT);\r
-                       break;\r
-               default:\r
-                       /* This could be that the target reset itself. */\r
-                       ERROR("unexpected error %i. Dropping connection.", retval);\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* We don't have to worry about the default 2 second timeout for GDB packets,\r
- * because GDB breaks up large memory reads into smaller reads.\r
- * \r
- * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????\r
- */\r
-int gdb_read_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       char *separator;\r
-       u32 addr = 0;\r
-       u32 len = 0;\r
-\r
-       u8 *buffer;\r
-       char *hex_buffer;\r
-\r
-       int retval = ERROR_OK;\r
-\r
-       /* skip command character */\r
-       packet++;\r
-\r
-       addr = strtoul(packet, &separator, 16);\r
-\r
-       if (*separator != ',')\r
-       {\r
-               ERROR("incomplete read memory packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       len = strtoul(separator+1, NULL, 16);\r
-\r
-       buffer = malloc(len);\r
-\r
-       DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);\r
-\r
-       retval = target_read_buffer(target, addr, len, buffer);\r
-\r
-       if ((retval == ERROR_TARGET_DATA_ABORT) && (!gdb_report_data_abort))\r
-       {\r
-               /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.\r
-                * At some point this might be fixed in GDB, in which case this code can be removed.\r
-                * \r
-                * OpenOCD developers are acutely aware of this problem, but there is nothing\r
-                * gained by involving the user in this problem that hopefully will get resolved\r
-                * eventually\r
-                * \r
-                * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395\r
-                *\r
-                * For now, the default is to fix up things to make current GDB versions work.\r
-                * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command.\r
-                */\r
-               memset(buffer, 0, len);\r
-               retval = ERROR_OK;\r
-       }\r
-\r
-       if (retval == ERROR_OK)\r
-       {\r
-               hex_buffer = malloc(len * 2 + 1);\r
-\r
-               int i;\r
-               for (i = 0; i < len; i++)\r
-               {\r
-                       u8 t = buffer[i];\r
-                       hex_buffer[2 * i] = DIGITS[(t >> 4) & 0xf];\r
-                       hex_buffer[2 * i + 1] = DIGITS[t & 0xf];\r
-               }\r
-\r
-               gdb_put_packet(connection, hex_buffer, len * 2);\r
-\r
-               free(hex_buffer);\r
-       }\r
-       else\r
-       {\r
-               retval = gdb_memory_packet_error(connection, retval);\r
-       }\r
-\r
-       free(buffer);\r
-\r
-       return retval;\r
-}\r
-\r
-int gdb_write_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       char *separator;\r
-       u32 addr = 0;\r
-       u32 len = 0;\r
-\r
-       u8 *buffer;\r
-\r
-       int i;\r
-       int retval;\r
-\r
-       /* skip command character */\r
-       packet++;\r
-\r
-       addr = strtoul(packet, &separator, 16);\r
-\r
-       if (*separator != ',')\r
-       {\r
-               ERROR("incomplete write memory packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       len = strtoul(separator+1, &separator, 16);\r
-\r
-       if (*(separator++) != ':')\r
-       {\r
-               ERROR("incomplete write memory packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       buffer = malloc(len);\r
-\r
-       DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);\r
-\r
-       for (i=0; i<len; i++)\r
-       {\r
-               u32 tmp;\r
-               sscanf(separator + 2*i, "%2x", &tmp);\r
-               buffer[i] = tmp;\r
-       }\r
-\r
-       retval = target_write_buffer(target, addr, len, buffer);\r
-\r
-       if (retval == ERROR_OK)\r
-       {\r
-               gdb_put_packet(connection, "OK", 2);\r
-       }\r
-       else\r
-       {\r
-               if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)\r
-                       return retval; \r
-       }\r
-\r
-       free(buffer);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       char *separator;\r
-       u32 addr = 0;\r
-       u32 len = 0;\r
-\r
-       int retval;\r
-\r
-       /* skip command character */\r
-       packet++;\r
-\r
-       addr = strtoul(packet, &separator, 16);\r
-\r
-       if (*separator != ',')\r
-       {\r
-               ERROR("incomplete write memory binary packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       len = strtoul(separator+1, &separator, 16);\r
-\r
-       if (*(separator++) != ':')\r
-       {\r
-               ERROR("incomplete write memory binary packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       retval = ERROR_OK;\r
-       if (len)\r
-       {\r
-               DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);\r
-\r
-               retval = target_write_buffer(target, addr, len, (u8*)separator);\r
-       }\r
-\r
-       if (retval == ERROR_OK)\r
-       {\r
-               gdb_put_packet(connection, "OK", 2);\r
-       }\r
-       else\r
-       {\r
-               if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)\r
-                       return retval; \r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void gdb_step_continue_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       int current = 0;\r
-       u32 address = 0x0;\r
-\r
-       DEBUG("-");\r
-\r
-       if (packet_size > 1)\r
-       {\r
-               packet[packet_size] = 0;\r
-               address = strtoul(packet + 1, NULL, 16);\r
-       }\r
-       else\r
-       {\r
-               current = 1;\r
-       }\r
-\r
-       if (packet[0] == 'c')\r
-       {\r
-               DEBUG("continue");\r
-               target->type->resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */\r
-       }\r
-       else if (packet[0] == 's')\r
-       {\r
-               DEBUG("step");\r
-               target->type->step(target, current, address, 0); /* step at current or address, don't handle breakpoints */\r
-       }\r
-}\r
-\r
-int gdb_bp_wp_packet_error(connection_t *connection, int retval)\r
-{\r
-       switch (retval)\r
-       {\r
-               case ERROR_TARGET_NOT_HALTED:\r
-                       ERROR("gdb tried to set a breakpoint but we're not halted, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-                       break;\r
-               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:\r
-                       gdb_send_error(connection, EBUSY);\r
-                       break;\r
-               default:\r
-                       ERROR("BUG: unexpected error %i", retval);\r
-                       exit(-1);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       int type;\r
-       enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;\r
-       enum watchpoint_rw wp_type;\r
-       u32 address;\r
-       u32 size;\r
-       char *separator;\r
-       int retval;\r
-\r
-       DEBUG("-");\r
-\r
-       type = strtoul(packet + 1, &separator, 16);\r
-\r
-       if (type == 0)  /* memory breakpoint */\r
-               bp_type = BKPT_SOFT;\r
-       else if (type == 1) /* hardware breakpoint */\r
-               bp_type = BKPT_HARD;\r
-       else if (type == 2) /* write watchpoint */\r
-               wp_type = WPT_WRITE;\r
-       else if (type == 3) /* read watchpoint */\r
-               wp_type = WPT_READ;\r
-       else if (type == 4) /* access watchpoint */\r
-               wp_type = WPT_ACCESS;\r
-\r
-       if (*separator != ',')\r
-       {\r
-               ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       address = strtoul(separator+1, &separator, 16);\r
-\r
-       if (*separator != ',')\r
-       {\r
-               ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-\r
-       size = strtoul(separator+1, &separator, 16);\r
-\r
-       switch (type)\r
-       {\r
-               case 0:\r
-               case 1:\r
-                       if (packet[0] == 'Z')\r
-                       {\r
-                               if ((retval = breakpoint_add(target, address, size, bp_type)) != ERROR_OK)\r
-                               {\r
-                                       if ((retval = gdb_bp_wp_packet_error(connection, retval)) != ERROR_OK)\r
-                                               return retval;\r
-                               }\r
-                               else\r
-                               {\r
-                                       gdb_put_packet(connection, "OK", 2);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               breakpoint_remove(target, address);\r
-                               gdb_put_packet(connection, "OK", 2);\r
-                       }\r
-                       break;\r
-               case 2:\r
-               case 3:\r
-               case 4:\r
-               {\r
-                       if (packet[0] == 'Z')\r
-                       {\r
-                               if ((retval = watchpoint_add(target, address, size, type-2, 0, 0xffffffffu)) != ERROR_OK)\r
-                               {\r
-                                       if ((retval = gdb_bp_wp_packet_error(connection, retval)) != ERROR_OK)\r
-                                               return retval;\r
-                               }\r
-                               else\r
-                               {\r
-                                       gdb_put_packet(connection, "OK", 2);\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               watchpoint_remove(target, address);\r
-                               gdb_put_packet(connection, "OK", 2);\r
-                       }\r
-                       break;\r
-               }\r
-               default:\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* print out a string and allocate more space as needed, mainly used for XML at this point */\r
-void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, ...)\r
-{\r
-       if (*retval != ERROR_OK)\r
-       {\r
-               return;\r
-       }\r
-       int first = 1;\r
-       \r
-       for (;;)\r
-       {\r
-               if ((*xml == NULL) || (!first))\r
-               {\r
-                       /* start by 0 to exercise all the code paths.\r
-                        * Need minimum 2 bytes to fit 1 char and 0 terminator. */\r
-                        \r
-                       *size = *size * 2 + 2;\r
-                       char *t = *xml;\r
-                       *xml = realloc(*xml, *size);\r
-                       if (*xml == NULL)\r
-                       {\r
-                               if (t)\r
-                                       free(t);\r
-                               *retval = ERROR_SERVER_REMOTE_CLOSED;\r
-                               return;\r
-                       }\r
-               }\r
-               \r
-           va_list ap;\r
-           int ret;\r
-           va_start(ap, fmt);\r
-           ret = vsnprintf(*xml + *pos, *size - *pos, fmt, ap);\r
-           va_end(ap);\r
-           if ((ret > 0) && ((ret + 1) < *size - *pos))\r
-           {\r
-               *pos += ret;\r
-               return;\r
-           }\r
-           /* there was just enough or not enough space, allocate more. */\r
-           first = 0;\r
-       }\r
-}\r
-\r
-static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len)\r
-{\r
-       char *separator;\r
-       \r
-       /* Extract and NUL-terminate the annex. */\r
-       *annex = buf;\r
-       while (*buf && *buf != ':')\r
-               buf++;\r
-       if (*buf == '\0')\r
-               return -1;\r
-       *buf++ = 0;\r
-       \r
-       /* After the read marker and annex, qXfer looks like a\r
-        * traditional 'm' packet. */\r
-       \r
-       *ofs = strtoul(buf, &separator, 16);\r
-\r
-       if (*separator != ',')\r
-               return -1;\r
-\r
-       *len = strtoul(separator+1, NULL, 16);\r
-       \r
-       return 0;\r
-}\r
-\r
-int gdb_calc_blocksize(flash_bank_t *bank)\r
-{\r
-       int i;\r
-       int block_size = 0xffffffff;\r
-       \r
-       /* loop through all sectors and return smallest sector size */\r
-       \r
-       for (i = 0; i < bank->num_sectors; i++)\r
-       {\r
-               if (bank->sectors[i].size < block_size)\r
-                       block_size = bank->sectors[i].size;\r
-       }\r
-       \r
-       return block_size;\r
-}\r
-\r
-int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       command_context_t *cmd_ctx = connection->cmd_ctx;\r
-       \r
-       if (strstr(packet, "qRcmd,"))\r
-       {\r
-               if (packet_size > 6)\r
-               {\r
-                       char *cmd;\r
-                       int i;\r
-                       cmd = malloc((packet_size - 6)/2 + 1);\r
-                       for (i=0; i < (packet_size - 6)/2; i++)\r
-                       {\r
-                               u32 tmp;\r
-                               sscanf(packet + 6 + 2*i, "%2x", &tmp);\r
-                               cmd[i] = tmp;\r
-                       }\r
-                       cmd[(packet_size - 6)/2] = 0x0;\r
-                       \r
-                       /* We want to print all debug output to GDB connection */\r
-                       log_add_callback(gdb_log_callback, connection);\r
-                       target_call_timer_callbacks();\r
-                       command_run_line(cmd_ctx, cmd);\r
-                       free(cmd);\r
-               }\r
-               gdb_put_packet(connection, "OK", 2);\r
-               return ERROR_OK;\r
-       }\r
-       else if (strstr(packet, "qCRC:"))\r
-       {\r
-               if (packet_size > 5)\r
-               {\r
-                       int retval;\r
-                       char gdb_reply[10];\r
-                       char *separator;\r
-                       u32 checksum;\r
-                       u32 addr = 0;\r
-                       u32 len = 0;\r
-                       \r
-                       /* skip command character */\r
-                       packet += 5;\r
-                       \r
-                       addr = strtoul(packet, &separator, 16);\r
-                       \r
-                       if (*separator != ',')\r
-                       {\r
-                               ERROR("incomplete read memory packet received, dropping connection");\r
-                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                       }\r
-                       \r
-                       len = strtoul(separator + 1, NULL, 16);\r
-                       \r
-                       retval = target_checksum_memory(target, addr, len, &checksum);\r
-                       \r
-                       if (retval == ERROR_OK)\r
-                       {\r
-                               snprintf(gdb_reply, 10, "C%8.8x", checksum);\r
-                               gdb_put_packet(connection, gdb_reply, 9);\r
-                       }\r
-                       else\r
-                       {\r
-                               if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)\r
-                                       return retval; \r
-                       }\r
-                       \r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       else if (strstr(packet, "qSupported"))\r
-       {\r
-               /* we currently support packet size and qXfer:memory-map:read (if enabled)\r
-                * disable qXfer:features:read for the moment */\r
-               int retval = ERROR_OK;\r
-               char *buffer = NULL;\r
-               int pos = 0;\r
-               int size = 0;\r
-\r
-               xml_printf(&retval, &buffer, &pos, &size, \r
-                               "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",\r
-                               (GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-');\r
-               \r
-               if (retval != ERROR_OK)\r
-               {\r
-                       gdb_send_error(connection, 01);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               gdb_put_packet(connection, buffer, strlen(buffer));\r
-               free(buffer);\r
-               \r
-               return ERROR_OK;\r
-       }\r
-       else if (strstr(packet, "qXfer:memory-map:read::"))\r
-       {\r
-               /* We get away with only specifying flash here. Regions that are not\r
-                * specified are treated as if we provided no memory map(if not we \r
-                * could detect the holes and mark them as RAM).\r
-                * Normally we only execute this code once, but no big deal if we\r
-                * have to regenerate it a couple of times. */\r
-                \r
-               flash_bank_t *p;\r
-               char *xml = NULL;\r
-               int size = 0;\r
-               int pos = 0;\r
-               int retval = ERROR_OK;\r
-               \r
-               int offset;\r
-               int length;\r
-               char *separator;\r
-               int blocksize;\r
-               \r
-               /* skip command character */\r
-               packet += 23;\r
-               \r
-               offset = strtoul(packet, &separator, 16);\r
-               length = strtoul(separator + 1, &separator, 16);\r
-               \r
-               xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");\r
-               \r
-               int i = 0;\r
-               for (;;)\r
-               {\r
-                       p = get_flash_bank_by_num(i);\r
-                       if (p == NULL)\r
-                               break;\r
-                       \r
-                       /* if device has uneven sector sizes, eg. str7, lpc\r
-                        * we pass the smallest sector size to gdb memory map */\r
-                       blocksize = gdb_calc_blocksize(p);\r
-                       \r
-                       xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \\r
-                               "<property name=\"blocksize\">0x%x</property>\n" \\r
-                               "</memory>\n", \\r
-                               p->base, p->size, blocksize);\r
-                       i++;\r
-               }\r
-               \r
-               xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");\r
-\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       gdb_send_error(connection, retval);\r
-                       return retval;\r
-               }\r
-                               \r
-               if (offset + length > pos)\r
-               {\r
-                       length = pos - offset;\r
-               }\r
-\r
-               char *t = malloc(length + 1);\r
-               t[0] = 'l';\r
-               memcpy(t + 1, xml + offset, length);\r
-               gdb_put_packet(connection, t, length + 1);\r
-               \r
-               free(t);\r
-               free(xml);\r
-               return ERROR_OK;\r
-       }\r
-       else if (strstr(packet, "qXfer:features:read:"))\r
-       {                \r
-               char *xml = NULL;\r
-               int size = 0;\r
-               int pos = 0;\r
-               int retval = ERROR_OK;\r
-               \r
-               int offset;\r
-               unsigned int length;\r
-               char *annex;\r
-               \r
-               /* skip command character */\r
-               packet += 20;\r
-               \r
-               if (decode_xfer_read(packet, &annex, &offset, &length) < 0)\r
-               {\r
-                       gdb_send_error(connection, 01);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               if (strcmp(annex, "target.xml") != 0)\r
-               {\r
-                       gdb_send_error(connection, 01);\r
-                       return ERROR_OK;\r
-               }\r
-                               \r
-               xml_printf(&retval, &xml, &pos, &size, \\r
-                       "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");\r
-                                       \r
-               if (retval != ERROR_OK)\r
-               {\r
-                       gdb_send_error(connection, retval);\r
-                       return retval;\r
-               }\r
-               \r
-               gdb_put_packet(connection, xml, strlen(xml) + 1);\r
-               \r
-               free(xml);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       gdb_put_packet(connection, "", 0);\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int packet_size)\r
-{\r
-       gdb_connection_t *gdb_connection = connection->priv;\r
-       gdb_service_t *gdb_service = connection->service->priv;\r
-       int result;\r
-\r
-       /* if flash programming disabled - send a empty reply */\r
-       \r
-       if (gdb_flash_program == 0)\r
-       {\r
-               gdb_put_packet(connection, "", 0);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (strstr(packet, "vFlashErase:"))\r
-       {\r
-               unsigned long addr;\r
-               unsigned long length;\r
-       \r
-               char *parse = packet + 12;\r
-               if (*parse == '\0')\r
-               {\r
-                       ERROR("incomplete vFlashErase packet received, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-\r
-               addr = strtoul(parse, &parse, 16);\r
-\r
-               if (*(parse++) != ',' || *parse == '\0')\r
-               {\r
-                       ERROR("incomplete vFlashErase packet received, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-\r
-               length = strtoul(parse, &parse, 16);\r
-\r
-               if (*parse != '\0')\r
-               {\r
-                       ERROR("incomplete vFlashErase packet received, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-               \r
-               /* assume all sectors need erasing - stops any problems\r
-                * when flash_write is called multiple times */\r
-               flash_set_dirty();\r
-               \r
-               /* perform any target specific operations before the erase */\r
-               target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_PROGRAM);\r
-               \r
-               /* perform erase */\r
-               if ((result = flash_erase_address_range(gdb_service->target, addr, length)) != ERROR_OK)\r
-               {\r
-                       /* GDB doesn't evaluate the actual error number returned,\r
-                        * treat a failed erase as an I/O error\r
-                        */\r
-                       gdb_send_error(connection, EIO);\r
-                       ERROR("flash_erase returned %i", result);\r
-               }\r
-               else\r
-                       gdb_put_packet(connection, "OK", 2);\r
-               \r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (strstr(packet, "vFlashWrite:"))\r
-       {\r
-               unsigned long addr;\r
-               unsigned long length;\r
-               char *parse = packet + 12;\r
-\r
-               if (*parse == '\0')\r
-               {\r
-                       ERROR("incomplete vFlashErase packet received, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-               addr = strtoul(parse, &parse, 16);\r
-               if (*(parse++) != ':')\r
-               {\r
-                       ERROR("incomplete vFlashErase packet received, dropping connection");\r
-                       return ERROR_SERVER_REMOTE_CLOSED;\r
-               }\r
-               length = packet_size - (parse - packet);\r
-               \r
-               /* create a new image if there isn't already one */\r
-               if (gdb_connection->vflash_image == NULL)\r
-               {\r
-                       gdb_connection->vflash_image = malloc(sizeof(image_t));\r
-                       image_open(gdb_connection->vflash_image, "", "build");\r
-               }\r
-\r
-               /* create new section with content from packet buffer */\r
-               image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (u8*)parse);\r
-\r
-               gdb_put_packet(connection, "OK", 2);\r
-\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (!strcmp(packet, "vFlashDone"))\r
-       {\r
-               u32 written;\r
-\r
-               /* process the flashing buffer. No need to erase as GDB\r
-                * always issues a vFlashErase first. */\r
-               if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, 0)) != ERROR_OK)\r
-               {\r
-                       if (result == ERROR_FLASH_DST_OUT_OF_BANK)\r
-                               gdb_put_packet(connection, "E.memtype", 9);\r
-                       else\r
-                               gdb_send_error(connection, EIO);\r
-                       }\r
-               else\r
-               {\r
-                       DEBUG("wrote %u bytes from vFlash image to flash", written);\r
-                       gdb_put_packet(connection, "OK", 2);\r
-               }\r
-               \r
-               image_close(gdb_connection->vflash_image);\r
-               free(gdb_connection->vflash_image);\r
-               gdb_connection->vflash_image = NULL;\r
-               \r
-               return ERROR_OK;\r
-       }\r
-\r
-       gdb_put_packet(connection, "", 0);\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_detach(connection_t *connection, target_t *target)\r
-{\r
-       switch( detach_mode )\r
-       {\r
-               case GDB_DETACH_RESUME:\r
-                       target->type->resume(target, 1, 0, 1, 0);\r
-                       break;\r
-               \r
-               case GDB_DETACH_RESET:\r
-                       target_process_reset(connection->cmd_ctx);\r
-                       break;\r
-               \r
-               case GDB_DETACH_HALT:\r
-                       target->type->halt(target);\r
-                       break;\r
-               \r
-               case GDB_DETACH_NOTHING:\r
-                       break;\r
-       }\r
-       \r
-       gdb_put_packet(connection, "OK", 2);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-static void gdb_log_callback(void *priv, const char *file, int line, \r
-               const char *function, const char *format, va_list args)\r
-{\r
-       connection_t *connection = priv;\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-       \r
-       if (gdb_con->busy)\r
-       {\r
-               /* do not reply this using the O packet */\r
-               return;\r
-       }\r
-\r
-       char *t = alloc_printf(format, args);\r
-       if (t == NULL)\r
-               return;\r
-       \r
-       gdb_output_con(connection, t); \r
-       \r
-       free(t);\r
-}\r
-\r
-int gdb_input_inner(connection_t *connection)\r
-{\r
-       gdb_service_t *gdb_service = connection->service->priv;\r
-       target_t *target = gdb_service->target;\r
-       char packet[GDB_BUFFER_SIZE];\r
-       int packet_size;\r
-       int retval;\r
-       gdb_connection_t *gdb_con = connection->priv;\r
-       static int extended_protocol = 0;\r
-\r
-       /* drain input buffer */\r
-       do\r
-       {\r
-               packet_size = GDB_BUFFER_SIZE-1;\r
-               if ((retval = gdb_get_packet(connection, packet, &packet_size)) != ERROR_OK)\r
-               {\r
-                       return retval;\r
-               }\r
-\r
-               /* terminate with zero */\r
-               packet[packet_size] = 0;\r
-\r
-               DEBUG("received packet: '%s'", packet);\r
-\r
-               if (packet_size > 0)\r
-               {\r
-                       retval = ERROR_OK;\r
-                       switch (packet[0])\r
-                       {\r
-                               case 'H':\r
-                                       /* Hct... -- set thread \r
-                                        * we don't have threads, send empty reply */\r
-                                       gdb_put_packet(connection, NULL, 0);\r
-                                       break;\r
-                               case 'q':\r
-                                       retval = gdb_query_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'g':\r
-                                       retval = gdb_get_registers_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'G':\r
-                                       retval = gdb_set_registers_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'p':\r
-                                       retval = gdb_get_register_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'P':\r
-                                       retval = gdb_set_register_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'm':\r
-                                       retval = gdb_read_memory_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'M':\r
-                                       retval = gdb_write_memory_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'z':\r
-                               case 'Z':\r
-                                       retval = gdb_breakpoint_watchpoint_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case '?':\r
-                                       gdb_last_signal_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'c':\r
-                               case 's':\r
-                                       {\r
-                                       /* We're running/stepping, in which case we can \r
-                                        * forward log output until the target is halted */\r
-                                               gdb_connection_t *gdb_con = connection->priv;\r
-                                               gdb_con->frontend_state = TARGET_RUNNING;\r
-                                               log_add_callback(gdb_log_callback, connection);\r
-                                               gdb_step_continue_packet(connection, target, packet, packet_size);\r
-                                       }\r
-                                       break;\r
-                               case 'v':\r
-                                       retval = gdb_v_packet(connection, target, packet, packet_size);\r
-                                       break;\r
-                               case 'D':\r
-                                       retval = gdb_detach(connection, target);\r
-                                       extended_protocol = 0;\r
-                                       break;\r
-                               case 'X':\r
-                                       if ((retval = gdb_write_memory_binary_packet(connection, target, packet, packet_size)) != ERROR_OK)\r
-                                               return retval;\r
-                                       break;\r
-                               case 'k':\r
-                                       if (extended_protocol != 0)\r
-                                               break;\r
-                                       gdb_put_packet(connection, "OK", 2);\r
-                                       return ERROR_SERVER_REMOTE_CLOSED;\r
-                               case '!':\r
-                                       /* handle extended remote protocol */\r
-                                       extended_protocol = 1;\r
-                                       gdb_put_packet(connection, "OK", 2);\r
-                                       break;\r
-                               case 'R':\r
-                                       /* handle extended restart packet */\r
-                                       target_process_reset(connection->cmd_ctx);\r
-                                       break;\r
-                               default:\r
-                                       /* ignore unkown packets */\r
-                                       DEBUG("ignoring 0x%2.2x packet", packet[0]);\r
-                                       gdb_put_packet(connection, NULL, 0);\r
-                                       break;\r
-                       }\r
-\r
-                       /* if a packet handler returned an error, exit input loop */\r
-                       if (retval != ERROR_OK)\r
-                               return retval;\r
-               }\r
-\r
-               if (gdb_con->ctrl_c)\r
-               {\r
-                       if (target->state == TARGET_RUNNING)\r
-                       {\r
-                               target->type->halt(target);\r
-                               gdb_con->ctrl_c = 0;\r
-                       }\r
-               }\r
-\r
-       } while (gdb_con->buf_cnt > 0);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_input(connection_t *connection)\r
-{\r
-       int retval = gdb_input_inner(connection);\r
-       if (retval == ERROR_SERVER_REMOTE_CLOSED)\r
-               return retval;\r
-       /* we'll recover from any other errors(e.g. temporary timeouts, etc.) */\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_init()\r
-{\r
-       gdb_service_t *gdb_service;\r
-       target_t *target = targets;\r
-       int i = 0;\r
-\r
-       if (!target)\r
-       {\r
-               WARNING("no gdb ports allocated as no target has been specified");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (gdb_port == 0)\r
-       {\r
-               WARNING("no gdb port specified, using default port 3333");\r
-               gdb_port = 3333;\r
-       }\r
-\r
-       while (target)\r
-       {\r
-               char service_name[8];\r
-\r
-               snprintf(service_name, 8, "gdb-%2.2i", i);\r
-\r
-               gdb_service = malloc(sizeof(gdb_service_t));\r
-               gdb_service->target = target;\r
-\r
-               add_service("gdb", CONNECTION_GDB, gdb_port + i, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);\r
-\r
-               DEBUG("gdb service for target %s at port %i", target->type->name, gdb_port + i);\r
-\r
-               i++;\r
-               target = target->next;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* daemon configuration command gdb_port */\r
-int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 0)\r
-               return ERROR_OK;\r
-\r
-       /* only if the port wasn't overwritten by cmdline */\r
-       if (gdb_port == 0)\r
-               gdb_port = strtoul(args[0], NULL, 0);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "resume") == 0)\r
-               {\r
-                       detach_mode = GDB_DETACH_RESUME;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "reset") == 0)\r
-               {\r
-                       detach_mode = GDB_DETACH_RESET;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "halt") == 0)\r
-               {\r
-                       detach_mode = GDB_DETACH_HALT;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "nothing") == 0)\r
-               {\r
-                       detach_mode = GDB_DETACH_NOTHING;\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       \r
-       WARNING("invalid gdb_detach configuration directive: %s", args[0]);\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "enable") == 0)\r
-               {\r
-                       gdb_use_memory_map = 1;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "disable") == 0)\r
-               {\r
-                       gdb_use_memory_map = 0;\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       \r
-       WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "enable") == 0)\r
-               {\r
-                       gdb_flash_program = 1;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "disable") == 0)\r
-               {\r
-                       gdb_flash_program = 0;\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       \r
-       WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_gdb_report_data_abort_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "enable") == 0)\r
-               {\r
-                       gdb_report_data_abort = 1;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "disable") == 0)\r
-               {\r
-                       gdb_report_data_abort = 0;\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       \r
-       WARNING("invalid gdb_report_data_abort configuration directive: %s", args[0]);\r
-       return ERROR_OK;\r
-}\r
-\r
-int gdb_register_commands(command_context_t *command_context)\r
-{\r
-       register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,\r
-                       COMMAND_CONFIG, "");\r
-       register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,\r
-                       COMMAND_CONFIG, "");\r
-       register_command(command_context, NULL, "gdb_memory_map", handle_gdb_memory_map_command,\r
-                       COMMAND_CONFIG, "");\r
-       register_command(command_context, NULL, "gdb_flash_program", handle_gdb_flash_program_command,\r
-                       COMMAND_CONFIG, "");\r
-       register_command(command_context, NULL, "gdb_report_data_abort", handle_gdb_report_data_abort_command,\r
-                       COMMAND_CONFIG, "");\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "gdb_server.h"
+
+#include "server.h"
+#include "log.h"
+#include "binarybuffer.h"
+#include "jtag.h"
+#include "breakpoints.h"
+#include "flash.h"
+#include "target_request.h"
+#include "configuration.h"
+
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#if 0
+#define _DEBUG_GDB_IO_
+#endif
+
+static unsigned short gdb_port;
+static const char *DIGITS = "0123456789abcdef";
+
+static void gdb_log_callback(void *priv, const char *file, int line, 
+               const char *function, const char *format, va_list args);
+
+enum gdb_detach_mode
+{
+       GDB_DETACH_RESUME,
+       GDB_DETACH_RESET,
+       GDB_DETACH_HALT,
+       GDB_DETACH_NOTHING
+};
+
+/* target behaviour on gdb detach */
+enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
+
+/* set if we are sending a memory map to gdb
+ * via qXfer:memory-map:read packet */
+int gdb_use_memory_map = 0;
+int gdb_flash_program = 0;
+
+/* if set, data aborts cause an error to be reported in memory read packets
+ * see the code in gdb_read_memory_packet() for further explanations */
+int gdb_report_data_abort = 0;
+
+int gdb_last_signal(target_t *target)
+{
+       switch (target->debug_reason)
+       {
+               case DBG_REASON_DBGRQ:
+                       return 0x2; /* SIGINT */
+               case DBG_REASON_BREAKPOINT:
+               case DBG_REASON_WATCHPOINT:
+               case DBG_REASON_WPTANDBKPT:
+                       return 0x05; /* SIGTRAP */
+               case DBG_REASON_SINGLESTEP:
+                       return 0x05; /* SIGTRAP */
+               case DBG_REASON_NOTHALTED:
+                       return 0x0; /* no signal... shouldn't happen */
+               default:
+                       ERROR("BUG: undefined debug reason");
+                       exit(-1);
+       }
+}
+
+int gdb_get_char(connection_t *connection, int* next_char)
+{
+       gdb_connection_t *gdb_con = connection->priv;
+
+#ifdef _DEBUG_GDB_IO_
+       char *debug_buffer;
+#endif
+
+       if (gdb_con->buf_cnt-- > 0)
+       {
+               *next_char = *(gdb_con->buf_p++);
+               if (gdb_con->buf_cnt > 0)
+                       connection->input_pending = 1;
+               else
+                       connection->input_pending = 0;
+
+#ifdef _DEBUG_GDB_IO_
+               DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
+#endif
+
+               return ERROR_OK;
+       }
+
+       for (;;)
+       {
+#ifndef _WIN32
+               /* a non-blocking socket will block if there is 0 bytes available on the socket,
+                * but return with as many bytes as are available immediately
+                */
+               struct timeval tv;
+               fd_set read_fds;
+               
+               FD_ZERO(&read_fds);
+               FD_SET(connection->fd, &read_fds);
+               
+               tv.tv_sec = 1;
+               tv.tv_usec = 0;
+               if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
+               {
+                       /* This can typically be because a "monitor" command took too long
+                        * before printing any progress messages
+                        */
+                       return ERROR_GDB_TIMEOUT; 
+               }
+#endif
+               gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
+               if (gdb_con->buf_cnt > 0)
+               {
+                       break;
+               }
+               if (gdb_con->buf_cnt == 0)
+               {
+                       gdb_con->closed = 1;
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+
+#ifdef _WIN32
+               errno = WSAGetLastError();
+
+               switch(errno)
+               {
+                       case WSAEWOULDBLOCK:
+                               usleep(1000);
+                               break;
+                       case WSAECONNABORTED:
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       case WSAECONNRESET:
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       default:
+                               ERROR("read: %d", errno);
+                               exit(-1);
+               }
+#else
+               switch(errno)
+               {
+                       case EAGAIN:
+                               usleep(1000);
+                               break;
+                       case ECONNABORTED:
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       case ECONNRESET:
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       default:
+                               ERROR("read: %s", strerror(errno));
+                               return ERROR_SERVER_REMOTE_CLOSED;
+               }
+#endif
+       }
+
+#ifdef _DEBUG_GDB_IO_
+       debug_buffer = malloc(gdb_con->buf_cnt + 1);
+       memcpy(debug_buffer, gdb_con->buffer, gdb_con->buf_cnt);
+       debug_buffer[gdb_con->buf_cnt] = 0;
+       DEBUG("received '%s'", debug_buffer);
+       free(debug_buffer);
+#endif
+
+       gdb_con->buf_p = gdb_con->buffer;
+       gdb_con->buf_cnt--;
+       *next_char = *(gdb_con->buf_p++);
+       if (gdb_con->buf_cnt > 0)
+               connection->input_pending = 1;
+       else
+               connection->input_pending = 0;  
+#ifdef _DEBUG_GDB_IO_
+       DEBUG("returned char '%c' (0x%2.2x)", *next_char, *next_char);
+#endif
+
+       return ERROR_OK;
+}
+
+int gdb_putback_char(connection_t *connection, int last_char)
+{
+       gdb_connection_t *gdb_con = connection->priv;
+
+       if (gdb_con->buf_p > gdb_con->buffer)
+       {
+               *(--gdb_con->buf_p) = last_char;
+               gdb_con->buf_cnt++;
+       }
+       else
+       {
+               ERROR("BUG: couldn't put character back");      
+       }
+
+       return ERROR_OK;
+}
+
+/* The only way we can detect that the socket is closed is the first time
+ * we write to it, we will fail. Subsequent write operations will
+ * succeed. Shudder! */
+int gdb_write(connection_t *connection, void *data, int len)
+{
+       gdb_connection_t *gdb_con = connection->priv;
+       if (gdb_con->closed)
+               return ERROR_SERVER_REMOTE_CLOSED;
+
+       if (write_socket(connection->fd, data, len) == len)
+       {
+               return ERROR_OK;
+       }
+       gdb_con->closed = 1;
+       return ERROR_SERVER_REMOTE_CLOSED;
+}
+
+int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
+{
+       int i;
+       unsigned char my_checksum = 0;
+#ifdef _DEBUG_GDB_IO_
+       char *debug_buffer;
+#endif
+       int reply;
+       int retval;
+       gdb_connection_t *gdb_con = connection->priv;
+
+       for (i = 0; i < len; i++)
+               my_checksum += buffer[i];
+
+       while (1)
+       {
+#ifdef _DEBUG_GDB_IO_
+               debug_buffer = malloc(len + 1);
+               memcpy(debug_buffer, buffer, len);
+               debug_buffer[len] = 0;
+               DEBUG("sending packet '$%s#%2.2x'", debug_buffer, my_checksum);
+               free(debug_buffer);
+#endif
+#if 0
+               char checksum[3];
+               gdb_write(connection, "$", 1);
+               if (len > 0)
+                       gdb_write(connection, buffer, len);
+               gdb_write(connection, "#", 1);
+               
+               snprintf(checksum, 3, "%2.2x", my_checksum);
+               
+               gdb_write(connection, checksum, 2);
+#else
+               void *allocated = NULL;
+               char stackAlloc[1024];
+               char *t = stackAlloc;
+               int totalLen = 1 + len + 1 + 2;
+               if (totalLen > sizeof(stackAlloc))
+               {
+                       allocated = malloc(totalLen);
+                       t = allocated;
+                       if (allocated == NULL)
+                       {
+                               ERROR("Ran out of memory trying to reply packet %d\n", totalLen);
+                               exit(-1);
+                       }
+               }
+               t[0] = '$';
+               memcpy(t + 1, buffer, len);
+               t[1 + len] = '#';
+               t[1 + len + 1] = DIGITS[(my_checksum >> 4) & 0xf];
+               t[1 + len + 2] = DIGITS[my_checksum & 0xf];
+               
+               gdb_write(connection, t, totalLen);
+               
+               if (allocated)
+               {
+                       free(allocated);
+               }
+#endif
+               if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
+                       return retval;
+
+               if (reply == '+')
+                       break;
+               else if (reply == '-')
+               {
+                       /* Stop sending output packets for now */
+                       log_remove_callback(gdb_log_callback, connection);
+                       WARNING("negative reply, retrying");
+               }
+               else if (reply == 0x3)
+               {
+                       gdb_con->ctrl_c = 1;
+                       if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
+                               return retval;
+                       if (reply == '+')
+                               break;
+                       else if (reply == '-')
+                       {
+                               /* Stop sending output packets for now */
+                               log_remove_callback(gdb_log_callback, connection);
+                               WARNING("negative reply, retrying");
+                       }
+                       else
+                       {
+                               ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       }
+               }
+               else
+               {
+                       ERROR("unknown character 0x%2.2x in reply, dropping connection", reply);
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+       }
+       if (gdb_con->closed)
+               return ERROR_SERVER_REMOTE_CLOSED;
+
+       return ERROR_OK;
+}
+
+int gdb_put_packet(connection_t *connection, char *buffer, int len)
+{
+       gdb_connection_t *gdb_con = connection->priv;
+       gdb_con->busy = 1;
+       int retval = gdb_put_packet_inner(connection, buffer, len);
+       gdb_con->busy = 0;
+       return retval;
+}
+
+int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
+{
+       int character;
+       int count = 0;
+       int retval;
+       char checksum[3];
+       unsigned char my_checksum = 0;
+       gdb_connection_t *gdb_con = connection->priv;
+
+       while (1)
+       {
+               do
+               {
+                       if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
+                               return retval;
+
+#ifdef _DEBUG_GDB_IO_
+                       DEBUG("character: '%c'", character);
+#endif
+
+                       switch (character)
+                       {
+                               case '$':
+                                       break;
+                               case '+':
+                                       WARNING("acknowledgment received, but no packet pending");
+                                       break;
+                               case '-':
+                                       WARNING("negative acknowledgment, but no packet pending");
+                                       break;
+                               case 0x3:
+                                       gdb_con->ctrl_c = 1;
+                                       *len = 0;
+                                       return ERROR_OK;
+                               default:
+                                       WARNING("ignoring character 0x%x", character);
+                                       break;
+                       }
+               } while (character != '$');
+
+               my_checksum = 0;
+               
+               count = 0;
+               gdb_connection_t *gdb_con = connection->priv;
+               for (;;)
+               {
+                       /* The common case is that we have an entire packet with no escape chars.
+                        * We need to leave at least 2 bytes in the buffer to have
+                        * gdb_get_char() update various bits and bobs correctly. 
+                        */
+                       if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt+count) < *len))
+                       {
+                               /* The compiler will struggle a bit with constant propagation and
+                                * aliasing, so we help it by showing that these values do not
+                                * change inside the loop 
+                                */ 
+                               int i;
+                               char *buf = gdb_con->buf_p;
+                               int run = gdb_con->buf_cnt - 2;
+                               i = 0;
+                               int done = 0;
+                               while (i < run)
+                               {
+                                       character = *buf++;
+                                       i++;
+                                       if (character == '#')
+                                       {
+                                               /* Danger! character can be '#' when esc is 
+                                                * used so we need an explicit boolean for done here.
+                                                */
+                                               done = 1;
+                                               break;
+                                       }
+                                       
+                                       if (character == '}')
+                                       {
+                                               /* data transmitted in binary mode (X packet)
+                                                * uses 0x7d as escape character */
+                                               my_checksum += character & 0xff;
+                                               character = *buf++;
+                                               i++;
+                                               my_checksum += character & 0xff;
+                                               buffer[count++] = (character ^ 0x20) & 0xff;
+                                       } else
+                                       {
+                                               my_checksum += character & 0xff;
+                                               buffer[count++] = character & 0xff;
+                                       }
+                               }
+                               gdb_con->buf_p += i;
+                               gdb_con->buf_cnt -= i;
+                               if (done) 
+                                       break;
+                       } 
+                       if (count > *len)
+                       {
+                               ERROR("packet buffer too small");
+                               return ERROR_GDB_BUFFER_TOO_SMALL;
+                       }
+                       
+                       if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
+                               return retval;
+
+                       if (character == '#')
+                               break;
+
+                       if (character == '}')
+                       {
+                               /* data transmitted in binary mode (X packet)
+                                * uses 0x7d as escape character */
+                               my_checksum += character & 0xff;
+                               if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
+                                       return retval;
+                               my_checksum += character & 0xff;
+                               buffer[count++] = (character ^ 0x20) & 0xff;
+                       }
+                       else
+                       {
+                               my_checksum += character & 0xff;
+                               buffer[count++] = character & 0xff;
+                       }
+
+               }
+
+               *len = count;
+
+               if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
+                       return retval;
+               checksum[0] = character;
+               if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
+                       return retval;
+               checksum[1] = character;
+               checksum[2] = 0;
+
+               if (my_checksum == strtoul(checksum, NULL, 16))
+               {
+                       gdb_write(connection, "+", 1);
+                       break;
+               }
+
+               WARNING("checksum error, requesting retransmission");
+               gdb_write(connection, "-", 1);
+       }
+       if (gdb_con->closed)
+               return ERROR_SERVER_REMOTE_CLOSED;
+
+       return ERROR_OK;
+}
+
+int gdb_get_packet(connection_t *connection, char *buffer, int *len)
+{
+       gdb_connection_t *gdb_con = connection->priv;
+       gdb_con->busy = 1;
+       int retval = gdb_get_packet_inner(connection, buffer, len);
+       gdb_con->busy = 0;
+       return retval;
+}
+       
+int gdb_output_con(connection_t *connection, char* line)
+{
+       char *hex_buffer;
+       int i, bin_size;
+
+       bin_size = strlen(line);
+
+       hex_buffer = malloc(bin_size*2 + 4);
+
+       hex_buffer[0] = 'O';
+       for (i=0; i<bin_size; i++)
+               snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]);
+       hex_buffer[bin_size*2+1] = '0';
+       hex_buffer[bin_size*2+2] = 'a';
+       hex_buffer[bin_size*2+3] = 0x0;
+
+       gdb_put_packet(connection, hex_buffer, bin_size*2 + 3);
+
+       free(hex_buffer);
+       return ERROR_OK;
+}
+
+int gdb_output(struct command_context_s *context, char* line)
+{
+       /* this will be dumped to the log and also sent as an O packet if possible */
+       USER(line); 
+       return ERROR_OK;
+}
+
+int gdb_program_handler(struct target_s *target, enum target_event event, void *priv)
+{
+       FILE *script;
+       struct command_context_s *cmd_ctx = priv;
+       
+       if (target->gdb_program_script)
+       {
+               script = open_file_from_path(cmd_ctx, target->gdb_program_script, "r");
+               if (!script)
+               {
+                       ERROR("couldn't open script file %s", target->gdb_program_script);
+                               return ERROR_OK;
+               }
+
+               INFO("executing gdb_program script '%s'", target->gdb_program_script);
+               command_run_file(cmd_ctx, script, COMMAND_EXEC);
+               fclose(script);
+               
+               jtag_execute_queue();
+       }
+       
+       return ERROR_OK;
+}
+
+int gdb_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)
+{
+       connection_t *connection = priv;
+       gdb_connection_t *gdb_connection = connection->priv;
+       char sig_reply[4];
+       int signal;
+
+       switch (event)
+       {
+               case TARGET_EVENT_HALTED:
+                       /* In the GDB protocol when we are stepping or coninuing execution,
+                        * we have a lingering reply. Upon receiving a halted event 
+                        * when we have that lingering packet, we reply to the original
+                        * step or continue packet.
+                        * 
+                        * Executing monitor commands can bring the target in and
+                        * out of the running state so we'll see lots of TARGET_EVENT_XXX
+                        * that are to be ignored.
+                        */
+                       if (gdb_connection->frontend_state == TARGET_RUNNING)
+                       {
+                               /* stop forwarding log packets! */
+                               log_remove_callback(gdb_log_callback, connection);
+                               
+                               if (gdb_connection->ctrl_c)
+                               {
+                                       signal = 0x2;
+                                       gdb_connection->ctrl_c = 0;
+                               }
+                               else
+                               {
+                                       signal = gdb_last_signal(target);
+                               }
+
+                               snprintf(sig_reply, 4, "T%2.2x", signal);
+                               gdb_put_packet(connection, sig_reply, 3);
+                               gdb_connection->frontend_state = TARGET_HALTED;
+                       }
+                       break;
+               case TARGET_EVENT_GDB_PROGRAM:
+                       gdb_program_handler(target, event, connection->cmd_ctx);
+                       break;
+               default:
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int gdb_new_connection(connection_t *connection)
+{
+       gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t));
+       gdb_service_t *gdb_service = connection->service->priv;
+       int retval;
+       int initial_ack;
+
+       connection->priv = gdb_connection;
+
+       /* initialize gdb connection information */
+       gdb_connection->buf_p = gdb_connection->buffer;
+       gdb_connection->buf_cnt = 0;
+       gdb_connection->ctrl_c = 0;
+       gdb_connection->frontend_state = TARGET_HALTED;
+       gdb_connection->vflash_image = NULL;
+       gdb_connection->closed = 0;
+       gdb_connection->busy = 0;
+       
+       /* output goes through gdb connection */
+       command_set_output_handler(connection->cmd_ctx, gdb_output, connection);
+
+       /* register callback to be informed about target events */
+       target_register_event_callback(gdb_target_callback_event_handler, connection);  
+
+       /* a gdb session just attached, put the target in halt mode */
+       if (((retval = gdb_service->target->type->halt(gdb_service->target)) != ERROR_OK) &&
+                       (retval != ERROR_TARGET_ALREADY_HALTED))
+       {
+               ERROR("error(%d) when trying to halt target, falling back to \"reset halt\"", retval);
+               command_run_line(connection->cmd_ctx, "reset halt");
+       }
+
+       /* This will time out after 1 second */
+       command_run_line(connection->cmd_ctx, "wait_halt 1");
+
+       /* remove the initial ACK from the incoming buffer */
+       if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
+               return retval;
+
+       if (initial_ack != '+')
+               gdb_putback_char(connection, initial_ack);
+
+       return ERROR_OK;
+}
+
+int gdb_connection_closed(connection_t *connection)
+{
+       gdb_service_t *gdb_service = connection->service->priv;
+       gdb_connection_t *gdb_connection = connection->priv;
+
+       /* see if an image built with vFlash commands is left */
+       if (gdb_connection->vflash_image)
+       {
+               image_close(gdb_connection->vflash_image);
+               free(gdb_connection->vflash_image);
+               gdb_connection->vflash_image = NULL;
+       }
+
+       /* if this connection registered a debug-message receiver delete it */
+       delete_debug_msg_receiver(connection->cmd_ctx, gdb_service->target);
+       
+       if (connection->priv)
+       {
+               free(connection->priv);
+               connection->priv = NULL;
+       }
+       else
+       {
+               ERROR("BUG: connection->priv == NULL");
+       }
+
+       target_unregister_event_callback(gdb_target_callback_event_handler, connection);
+       log_remove_callback(gdb_log_callback, connection);
+
+       return ERROR_OK;
+}
+
+void gdb_send_error(connection_t *connection, u8 the_error)
+{
+       char err[4];
+       snprintf(err, 4, "E%2.2X", the_error );
+       gdb_put_packet(connection, err, 3);
+}
+
+int gdb_last_signal_packet(connection_t *connection, target_t *target, char* packet, int packet_size)
+{
+       char sig_reply[4];
+       int signal;
+
+       signal = gdb_last_signal(target);
+
+       snprintf(sig_reply, 4, "S%2.2x", signal);
+       gdb_put_packet(connection, sig_reply, 3);
+
+       return ERROR_OK;
+}
+
+/* Convert register to string of bits. NB! The # of bits in the
+ * register might be non-divisible by 8(a byte), in which
+ * case an entire byte is shown. */
+void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg)
+{
+       int i;
+
+       u8 *buf;
+       int buf_len;
+       buf = reg->value;
+       buf_len = CEIL(reg->size, 8); 
+
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+       {
+               for (i = 0; i < buf_len; i++)
+               {
+                       tstr[i*2]   = DIGITS[(buf[i]>>4) & 0xf];
+                       tstr[i*2+1] = DIGITS[buf[i]&0xf];
+               }
+       }
+       else
+       {
+               for (i = 0; i < buf_len; i++)
+               {
+                       tstr[(buf_len-1-i)*2]   = DIGITS[(buf[i]>>4)&0xf];
+                       tstr[(buf_len-1-i)*2+1] = DIGITS[buf[i]&0xf];
+               }
+       }       
+}
+
+void gdb_target_to_str(target_t *target, char *tstr, char *str)
+{
+       int str_len = strlen(tstr);
+       int i;
+
+       if (str_len % 2)
+       {
+               ERROR("BUG: gdb value with uneven number of characters encountered");
+               exit(-1);
+       }
+
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+       {
+               for (i = 0; i < str_len; i+=2)
+               {
+                       str[str_len - i - 1] = tstr[i + 1];
+                       str[str_len - i - 2] = tstr[i];
+               }
+       }
+       else
+       {
+               for (i = 0; i < str_len; i++)
+               {
+                       str[i] = tstr[i];
+               }
+       }       
+}
+
+int gdb_get_registers_packet(connection_t *connection, target_t *target, char* packet, int packet_size)
+{
+       reg_t **reg_list;
+       int reg_list_size;
+       int retval;
+       int reg_packet_size = 0;
+       char *reg_packet;
+       char *reg_packet_p;
+       int i;
+
+#ifdef _DEBUG_GDB_IO_
+       DEBUG("-");
+#endif
+
+       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       {
+               switch (retval)
+               {
+                       case ERROR_TARGET_NOT_HALTED:
+                               ERROR("gdb requested registers but we're not halted, dropping connection");
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       default:
+                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */
+                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
+                               exit(-1);
+               }
+       }
+
+       for (i = 0; i < reg_list_size; i++)
+       {
+               reg_packet_size += reg_list[i]->size;
+       }
+
+       reg_packet = malloc(CEIL(reg_packet_size, 8) * 2);
+       reg_packet_p = reg_packet;
+
+       for (i = 0; i < reg_list_size; i++)
+       {
+               gdb_str_to_target(target, reg_packet_p, reg_list[i]);
+               reg_packet_p += CEIL(reg_list[i]->size, 8) * 2;
+       }
+
+#ifdef _DEBUG_GDB_IO_
+       {
+               char *reg_packet_p;
+               reg_packet_p = strndup(reg_packet, CEIL(reg_packet_size, 8) * 2);
+               DEBUG("reg_packet: %s", reg_packet_p);
+               free(reg_packet_p);
+       }
+#endif
+
+       gdb_put_packet(connection, reg_packet, CEIL(reg_packet_size, 8) * 2);
+       free(reg_packet);
+
+       free(reg_list);
+
+       return ERROR_OK;
+}
+
+int gdb_set_registers_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       int i;
+       reg_t **reg_list;
+       int reg_list_size;
+       int retval;
+       char *packet_p;
+
+#ifdef _DEBUG_GDB_IO_
+       DEBUG("-");
+#endif
+
+       /* skip command character */
+       packet++;
+       packet_size--;
+
+       if (packet_size % 2)
+       {
+               WARNING("GDB set_registers packet with uneven characters received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       {
+               switch (retval)
+               {
+                       case ERROR_TARGET_NOT_HALTED:
+                               ERROR("gdb tried to registers but we're not halted, dropping connection");
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       default:
+                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */
+                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
+                               exit(-1);
+               }
+       }
+
+       packet_p = packet;
+       for (i = 0; i < reg_list_size; i++)
+       {
+               u8 *bin_buf;
+               char *hex_buf;
+               reg_arch_type_t *arch_type;
+
+               /* convert from GDB-string (target-endian) to hex-string (big-endian) */
+               hex_buf = malloc(CEIL(reg_list[i]->size, 8) * 2);
+               gdb_target_to_str(target, packet_p, hex_buf);
+
+               /* convert hex-string to binary buffer */
+               bin_buf = malloc(CEIL(reg_list[i]->size, 8));
+               str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16);
+
+               /* get register arch_type, and call set method */       
+               arch_type = register_get_arch_type(reg_list[i]->arch_type);
+               if (arch_type == NULL)
+               {
+                       ERROR("BUG: encountered unregistered arch type");
+                       exit(-1);
+               }
+               arch_type->set(reg_list[i], bin_buf);
+
+               /* advance packet pointer */            
+               packet_p += (CEIL(reg_list[i]->size, 8) * 2);
+
+               free(bin_buf);
+               free(hex_buf);
+       }
+
+       /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */ 
+       free(reg_list);
+
+       gdb_put_packet(connection, "OK", 2);
+
+       return ERROR_OK;
+}
+
+int gdb_get_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       char *reg_packet;
+       int reg_num = strtoul(packet + 1, NULL, 16);
+       reg_t **reg_list;
+       int reg_list_size;
+       int retval;
+
+#ifdef _DEBUG_GDB_IO_
+       DEBUG("-");
+#endif
+
+       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       {
+               switch (retval)
+               {
+                       case ERROR_TARGET_NOT_HALTED:
+                               ERROR("gdb requested registers but we're not halted, dropping connection");
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       default:
+                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */
+                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
+                               exit(-1);
+               }
+       }
+
+       if (reg_list_size <= reg_num)
+       {
+               ERROR("gdb requested a non-existing register");
+               exit(-1);
+       }
+
+       reg_packet = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);
+
+       gdb_str_to_target(target, reg_packet, reg_list[reg_num]);
+
+       gdb_put_packet(connection, reg_packet, CEIL(reg_list[reg_num]->size, 8) * 2);
+
+       free(reg_list);
+       free(reg_packet);
+
+       return ERROR_OK;
+}
+
+int gdb_set_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       char *separator;
+       char *hex_buf;
+       u8 *bin_buf;
+       int reg_num = strtoul(packet + 1, &separator, 16);
+       reg_t **reg_list;
+       int reg_list_size;
+       int retval;
+       reg_arch_type_t *arch_type;
+
+       DEBUG("-");
+
+       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       {
+               switch (retval)
+               {
+                       case ERROR_TARGET_NOT_HALTED:
+                               ERROR("gdb tried to set a register but we're not halted, dropping connection");
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       default:
+                               /* this is a bug condition - get_gdb_reg_list() may not return any other error */
+                               ERROR("BUG: unexpected error returned by get_gdb_reg_list()");
+                               exit(-1);
+               }
+       }
+
+       if (reg_list_size < reg_num)
+       {
+               ERROR("gdb requested a non-existing register");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       if (*separator != '=')
+       {
+               ERROR("GDB 'set register packet', but no '=' following the register number");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       /* convert from GDB-string (target-endian) to hex-string (big-endian) */
+       hex_buf = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);
+       gdb_target_to_str(target, separator + 1, hex_buf);
+
+       /* convert hex-string to binary buffer */
+       bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8));
+       str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16);
+
+       /* get register arch_type, and call set method */       
+       arch_type = register_get_arch_type(reg_list[reg_num]->arch_type);
+       if (arch_type == NULL)
+       {
+               ERROR("BUG: encountered unregistered arch type");
+               exit(-1);
+       }
+       arch_type->set(reg_list[reg_num], bin_buf);
+
+       gdb_put_packet(connection, "OK", 2);
+
+       free(bin_buf);
+       free(hex_buf);
+       free(reg_list);
+
+       return ERROR_OK;
+}
+
+int gdb_memory_packet_error(connection_t *connection, int retval)
+{
+       switch (retval)
+       {
+               case ERROR_TARGET_NOT_HALTED:
+                       ERROR("gdb tried to read memory but we're not halted, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               case ERROR_TARGET_DATA_ABORT:
+                       gdb_send_error(connection, EIO);
+                       break;
+               case ERROR_TARGET_TRANSLATION_FAULT:
+                       gdb_send_error(connection, EFAULT);
+                       break;
+               case ERROR_TARGET_UNALIGNED_ACCESS:
+                       gdb_send_error(connection, EFAULT);
+                       break;
+               default:
+                       /* This could be that the target reset itself. */
+                       ERROR("unexpected error %i. Dropping connection.", retval);
+                       return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       return ERROR_OK;
+}
+
+/* We don't have to worry about the default 2 second timeout for GDB packets,
+ * because GDB breaks up large memory reads into smaller reads.
+ * 
+ * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????
+ */
+int gdb_read_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       char *separator;
+       u32 addr = 0;
+       u32 len = 0;
+
+       u8 *buffer;
+       char *hex_buffer;
+
+       int retval = ERROR_OK;
+
+       /* skip command character */
+       packet++;
+
+       addr = strtoul(packet, &separator, 16);
+
+       if (*separator != ',')
+       {
+               ERROR("incomplete read memory packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       len = strtoul(separator+1, NULL, 16);
+
+       buffer = malloc(len);
+
+       DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
+
+       retval = target_read_buffer(target, addr, len, buffer);
+
+       if ((retval == ERROR_TARGET_DATA_ABORT) && (!gdb_report_data_abort))
+       {
+               /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
+                * At some point this might be fixed in GDB, in which case this code can be removed.
+                * 
+                * OpenOCD developers are acutely aware of this problem, but there is nothing
+                * gained by involving the user in this problem that hopefully will get resolved
+                * eventually
+                * 
+                * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395
+                *
+                * For now, the default is to fix up things to make current GDB versions work.
+                * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command.
+                */
+               memset(buffer, 0, len);
+               retval = ERROR_OK;
+       }
+
+       if (retval == ERROR_OK)
+       {
+               hex_buffer = malloc(len * 2 + 1);
+
+               int i;
+               for (i = 0; i < len; i++)
+               {
+                       u8 t = buffer[i];
+                       hex_buffer[2 * i] = DIGITS[(t >> 4) & 0xf];
+                       hex_buffer[2 * i + 1] = DIGITS[t & 0xf];
+               }
+
+               gdb_put_packet(connection, hex_buffer, len * 2);
+
+               free(hex_buffer);
+       }
+       else
+       {
+               retval = gdb_memory_packet_error(connection, retval);
+       }
+
+       free(buffer);
+
+       return retval;
+}
+
+int gdb_write_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       char *separator;
+       u32 addr = 0;
+       u32 len = 0;
+
+       u8 *buffer;
+
+       int i;
+       int retval;
+
+       /* skip command character */
+       packet++;
+
+       addr = strtoul(packet, &separator, 16);
+
+       if (*separator != ',')
+       {
+               ERROR("incomplete write memory packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       len = strtoul(separator+1, &separator, 16);
+
+       if (*(separator++) != ':')
+       {
+               ERROR("incomplete write memory packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       buffer = malloc(len);
+
+       DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
+
+       for (i=0; i<len; i++)
+       {
+               u32 tmp;
+               sscanf(separator + 2*i, "%2x", &tmp);
+               buffer[i] = tmp;
+       }
+
+       retval = target_write_buffer(target, addr, len, buffer);
+
+       if (retval == ERROR_OK)
+       {
+               gdb_put_packet(connection, "OK", 2);
+       }
+       else
+       {
+               if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
+                       return retval; 
+       }
+
+       free(buffer);
+
+       return ERROR_OK;
+}
+
+int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       char *separator;
+       u32 addr = 0;
+       u32 len = 0;
+
+       int retval;
+
+       /* skip command character */
+       packet++;
+
+       addr = strtoul(packet, &separator, 16);
+
+       if (*separator != ',')
+       {
+               ERROR("incomplete write memory binary packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       len = strtoul(separator+1, &separator, 16);
+
+       if (*(separator++) != ':')
+       {
+               ERROR("incomplete write memory binary packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       retval = ERROR_OK;
+       if (len)
+       {
+               DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
+
+               retval = target_write_buffer(target, addr, len, (u8*)separator);
+       }
+
+       if (retval == ERROR_OK)
+       {
+               gdb_put_packet(connection, "OK", 2);
+       }
+       else
+       {
+               if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
+                       return retval; 
+       }
+
+       return ERROR_OK;
+}
+
+void gdb_step_continue_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       int current = 0;
+       u32 address = 0x0;
+
+       DEBUG("-");
+
+       if (packet_size > 1)
+       {
+               packet[packet_size] = 0;
+               address = strtoul(packet + 1, NULL, 16);
+       }
+       else
+       {
+               current = 1;
+       }
+
+       if (packet[0] == 'c')
+       {
+               DEBUG("continue");
+               target->type->resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
+       }
+       else if (packet[0] == 's')
+       {
+               DEBUG("step");
+               target->type->step(target, current, address, 0); /* step at current or address, don't handle breakpoints */
+       }
+}
+
+int gdb_bp_wp_packet_error(connection_t *connection, int retval)
+{
+       switch (retval)
+       {
+               case ERROR_TARGET_NOT_HALTED:
+                       ERROR("gdb tried to set a breakpoint but we're not halted, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+                       break;
+               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+                       gdb_send_error(connection, EBUSY);
+                       break;
+               default:
+                       ERROR("BUG: unexpected error %i", retval);
+                       exit(-1);
+       }
+
+       return ERROR_OK;
+}
+
+int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       int type;
+       enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
+       enum watchpoint_rw wp_type;
+       u32 address;
+       u32 size;
+       char *separator;
+       int retval;
+
+       DEBUG("-");
+
+       type = strtoul(packet + 1, &separator, 16);
+
+       if (type == 0)  /* memory breakpoint */
+               bp_type = BKPT_SOFT;
+       else if (type == 1) /* hardware breakpoint */
+               bp_type = BKPT_HARD;
+       else if (type == 2) /* write watchpoint */
+               wp_type = WPT_WRITE;
+       else if (type == 3) /* read watchpoint */
+               wp_type = WPT_READ;
+       else if (type == 4) /* access watchpoint */
+               wp_type = WPT_ACCESS;
+
+       if (*separator != ',')
+       {
+               ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       address = strtoul(separator+1, &separator, 16);
+
+       if (*separator != ',')
+       {
+               ERROR("incomplete breakpoint/watchpoint packet received, dropping connection");
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       size = strtoul(separator+1, &separator, 16);
+
+       switch (type)
+       {
+               case 0:
+               case 1:
+                       if (packet[0] == 'Z')
+                       {
+                               if ((retval = breakpoint_add(target, address, size, bp_type)) != ERROR_OK)
+                               {
+                                       if ((retval = gdb_bp_wp_packet_error(connection, retval)) != ERROR_OK)
+                                               return retval;
+                               }
+                               else
+                               {
+                                       gdb_put_packet(connection, "OK", 2);
+                               }
+                       }
+                       else
+                       {
+                               breakpoint_remove(target, address);
+                               gdb_put_packet(connection, "OK", 2);
+                       }
+                       break;
+               case 2:
+               case 3:
+               case 4:
+               {
+                       if (packet[0] == 'Z')
+                       {
+                               if ((retval = watchpoint_add(target, address, size, type-2, 0, 0xffffffffu)) != ERROR_OK)
+                               {
+                                       if ((retval = gdb_bp_wp_packet_error(connection, retval)) != ERROR_OK)
+                                               return retval;
+                               }
+                               else
+                               {
+                                       gdb_put_packet(connection, "OK", 2);
+                               }
+                       }
+                       else
+                       {
+                               watchpoint_remove(target, address);
+                               gdb_put_packet(connection, "OK", 2);
+                       }
+                       break;
+               }
+               default:
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+/* print out a string and allocate more space as needed, mainly used for XML at this point */
+void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, ...)
+{
+       if (*retval != ERROR_OK)
+       {
+               return;
+       }
+       int first = 1;
+       
+       for (;;)
+       {
+               if ((*xml == NULL) || (!first))
+               {
+                       /* start by 0 to exercise all the code paths.
+                        * Need minimum 2 bytes to fit 1 char and 0 terminator. */
+                        
+                       *size = *size * 2 + 2;
+                       char *t = *xml;
+                       *xml = realloc(*xml, *size);
+                       if (*xml == NULL)
+                       {
+                               if (t)
+                                       free(t);
+                               *retval = ERROR_SERVER_REMOTE_CLOSED;
+                               return;
+                       }
+               }
+               
+           va_list ap;
+           int ret;
+           va_start(ap, fmt);
+           ret = vsnprintf(*xml + *pos, *size - *pos, fmt, ap);
+           va_end(ap);
+           if ((ret > 0) && ((ret + 1) < *size - *pos))
+           {
+               *pos += ret;
+               return;
+           }
+           /* there was just enough or not enough space, allocate more. */
+           first = 0;
+       }
+}
+
+static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len)
+{
+       char *separator;
+       
+       /* Extract and NUL-terminate the annex. */
+       *annex = buf;
+       while (*buf && *buf != ':')
+               buf++;
+       if (*buf == '\0')
+               return -1;
+       *buf++ = 0;
+       
+       /* After the read marker and annex, qXfer looks like a
+        * traditional 'm' packet. */
+       
+       *ofs = strtoul(buf, &separator, 16);
+
+       if (*separator != ',')
+               return -1;
+
+       *len = strtoul(separator+1, NULL, 16);
+       
+       return 0;
+}
+
+int gdb_calc_blocksize(flash_bank_t *bank)
+{
+       int i;
+       int block_size = 0xffffffff;
+       
+       /* loop through all sectors and return smallest sector size */
+       
+       for (i = 0; i < bank->num_sectors; i++)
+       {
+               if (bank->sectors[i].size < block_size)
+                       block_size = bank->sectors[i].size;
+       }
+       
+       return block_size;
+}
+
+int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       command_context_t *cmd_ctx = connection->cmd_ctx;
+       
+       if (strstr(packet, "qRcmd,"))
+       {
+               if (packet_size > 6)
+               {
+                       char *cmd;
+                       int i;
+                       cmd = malloc((packet_size - 6)/2 + 1);
+                       for (i=0; i < (packet_size - 6)/2; i++)
+                       {
+                               u32 tmp;
+                               sscanf(packet + 6 + 2*i, "%2x", &tmp);
+                               cmd[i] = tmp;
+                       }
+                       cmd[(packet_size - 6)/2] = 0x0;
+                       
+                       /* We want to print all debug output to GDB connection */
+                       log_add_callback(gdb_log_callback, connection);
+                       target_call_timer_callbacks();
+                       command_run_line(cmd_ctx, cmd);
+                       free(cmd);
+               }
+               gdb_put_packet(connection, "OK", 2);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qCRC:"))
+       {
+               if (packet_size > 5)
+               {
+                       int retval;
+                       char gdb_reply[10];
+                       char *separator;
+                       u32 checksum;
+                       u32 addr = 0;
+                       u32 len = 0;
+                       
+                       /* skip command character */
+                       packet += 5;
+                       
+                       addr = strtoul(packet, &separator, 16);
+                       
+                       if (*separator != ',')
+                       {
+                               ERROR("incomplete read memory packet received, dropping connection");
+                               return ERROR_SERVER_REMOTE_CLOSED;
+                       }
+                       
+                       len = strtoul(separator + 1, NULL, 16);
+                       
+                       retval = target_checksum_memory(target, addr, len, &checksum);
+                       
+                       if (retval == ERROR_OK)
+                       {
+                               snprintf(gdb_reply, 10, "C%8.8x", checksum);
+                               gdb_put_packet(connection, gdb_reply, 9);
+                       }
+                       else
+                       {
+                               if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
+                                       return retval; 
+                       }
+                       
+                       return ERROR_OK;
+               }
+       }
+       else if (strstr(packet, "qSupported"))
+       {
+               /* we currently support packet size and qXfer:memory-map:read (if enabled)
+                * disable qXfer:features:read for the moment */
+               int retval = ERROR_OK;
+               char *buffer = NULL;
+               int pos = 0;
+               int size = 0;
+
+               xml_printf(&retval, &buffer, &pos, &size, 
+                               "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",
+                               (GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-');
+               
+               if (retval != ERROR_OK)
+               {
+                       gdb_send_error(connection, 01);
+                       return ERROR_OK;
+               }
+               
+               gdb_put_packet(connection, buffer, strlen(buffer));
+               free(buffer);
+               
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qXfer:memory-map:read::"))
+       {
+               /* We get away with only specifying flash here. Regions that are not
+                * specified are treated as if we provided no memory map(if not we 
+                * could detect the holes and mark them as RAM).
+                * Normally we only execute this code once, but no big deal if we
+                * have to regenerate it a couple of times. */
+                
+               flash_bank_t *p;
+               char *xml = NULL;
+               int size = 0;
+               int pos = 0;
+               int retval = ERROR_OK;
+               
+               int offset;
+               int length;
+               char *separator;
+               int blocksize;
+               
+               /* skip command character */
+               packet += 23;
+               
+               offset = strtoul(packet, &separator, 16);
+               length = strtoul(separator + 1, &separator, 16);
+               
+               xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
+               
+               int i = 0;
+               for (;;)
+               {
+                       p = get_flash_bank_by_num(i);
+                       if (p == NULL)
+                               break;
+                       
+                       /* if device has uneven sector sizes, eg. str7, lpc
+                        * we pass the smallest sector size to gdb memory map */
+                       blocksize = gdb_calc_blocksize(p);
+                       
+                       xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
+                               "<property name=\"blocksize\">0x%x</property>\n" \
+                               "</memory>\n", \
+                               p->base, p->size, blocksize);
+                       i++;
+               }
+               
+               xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
+
+               if (retval != ERROR_OK)
+               {
+                       gdb_send_error(connection, retval);
+                       return retval;
+               }
+                               
+               if (offset + length > pos)
+               {
+                       length = pos - offset;
+               }
+
+               char *t = malloc(length + 1);
+               t[0] = 'l';
+               memcpy(t + 1, xml + offset, length);
+               gdb_put_packet(connection, t, length + 1);
+               
+               free(t);
+               free(xml);
+               return ERROR_OK;
+       }
+       else if (strstr(packet, "qXfer:features:read:"))
+       {                
+               char *xml = NULL;
+               int size = 0;
+               int pos = 0;
+               int retval = ERROR_OK;
+               
+               int offset;
+               unsigned int length;
+               char *annex;
+               
+               /* skip command character */
+               packet += 20;
+               
+               if (decode_xfer_read(packet, &annex, &offset, &length) < 0)
+               {
+                       gdb_send_error(connection, 01);
+                       return ERROR_OK;
+               }
+               
+               if (strcmp(annex, "target.xml") != 0)
+               {
+                       gdb_send_error(connection, 01);
+                       return ERROR_OK;
+               }
+                               
+               xml_printf(&retval, &xml, &pos, &size, \
+                       "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
+                                       
+               if (retval != ERROR_OK)
+               {
+                       gdb_send_error(connection, retval);
+                       return retval;
+               }
+               
+               gdb_put_packet(connection, xml, strlen(xml) + 1);
+               
+               free(xml);
+               return ERROR_OK;
+       }
+       
+       gdb_put_packet(connection, "", 0);
+       return ERROR_OK;
+}
+
+int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
+{
+       gdb_connection_t *gdb_connection = connection->priv;
+       gdb_service_t *gdb_service = connection->service->priv;
+       int result;
+
+       /* if flash programming disabled - send a empty reply */
+       
+       if (gdb_flash_program == 0)
+       {
+               gdb_put_packet(connection, "", 0);
+               return ERROR_OK;
+       }
+       
+       if (strstr(packet, "vFlashErase:"))
+       {
+               unsigned long addr;
+               unsigned long length;
+       
+               char *parse = packet + 12;
+               if (*parse == '\0')
+               {
+                       ERROR("incomplete vFlashErase packet received, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+
+               addr = strtoul(parse, &parse, 16);
+
+               if (*(parse++) != ',' || *parse == '\0')
+               {
+                       ERROR("incomplete vFlashErase packet received, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+
+               length = strtoul(parse, &parse, 16);
+
+               if (*parse != '\0')
+               {
+                       ERROR("incomplete vFlashErase packet received, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+               
+               /* assume all sectors need erasing - stops any problems
+                * when flash_write is called multiple times */
+               flash_set_dirty();
+               
+               /* perform any target specific operations before the erase */
+               target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_PROGRAM);
+               
+               /* perform erase */
+               if ((result = flash_erase_address_range(gdb_service->target, addr, length)) != ERROR_OK)
+               {
+                       /* GDB doesn't evaluate the actual error number returned,
+                        * treat a failed erase as an I/O error
+                        */
+                       gdb_send_error(connection, EIO);
+                       ERROR("flash_erase returned %i", result);
+               }
+               else
+                       gdb_put_packet(connection, "OK", 2);
+               
+               return ERROR_OK;
+       }
+
+       if (strstr(packet, "vFlashWrite:"))
+       {
+               unsigned long addr;
+               unsigned long length;
+               char *parse = packet + 12;
+
+               if (*parse == '\0')
+               {
+                       ERROR("incomplete vFlashErase packet received, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+               addr = strtoul(parse, &parse, 16);
+               if (*(parse++) != ':')
+               {
+                       ERROR("incomplete vFlashErase packet received, dropping connection");
+                       return ERROR_SERVER_REMOTE_CLOSED;
+               }
+               length = packet_size - (parse - packet);
+               
+               /* create a new image if there isn't already one */
+               if (gdb_connection->vflash_image == NULL)
+               {
+                       gdb_connection->vflash_image = malloc(sizeof(image_t));
+                       image_open(gdb_connection->vflash_image, "", "build");
+               }
+
+               /* create new section with content from packet buffer */
+               image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (u8*)parse);
+
+               gdb_put_packet(connection, "OK", 2);
+
+               return ERROR_OK;
+       }
+
+       if (!strcmp(packet, "vFlashDone"))
+       {
+               u32 written;
+
+               /* process the flashing buffer. No need to erase as GDB
+                * always issues a vFlashErase first. */
+               if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, 0)) != ERROR_OK)
+               {
+                       if (result == ERROR_FLASH_DST_OUT_OF_BANK)
+                               gdb_put_packet(connection, "E.memtype", 9);
+                       else
+                               gdb_send_error(connection, EIO);
+                       }
+               else
+               {
+                       DEBUG("wrote %u bytes from vFlash image to flash", written);
+                       gdb_put_packet(connection, "OK", 2);
+               }
+               
+               image_close(gdb_connection->vflash_image);
+               free(gdb_connection->vflash_image);
+               gdb_connection->vflash_image = NULL;
+               
+               return ERROR_OK;
+       }
+
+       gdb_put_packet(connection, "", 0);
+       return ERROR_OK;
+}
+
+int gdb_detach(connection_t *connection, target_t *target)
+{
+       switch( detach_mode )
+       {
+               case GDB_DETACH_RESUME:
+                       target->type->resume(target, 1, 0, 1, 0);
+                       break;
+               
+               case GDB_DETACH_RESET:
+                       target_process_reset(connection->cmd_ctx);
+                       break;
+               
+               case GDB_DETACH_HALT:
+                       target->type->halt(target);
+                       break;
+               
+               case GDB_DETACH_NOTHING:
+                       break;
+       }
+       
+       gdb_put_packet(connection, "OK", 2);
+       
+       return ERROR_OK;
+}
+
+static void gdb_log_callback(void *priv, const char *file, int line, 
+               const char *function, const char *format, va_list args)
+{
+       connection_t *connection = priv;
+       gdb_connection_t *gdb_con = connection->priv;
+       
+       if (gdb_con->busy)
+       {
+               /* do not reply this using the O packet */
+               return;
+       }
+
+       char *t = alloc_printf(format, args);
+       if (t == NULL)
+               return;
+       
+       gdb_output_con(connection, t); 
+       
+       free(t);
+}
+
+int gdb_input_inner(connection_t *connection)
+{
+       gdb_service_t *gdb_service = connection->service->priv;
+       target_t *target = gdb_service->target;
+       char packet[GDB_BUFFER_SIZE];
+       int packet_size;
+       int retval;
+       gdb_connection_t *gdb_con = connection->priv;
+       static int extended_protocol = 0;
+
+       /* drain input buffer */
+       do
+       {
+               packet_size = GDB_BUFFER_SIZE-1;
+               if ((retval = gdb_get_packet(connection, packet, &packet_size)) != ERROR_OK)
+               {
+                       return retval;
+               }
+
+               /* terminate with zero */
+               packet[packet_size] = 0;
+
+               DEBUG("received packet: '%s'", packet);
+
+               if (packet_size > 0)
+               {
+                       retval = ERROR_OK;
+                       switch (packet[0])
+                       {
+                               case 'H':
+                                       /* Hct... -- set thread 
+                                        * we don't have threads, send empty reply */
+                                       gdb_put_packet(connection, NULL, 0);
+                                       break;
+                               case 'q':
+                                       retval = gdb_query_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'g':
+                                       retval = gdb_get_registers_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'G':
+                                       retval = gdb_set_registers_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'p':
+                                       retval = gdb_get_register_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'P':
+                                       retval = gdb_set_register_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'm':
+                                       retval = gdb_read_memory_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'M':
+                                       retval = gdb_write_memory_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'z':
+                               case 'Z':
+                                       retval = gdb_breakpoint_watchpoint_packet(connection, target, packet, packet_size);
+                                       break;
+                               case '?':
+                                       gdb_last_signal_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'c':
+                               case 's':
+                                       {
+                                       /* We're running/stepping, in which case we can 
+                                        * forward log output until the target is halted */
+                                               gdb_connection_t *gdb_con = connection->priv;
+                                               gdb_con->frontend_state = TARGET_RUNNING;
+                                               log_add_callback(gdb_log_callback, connection);
+                                               gdb_step_continue_packet(connection, target, packet, packet_size);
+                                       }
+                                       break;
+                               case 'v':
+                                       retval = gdb_v_packet(connection, target, packet, packet_size);
+                                       break;
+                               case 'D':
+                                       retval = gdb_detach(connection, target);
+                                       extended_protocol = 0;
+                                       break;
+                               case 'X':
+                                       if ((retval = gdb_write_memory_binary_packet(connection, target, packet, packet_size)) != ERROR_OK)
+                                               return retval;
+                                       break;
+                               case 'k':
+                                       if (extended_protocol != 0)
+                                               break;
+                                       gdb_put_packet(connection, "OK", 2);
+                                       return ERROR_SERVER_REMOTE_CLOSED;
+                               case '!':
+                                       /* handle extended remote protocol */
+                                       extended_protocol = 1;
+                                       gdb_put_packet(connection, "OK", 2);
+                                       break;
+                               case 'R':
+                                       /* handle extended restart packet */
+                                       target_process_reset(connection->cmd_ctx);
+                                       break;
+                               default:
+                                       /* ignore unkown packets */
+                                       DEBUG("ignoring 0x%2.2x packet", packet[0]);
+                                       gdb_put_packet(connection, NULL, 0);
+                                       break;
+                       }
+
+                       /* if a packet handler returned an error, exit input loop */
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+
+               if (gdb_con->ctrl_c)
+               {
+                       if (target->state == TARGET_RUNNING)
+                       {
+                               target->type->halt(target);
+                               gdb_con->ctrl_c = 0;
+                       }
+               }
+
+       } while (gdb_con->buf_cnt > 0);
+
+       return ERROR_OK;
+}
+
+int gdb_input(connection_t *connection)
+{
+       int retval = gdb_input_inner(connection);
+       if (retval == ERROR_SERVER_REMOTE_CLOSED)
+               return retval;
+       /* we'll recover from any other errors(e.g. temporary timeouts, etc.) */
+       return ERROR_OK;
+}
+
+int gdb_init()
+{
+       gdb_service_t *gdb_service;
+       target_t *target = targets;
+       int i = 0;
+
+       if (!target)
+       {
+               WARNING("no gdb ports allocated as no target has been specified");
+               return ERROR_OK;
+       }
+
+       if (gdb_port == 0)
+       {
+               WARNING("no gdb port specified, using default port 3333");
+               gdb_port = 3333;
+       }
+
+       while (target)
+       {
+               char service_name[8];
+
+               snprintf(service_name, 8, "gdb-%2.2i", i);
+
+               gdb_service = malloc(sizeof(gdb_service_t));
+               gdb_service->target = target;
+
+               add_service("gdb", CONNECTION_GDB, gdb_port + i, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
+
+               DEBUG("gdb service for target %s at port %i", target->type->name, gdb_port + i);
+
+               i++;
+               target = target->next;
+       }
+
+       return ERROR_OK;
+}
+
+/* daemon configuration command gdb_port */
+int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               return ERROR_OK;
+
+       /* only if the port wasn't overwritten by cmdline */
+       if (gdb_port == 0)
+               gdb_port = strtoul(args[0], NULL, 0);
+
+       return ERROR_OK;
+}
+
+int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "resume") == 0)
+               {
+                       detach_mode = GDB_DETACH_RESUME;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "reset") == 0)
+               {
+                       detach_mode = GDB_DETACH_RESET;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "halt") == 0)
+               {
+                       detach_mode = GDB_DETACH_HALT;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "nothing") == 0)
+               {
+                       detach_mode = GDB_DETACH_NOTHING;
+                       return ERROR_OK;
+               }
+       }
+       
+       WARNING("invalid gdb_detach configuration directive: %s", args[0]);
+       return ERROR_OK;
+}
+
+int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "enable") == 0)
+               {
+                       gdb_use_memory_map = 1;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "disable") == 0)
+               {
+                       gdb_use_memory_map = 0;
+                       return ERROR_OK;
+               }
+       }
+       
+       WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);
+       return ERROR_OK;
+}
+
+int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "enable") == 0)
+               {
+                       gdb_flash_program = 1;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "disable") == 0)
+               {
+                       gdb_flash_program = 0;
+                       return ERROR_OK;
+               }
+       }
+       
+       WARNING("invalid gdb_memory_map configuration directive: %s", args[0]);
+       return ERROR_OK;
+}
+
+int handle_gdb_report_data_abort_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "enable") == 0)
+               {
+                       gdb_report_data_abort = 1;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "disable") == 0)
+               {
+                       gdb_report_data_abort = 0;
+                       return ERROR_OK;
+               }
+       }
+       
+       WARNING("invalid gdb_report_data_abort configuration directive: %s", args[0]);
+       return ERROR_OK;
+}
+
+int gdb_register_commands(command_context_t *command_context)
+{
+       register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
+                       COMMAND_CONFIG, "");
+       register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
+                       COMMAND_CONFIG, "");
+       register_command(command_context, NULL, "gdb_memory_map", handle_gdb_memory_map_command,
+                       COMMAND_CONFIG, "");
+       register_command(command_context, NULL, "gdb_flash_program", handle_gdb_flash_program_command,
+                       COMMAND_CONFIG, "");
+       register_command(command_context, NULL, "gdb_report_data_abort", handle_gdb_report_data_abort_command,
+                       COMMAND_CONFIG, "");
+       return ERROR_OK;
+}
index 0aa3383492e85315c9536ad4f574934fb1ec0d38..6aa72b92b1508266c4b06837a30a0493a52dfa58 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "server.h"\r
-\r
-#include "log.h"\r
-#include "telnet_server.h"\r
-#include "target.h"\r
-\r
-#include <command.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <errno.h>\r
-#include <unistd.h>\r
-#include <sys/types.h>\r
-#include <fcntl.h>\r
-#include <signal.h>\r
-\r
-service_t *services = NULL;\r
-\r
-/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */\r
-static int shutdown_openocd = 0;\r
-int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int add_connection(service_t *service, command_context_t *cmd_ctx)\r
-{\r
-       unsigned int address_size;\r
-       connection_t *c, **p;\r
-       int retval;\r
-       \r
-       c = malloc(sizeof(connection_t));\r
-       c->fd = -1;\r
-       memset(&c->sin, 0, sizeof(c->sin));\r
-       c->cmd_ctx = copy_command_context(cmd_ctx);\r
-       c->service = service;\r
-       c->input_pending = 0;\r
-       c->priv = NULL;\r
-       c->next = NULL;\r
-\r
-       address_size = sizeof(c->sin);\r
-       c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);\r
-                               \r
-       if ((retval = service->new_connection(c)) == ERROR_OK)\r
-       {\r
-               INFO("accepted '%s' connection from %i", service->name, c->sin.sin_port);\r
-       }\r
-       else\r
-       {\r
-               close_socket(c->fd);\r
-               INFO("attempted '%s' connection rejected", service->name);\r
-               free(c);\r
-       }\r
-       \r
-       /* add to the end of linked list */\r
-       for (p = &service->connections; *p; p = &(*p)->next);\r
-       *p = c;\r
-       \r
-       service->max_connections--;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int remove_connection(service_t *service, connection_t *connection)\r
-{\r
-       connection_t **p = &service->connections;\r
-       connection_t *c;\r
-       \r
-       /* find connection */\r
-       while(c = *p)\r
-       {               \r
-               if (c->fd == connection->fd)\r
-               {       \r
-                       service->connection_closed(c);\r
-                       close_socket(c->fd);\r
-                       command_done(c->cmd_ctx);\r
-                       \r
-                       /* delete connection */\r
-                       *p = c->next;\r
-                       free(c);\r
-                       \r
-                       service->max_connections++;\r
-                       break;\r
-               }\r
-               \r
-               /* redirect p to next list pointer */\r
-               p = &(*p)->next;                \r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)\r
-{\r
-       service_t *c, **p;\r
-       int so_reuseaddr_option = 1;\r
-       \r
-       c = malloc(sizeof(service_t));\r
-       \r
-       c->name = strdup(name);\r
-       c->type = type;\r
-       c->port = port;\r
-       c->max_connections = max_connections;\r
-       c->fd = -1;\r
-       c->connections = NULL;\r
-       c->new_connection = new_connection_handler;\r
-       c->input = input_handler;\r
-       c->connection_closed = connection_closed_handler;\r
-       c->priv = priv;\r
-       c->next = NULL;\r
-       \r
-       if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)\r
-       {\r
-               ERROR("error creating socket: %s", strerror(errno));\r
-               exit(-1);\r
-       }\r
-       \r
-       setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));\r
-       \r
-       socket_nonblock(c->fd);\r
-       \r
-       memset(&c->sin, 0, sizeof(c->sin));\r
-       c->sin.sin_family = AF_INET;\r
-       c->sin.sin_addr.s_addr = INADDR_ANY;\r
-       c->sin.sin_port = htons(port);\r
-       \r
-       if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)\r
-       {\r
-               ERROR("couldn't bind to socket: %s", strerror(errno));\r
-               exit(-1);\r
-       }\r
-       \r
-       if (listen(c->fd, 1) == -1)\r
-       {\r
-               ERROR("couldn't listen on socket: %s", strerror(errno));\r
-               exit(-1);\r
-       }\r
-       \r
-       /* add to the end of linked list */\r
-       for (p = &services; *p; p = &(*p)->next);\r
-       *p = c;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int remove_service(unsigned short port)\r
-{\r
-       service_t **p = &services;\r
-       service_t *c;\r
-       \r
-       /* find service */\r
-       while(c = *p)\r
-       {               \r
-               if (c->port == port)\r
-               {       \r
-                       if (c->name)\r
-                               free(c->name);\r
-                       \r
-                       if (c->priv)\r
-                               free(c->priv);\r
-                       \r
-                       /* delete service */\r
-                       *p = c->next;\r
-                       free(c);\r
-               }\r
-\r
-               /* redirect p to next list pointer */\r
-               p = &(*p)->next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int remove_services()\r
-{\r
-       service_t *c = services;\r
-\r
-       /* loop service */\r
-       while(c)\r
-       {\r
-               service_t *next = c->next;\r
-\r
-               if (c->name)\r
-                       free(c->name);\r
-\r
-               if (c->priv)\r
-                       free(c->priv);\r
-\r
-               /* delete service */\r
-               free(c);\r
-\r
-               /* remember the last service for unlinking */\r
-               c = next;\r
-       }\r
-\r
-       services = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int server_loop(command_context_t *command_context)\r
-{\r
-       service_t *service;\r
-\r
-       /* used in select() */\r
-       fd_set read_fds;\r
-       struct timeval tv;\r
-       int fd_max;\r
-       \r
-       /* used in accept() */\r
-       int retval;\r
-       \r
-#ifndef _WIN32\r
-       if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)\r
-               ERROR("couldn't set SIGPIPE to SIG_IGN");\r
-#endif\r
-       \r
-       /* do regular tasks after at most 10ms */\r
-       tv.tv_sec = 0;\r
-       tv.tv_usec = 10000;\r
-       \r
-       while(!shutdown_openocd)\r
-       {\r
-               /* monitor sockets for acitvity */\r
-               fd_max = 0;\r
-               FD_ZERO(&read_fds);\r
-\r
-               /* add service and connection fds to read_fds */\r
-               for (service = services; service; service = service->next)\r
-               {\r
-                       if (service->fd != -1)\r
-                       {\r
-                               /* listen for new connections */\r
-                               FD_SET(service->fd, &read_fds);\r
-\r
-                               if (service->fd > fd_max)\r
-                                       fd_max = service->fd;\r
-                       }\r
-                       \r
-                       if (service->connections)\r
-                       {\r
-                               connection_t *c;\r
-                               \r
-                               for (c = service->connections; c; c = c->next)\r
-                               {\r
-                                       /* check for activity on the connection */\r
-                                       FD_SET(c->fd, &read_fds);\r
-                                       if (c->fd > fd_max)\r
-                                               fd_max = c->fd;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-#ifndef _WIN32\r
-               /* add STDIN to read_fds */\r
-               FD_SET(fileno(stdin), &read_fds);\r
-#endif\r
-\r
-               retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);\r
-               \r
-               if (retval == -1)\r
-               {\r
-#ifdef _WIN32\r
-\r
-                       errno = WSAGetLastError();\r
-\r
-                       if (errno == WSAEINTR)\r
-                               FD_ZERO(&read_fds);\r
-                       else\r
-                       {\r
-                               ERROR("error during select: %s", strerror(errno));\r
-                               exit(-1);\r
-                       }\r
-#else\r
-\r
-                       if (errno == EINTR)\r
-                       {\r
-                               FD_ZERO(&read_fds);\r
-                       }\r
-                       else\r
-                       {\r
-                               ERROR("error during select: %s", strerror(errno));\r
-                               exit(-1);\r
-                       }\r
-#endif\r
-               }\r
-               \r
-               target_call_timer_callbacks();\r
-\r
-               if (retval == 0)\r
-               {\r
-                       /* do regular tasks after at most 100ms */\r
-                       tv.tv_sec = 0;\r
-                       tv.tv_usec = 10000;\r
-                       FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case!  */\r
-               }\r
-               \r
-               for (service = services; service; service = service->next)\r
-               {\r
-                       /* handle new connections on listeners */\r
-                       if ((service->fd != -1) \r
-                               && (FD_ISSET(service->fd, &read_fds))) \r
-                       {\r
-                               if (service->max_connections > 0)\r
-                               {\r
-                                       add_connection(service, command_context);\r
-                               }\r
-                               else\r
-                               {\r
-                                       struct sockaddr_in sin;\r
-                                       unsigned int address_size = sizeof(sin);\r
-                                       int tmp_fd;\r
-                                       tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);\r
-                                       close_socket(tmp_fd);\r
-                                       INFO("rejected '%s' connection, no more connections allowed", service->name);\r
-                               }\r
-                       }\r
-                       \r
-                       /* handle activity on connections */\r
-                       if (service->connections)\r
-                       {\r
-                               connection_t *c;\r
-                               \r
-                               for (c = service->connections; c;)\r
-                               {\r
-                                       if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)\r
-                                       {\r
-                                               if (service->input(c) != ERROR_OK)\r
-                                               {\r
-                                                       connection_t *next = c->next;\r
-                                                       remove_connection(service, c);\r
-                                                       INFO("dropped '%s' connection", service->name);\r
-                                                       c = next;\r
-                                                       continue;\r
-                                               }\r
-                                       }\r
-                                       c = c->next;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-#ifndef _WIN32\r
-               if (FD_ISSET(fileno(stdin), &read_fds))\r
-               {\r
-                       if (getc(stdin) == 'x')\r
-                       {\r
-                               shutdown_openocd = 1;\r
-                       }\r
-               }\r
-#else\r
-               MSG msg;\r
-               while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))\r
-               {\r
-                       if (msg.message == WM_QUIT)\r
-                               shutdown_openocd = 1;\r
-               }\r
-#endif\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-#ifdef _WIN32\r
-BOOL WINAPI ControlHandler(DWORD dwCtrlType)\r
-{\r
-    shutdown_openocd = 1;\r
-    return TRUE;\r
-}\r
-\r
-void sig_handler(int sig) {\r
-    shutdown_openocd = 1;\r
-}\r
-#endif\r
-\r
-int server_init()\r
-{\r
-#ifdef _WIN32\r
-       WORD wVersionRequested;\r
-       WSADATA wsaData;\r
-\r
-       wVersionRequested = MAKEWORD( 2, 2 );\r
-\r
-       if (WSAStartup(wVersionRequested, &wsaData) != 0)\r
-       {\r
-               ERROR("Failed to Open Winsock");\r
-               exit(-1);\r
-       }\r
-\r
-       SetConsoleCtrlHandler( ControlHandler, TRUE );\r
-\r
-       signal(SIGINT, sig_handler);\r
-       signal(SIGTERM, sig_handler);\r
-       signal(SIGBREAK, sig_handler);\r
-       signal(SIGABRT, sig_handler);\r
-#endif\r
-\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int server_quit()\r
-{\r
-       remove_services();\r
-\r
-#ifdef _WIN32\r
-       WSACleanup();\r
-       SetConsoleCtrlHandler( ControlHandler, FALSE );\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int server_register_commands(command_context_t *context)\r
-{\r
-       register_command(context, NULL, "shutdown", handle_shutdown_command,\r
-                                        COMMAND_ANY, "shut the server down");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/* tell the server we want to shut down */\r
-int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       shutdown_openocd = 1;\r
-\r
-       return ERROR_COMMAND_CLOSE_CONNECTION;\r
-}\r
-\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "server.h"
+
+#include "log.h"
+#include "telnet_server.h"
+#include "target.h"
+
+#include <command.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <signal.h>
+
+service_t *services = NULL;
+
+/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
+static int shutdown_openocd = 0;
+int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int add_connection(service_t *service, command_context_t *cmd_ctx)
+{
+       unsigned int address_size;
+       connection_t *c, **p;
+       int retval;
+       
+       c = malloc(sizeof(connection_t));
+       c->fd = -1;
+       memset(&c->sin, 0, sizeof(c->sin));
+       c->cmd_ctx = copy_command_context(cmd_ctx);
+       c->service = service;
+       c->input_pending = 0;
+       c->priv = NULL;
+       c->next = NULL;
+
+       address_size = sizeof(c->sin);
+       c->fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
+                               
+       if ((retval = service->new_connection(c)) == ERROR_OK)
+       {
+               INFO("accepted '%s' connection from %i", service->name, c->sin.sin_port);
+       }
+       else
+       {
+               close_socket(c->fd);
+               INFO("attempted '%s' connection rejected", service->name);
+               free(c);
+       }
+       
+       /* add to the end of linked list */
+       for (p = &service->connections; *p; p = &(*p)->next);
+       *p = c;
+       
+       service->max_connections--;
+       
+       return ERROR_OK;
+}
+
+int remove_connection(service_t *service, connection_t *connection)
+{
+       connection_t **p = &service->connections;
+       connection_t *c;
+       
+       /* find connection */
+       while(c = *p)
+       {               
+               if (c->fd == connection->fd)
+               {       
+                       service->connection_closed(c);
+                       close_socket(c->fd);
+                       command_done(c->cmd_ctx);
+                       
+                       /* delete connection */
+                       *p = c->next;
+                       free(c);
+                       
+                       service->max_connections++;
+                       break;
+               }
+               
+               /* redirect p to next list pointer */
+               p = &(*p)->next;                
+       }
+       
+       return ERROR_OK;
+}
+
+int add_service(char *name, enum connection_type type, unsigned short port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv)
+{
+       service_t *c, **p;
+       int so_reuseaddr_option = 1;
+       
+       c = malloc(sizeof(service_t));
+       
+       c->name = strdup(name);
+       c->type = type;
+       c->port = port;
+       c->max_connections = max_connections;
+       c->fd = -1;
+       c->connections = NULL;
+       c->new_connection = new_connection_handler;
+       c->input = input_handler;
+       c->connection_closed = connection_closed_handler;
+       c->priv = priv;
+       c->next = NULL;
+       
+       if ((c->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+       {
+               ERROR("error creating socket: %s", strerror(errno));
+               exit(-1);
+       }
+       
+       setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
+       
+       socket_nonblock(c->fd);
+       
+       memset(&c->sin, 0, sizeof(c->sin));
+       c->sin.sin_family = AF_INET;
+       c->sin.sin_addr.s_addr = INADDR_ANY;
+       c->sin.sin_port = htons(port);
+       
+       if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1)
+       {
+               ERROR("couldn't bind to socket: %s", strerror(errno));
+               exit(-1);
+       }
+       
+       if (listen(c->fd, 1) == -1)
+       {
+               ERROR("couldn't listen on socket: %s", strerror(errno));
+               exit(-1);
+       }
+       
+       /* add to the end of linked list */
+       for (p = &services; *p; p = &(*p)->next);
+       *p = c;
+       
+       return ERROR_OK;
+}
+
+int remove_service(unsigned short port)
+{
+       service_t **p = &services;
+       service_t *c;
+       
+       /* find service */
+       while(c = *p)
+       {               
+               if (c->port == port)
+               {       
+                       if (c->name)
+                               free(c->name);
+                       
+                       if (c->priv)
+                               free(c->priv);
+                       
+                       /* delete service */
+                       *p = c->next;
+                       free(c);
+               }
+
+               /* redirect p to next list pointer */
+               p = &(*p)->next;
+       }
+       
+       return ERROR_OK;
+}
+
+int remove_services()
+{
+       service_t *c = services;
+
+       /* loop service */
+       while(c)
+       {
+               service_t *next = c->next;
+
+               if (c->name)
+                       free(c->name);
+
+               if (c->priv)
+                       free(c->priv);
+
+               /* delete service */
+               free(c);
+
+               /* remember the last service for unlinking */
+               c = next;
+       }
+
+       services = NULL;
+       
+       return ERROR_OK;
+}
+
+int server_loop(command_context_t *command_context)
+{
+       service_t *service;
+
+       /* used in select() */
+       fd_set read_fds;
+       struct timeval tv;
+       int fd_max;
+       
+       /* used in accept() */
+       int retval;
+       
+#ifndef _WIN32
+       if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+               ERROR("couldn't set SIGPIPE to SIG_IGN");
+#endif
+       
+       /* do regular tasks after at most 10ms */
+       tv.tv_sec = 0;
+       tv.tv_usec = 10000;
+       
+       while(!shutdown_openocd)
+       {
+               /* monitor sockets for acitvity */
+               fd_max = 0;
+               FD_ZERO(&read_fds);
+
+               /* add service and connection fds to read_fds */
+               for (service = services; service; service = service->next)
+               {
+                       if (service->fd != -1)
+                       {
+                               /* listen for new connections */
+                               FD_SET(service->fd, &read_fds);
+
+                               if (service->fd > fd_max)
+                                       fd_max = service->fd;
+                       }
+                       
+                       if (service->connections)
+                       {
+                               connection_t *c;
+                               
+                               for (c = service->connections; c; c = c->next)
+                               {
+                                       /* check for activity on the connection */
+                                       FD_SET(c->fd, &read_fds);
+                                       if (c->fd > fd_max)
+                                               fd_max = c->fd;
+                               }
+                       }
+               }
+               
+#ifndef _WIN32
+               /* add STDIN to read_fds */
+               FD_SET(fileno(stdin), &read_fds);
+#endif
+
+               retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
+               
+               if (retval == -1)
+               {
+#ifdef _WIN32
+
+                       errno = WSAGetLastError();
+
+                       if (errno == WSAEINTR)
+                               FD_ZERO(&read_fds);
+                       else
+                       {
+                               ERROR("error during select: %s", strerror(errno));
+                               exit(-1);
+                       }
+#else
+
+                       if (errno == EINTR)
+                       {
+                               FD_ZERO(&read_fds);
+                       }
+                       else
+                       {
+                               ERROR("error during select: %s", strerror(errno));
+                               exit(-1);
+                       }
+#endif
+               }
+               
+               target_call_timer_callbacks();
+
+               if (retval == 0)
+               {
+                       /* do regular tasks after at most 100ms */
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 10000;
+                       FD_ZERO(&read_fds); /* eCos leaves read_fds unchanged in this case!  */
+               }
+               
+               for (service = services; service; service = service->next)
+               {
+                       /* handle new connections on listeners */
+                       if ((service->fd != -1) 
+                               && (FD_ISSET(service->fd, &read_fds))) 
+                       {
+                               if (service->max_connections > 0)
+                               {
+                                       add_connection(service, command_context);
+                               }
+                               else
+                               {
+                                       struct sockaddr_in sin;
+                                       unsigned int address_size = sizeof(sin);
+                                       int tmp_fd;
+                                       tmp_fd = accept(service->fd, (struct sockaddr *)&service->sin, &address_size);
+                                       close_socket(tmp_fd);
+                                       INFO("rejected '%s' connection, no more connections allowed", service->name);
+                               }
+                       }
+                       
+                       /* handle activity on connections */
+                       if (service->connections)
+                       {
+                               connection_t *c;
+                               
+                               for (c = service->connections; c;)
+                               {
+                                       if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending)
+                                       {
+                                               if (service->input(c) != ERROR_OK)
+                                               {
+                                                       connection_t *next = c->next;
+                                                       remove_connection(service, c);
+                                                       INFO("dropped '%s' connection", service->name);
+                                                       c = next;
+                                                       continue;
+                                               }
+                                       }
+                                       c = c->next;
+                               }
+                       }
+               }
+               
+#ifndef _WIN32
+               if (FD_ISSET(fileno(stdin), &read_fds))
+               {
+                       if (getc(stdin) == 'x')
+                       {
+                               shutdown_openocd = 1;
+                       }
+               }
+#else
+               MSG msg;
+               while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
+               {
+                       if (msg.message == WM_QUIT)
+                               shutdown_openocd = 1;
+               }
+#endif
+       }
+       
+       return ERROR_OK;
+}
+
+#ifdef _WIN32
+BOOL WINAPI ControlHandler(DWORD dwCtrlType)
+{
+    shutdown_openocd = 1;
+    return TRUE;
+}
+
+void sig_handler(int sig) {
+    shutdown_openocd = 1;
+}
+#endif
+
+int server_init()
+{
+#ifdef _WIN32
+       WORD wVersionRequested;
+       WSADATA wsaData;
+
+       wVersionRequested = MAKEWORD( 2, 2 );
+
+       if (WSAStartup(wVersionRequested, &wsaData) != 0)
+       {
+               ERROR("Failed to Open Winsock");
+               exit(-1);
+       }
+
+       SetConsoleCtrlHandler( ControlHandler, TRUE );
+
+       signal(SIGINT, sig_handler);
+       signal(SIGTERM, sig_handler);
+       signal(SIGBREAK, sig_handler);
+       signal(SIGABRT, sig_handler);
+#endif
+
+       
+       return ERROR_OK;
+}
+
+int server_quit()
+{
+       remove_services();
+
+#ifdef _WIN32
+       WSACleanup();
+       SetConsoleCtrlHandler( ControlHandler, FALSE );
+#endif
+
+       return ERROR_OK;
+}
+
+int server_register_commands(command_context_t *context)
+{
+       register_command(context, NULL, "shutdown", handle_shutdown_command,
+                                        COMMAND_ANY, "shut the server down");
+       
+       return ERROR_OK;
+}
+
+/* tell the server we want to shut down */
+int handle_shutdown_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       shutdown_openocd = 1;
+
+       return ERROR_COMMAND_CLOSE_CONNECTION;
+}
+
+
index 830cf6410caa953b0316aa1b344a3f546cee6770..5cfb0ab49a6abc7a0c3f5ce489d62d01db9b1646 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "telnet_server.h"\r
-\r
-#include "server.h"\r
-#include "log.h"\r
-#include "command.h"\r
-#include "target.h"\r
-#include "target_request.h"\r
-\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <errno.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-\r
-static unsigned short telnet_port = 0;\r
-\r
-int handle_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_telnet_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-static char *negotiate =\r
-               "\xFF\xFB\x03"          /* IAC WILL Suppress Go Ahead */\r
-               "\xFF\xFB\x01"          /* IAC WILL Echo */\r
-               "\xFF\xFD\x03"          /* IAC DO Suppress Go Ahead */\r
-               "\xFF\xFE\x01";         /* IAC DON'T Echo */\r
-               \r
-#define CTRL(c) (c - '@')\r
-       \r
-/* The only way we can detect that the socket is closed is the first time\r
- * we write to it, we will fail. Subsequent write operations will\r
- * succeed. Shudder!\r
- */\r
-int telnet_write(connection_t *connection, void *data, int len)\r
-{\r
-       telnet_connection_t *t_con = connection->priv;\r
-       if (t_con->closed)\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-\r
-       if (write_socket(connection->fd, data, len) == len)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-       t_con->closed = 1;\r
-       return ERROR_SERVER_REMOTE_CLOSED;\r
-}\r
-\r
-int telnet_prompt(connection_t *connection)\r
-{\r
-       telnet_connection_t *t_con = connection->priv;\r
-\r
-       return telnet_write(connection, t_con->prompt, strlen(t_con->prompt));\r
-}\r
-\r
-int telnet_outputline(connection_t *connection, char* line)\r
-{\r
-       telnet_write(connection, line, strlen(line));\r
-       return telnet_write(connection, "\r\n\0", 3);\r
-}\r
-\r
-int telnet_output(struct command_context_s *cmd_ctx, char* line)\r
-{\r
-       connection_t *connection = cmd_ctx->output_handler_priv;\r
-       \r
-       return telnet_outputline(connection, line);\r
-}\r
-\r
-void telnet_log_callback(void *priv, const char *file, int line, \r
-               const char *function, const char *format, va_list args)\r
-{\r
-       connection_t *connection = priv;\r
-       char *t = alloc_printf(format, args);\r
-       char *t2;\r
-       if (t == NULL)\r
-               return;\r
-       t2=t;\r
-       char *endline;\r
-       do \r
-       {\r
-               if ((endline=strchr(t2, '\n'))!=NULL)\r
-               {\r
-                       *endline=0;\r
-               }\r
-               telnet_outputline(connection, t2);\r
-               t2=endline+1;\r
-       } while (endline);\r
-       \r
-       free(t);\r
-}\r
-\r
-int telnet_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)\r
-{\r
-       struct command_context_s *cmd_ctx = priv;\r
-       connection_t *connection = cmd_ctx->output_handler_priv;\r
-       telnet_connection_t *t_con = connection->priv;\r
-       \r
-       switch (event)\r
-       {\r
-               case TARGET_EVENT_HALTED:\r
-                       target_arch_state(target);\r
-                       if (!t_con->suppress_prompt)\r
-                               telnet_prompt(connection);\r
-                       break;\r
-               case TARGET_EVENT_RESUMED:\r
-                       if (!t_con->suppress_prompt)\r
-                               telnet_prompt(connection);\r
-                       break;\r
-               default:\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int telnet_new_connection(connection_t *connection)\r
-{\r
-       telnet_connection_t *telnet_connection = malloc(sizeof(telnet_connection_t));\r
-       telnet_service_t *telnet_service = connection->service->priv;\r
-       int i;\r
-       \r
-       connection->priv = telnet_connection;\r
-       \r
-       /* initialize telnet connection information */\r
-       telnet_connection->closed = 0;\r
-       telnet_connection->line_size = 0;\r
-       telnet_connection->line_cursor = 0;\r
-       telnet_connection->option_size = 0;\r
-       telnet_connection->prompt = strdup("> ");\r
-       telnet_connection->suppress_prompt = 0;\r
-       telnet_connection->state = TELNET_STATE_DATA;\r
-       \r
-       /* output goes through telnet connection */\r
-       command_set_output_handler(connection->cmd_ctx, telnet_output, connection);\r
-       \r
-       /* negotiate telnet options */\r
-       telnet_write(connection, negotiate, strlen(negotiate));\r
-       \r
-       /* print connection banner */\r
-       if (telnet_service->banner)\r
-       {\r
-               telnet_write(connection, telnet_service->banner, strlen(telnet_service->banner));\r
-               telnet_write(connection, "\r\n\0", 3);\r
-       }\r
-       \r
-       telnet_prompt(connection);\r
-       \r
-       /* initialize history */\r
-       for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)\r
-       {\r
-               telnet_connection->history[i] = NULL;\r
-       }\r
-       telnet_connection->next_history = 0;\r
-       telnet_connection->current_history = 0;\r
-\r
-       target_register_event_callback(telnet_target_callback_event_handler, connection->cmd_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-void telnet_clear_line(connection_t *connection, telnet_connection_t *t_con)\r
-{\r
-       /* move to end of line */\r
-       if (t_con->line_cursor < t_con->line_size)\r
-       {\r
-               telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);\r
-       }\r
-                                                       \r
-       /* backspace, overwrite with space, backspace */\r
-       while (t_con->line_size > 0)\r
-       {\r
-               telnet_write(connection, "\b \b", 3);\r
-               t_con->line_size--;\r
-       }\r
-       t_con->line_cursor = 0;\r
-}\r
-\r
-int telnet_input(connection_t *connection)\r
-{\r
-       int bytes_read;\r
-       char buffer[TELNET_BUFFER_SIZE];\r
-       char *buf_p;\r
-       telnet_connection_t *t_con = connection->priv;\r
-       command_context_t *command_context = connection->cmd_ctx;\r
-       \r
-       bytes_read = read_socket(connection->fd, buffer, TELNET_BUFFER_SIZE);\r
-       \r
-       if (bytes_read == 0)\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       else if (bytes_read == -1)\r
-       {\r
-               ERROR("error during read: %s", strerror(errno));\r
-               return ERROR_SERVER_REMOTE_CLOSED;\r
-       }\r
-       \r
-       buf_p = buffer;\r
-       while (bytes_read)\r
-       {\r
-               switch (t_con->state)\r
-               {\r
-                       case TELNET_STATE_DATA:\r
-                               if (*buf_p == '\xff')\r
-                               {\r
-                                       t_con->state = TELNET_STATE_IAC;\r
-                               }\r
-                               else\r
-                               {\r
-                                       if (isprint(*buf_p)) /* printable character */\r
-                                       {\r
-                                               telnet_write(connection, buf_p, 1);\r
-                                               if (t_con->line_cursor == t_con->line_size)\r
-                                               {\r
-                                                       t_con->line[t_con->line_size++] = *buf_p;\r
-                                                       t_con->line_cursor++;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       int i;\r
-                                                       memmove(t_con->line + t_con->line_cursor + 1, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);\r
-                                                       t_con->line[t_con->line_cursor++] = *buf_p;\r
-                                                       t_con->line_size++;\r
-                                                       telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);\r
-                                                       for (i = t_con->line_cursor; i < t_con->line_size; i++)\r
-                                                       {\r
-                                                               telnet_write(connection, "\b", 1);\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       else /* non-printable */\r
-                                       {\r
-                                               if (*buf_p == 0x1b) /* escape */\r
-                                               {\r
-                                                       t_con->state = TELNET_STATE_ESCAPE;\r
-                                                       t_con->last_escape = '\x00';\r
-                                               }\r
-                                               else if ((*buf_p == 0xd) || (*buf_p == 0xa)) /* CR/LF */\r
-                                               {\r
-                                                       int retval;\r
-                                                       \r
-                                                       /* skip over combinations with CR/LF + NUL */\r
-                                                       if (((*(buf_p + 1) == 0xa) || (*(buf_p + 1) == 0xd)) && (bytes_read > 1))\r
-                                                       {\r
-                                                               buf_p++;\r
-                                                               bytes_read--;\r
-                                                       }\r
-                                                       if ((*(buf_p + 1) == 0) && (bytes_read > 1))\r
-                                                       {\r
-                                                               buf_p++;\r
-                                                               bytes_read--;\r
-                                                       }\r
-                                                       t_con->line[t_con->line_size] = 0;\r
-                                                       \r
-                                                       telnet_write(connection, "\r\n\x00", 3);\r
-                                                       \r
-                                                       if (strcmp(t_con->line, "history") == 0)\r
-                                                       {\r
-                                                               int i;\r
-                                                               for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)\r
-                                                               {\r
-                                                                       if (t_con->history[i])\r
-                                                                       {\r
-                                                                               telnet_write(connection, t_con->history[i], strlen(t_con->history[i]));\r
-                                                                               telnet_write(connection, "\r\n\x00", 3);\r
-                                                                       }\r
-                                                               }\r
-                                                               telnet_prompt(connection);\r
-                                                               t_con->line_size = 0;\r
-                                                               t_con->line_cursor = 0;\r
-                                                               continue;\r
-                                                       }\r
-                                                       \r
-                                                       log_add_callback(telnet_log_callback, connection);\r
-                                                       t_con->suppress_prompt = 1;\r
-\r
-                                                       retval = command_run_line(command_context, t_con->line);\r
-                                                       \r
-                                                       log_remove_callback(telnet_log_callback, connection);\r
-                                                       t_con->suppress_prompt = 0;\r
-\r
-                                                       if (retval == ERROR_COMMAND_CLOSE_CONNECTION)\r
-                                                       {\r
-                                                               return ERROR_SERVER_REMOTE_CLOSED;\r
-                                                       }\r
-                                                       \r
-                                                       /* Save only non-blank lines in the history */\r
-                                                       if (t_con->line_size > 0)\r
-                                                       {\r
-                                                               /* if the history slot is already taken, free it */\r
-                                                               if (t_con->history[t_con->next_history])\r
-                                                               {\r
-                                                                       free(t_con->history[t_con->next_history]);\r
-                                                               }\r
-               \r
-                                                               /* add line to history */\r
-                                                               t_con->history[t_con->next_history] = strdup(t_con->line);\r
-\r
-                                                               /* wrap history at TELNET_LINE_HISTORY_SIZE */\r
-                                                               t_con->next_history = (t_con->next_history + 1) % TELNET_LINE_HISTORY_SIZE;\r
-                                                       \r
-                                                               /* current history line starts at the new entry */\r
-                                                               t_con->current_history = t_con->next_history;\r
-                                                       \r
-                                                               if (t_con->history[t_con->current_history])\r
-                                                               {\r
-                                                                       free(t_con->history[t_con->current_history]);\r
-                                                               }\r
-                                                               t_con->history[t_con->current_history] = strdup("");\r
-                                                       }\r
-                                                       \r
-                                                       int t = telnet_prompt(connection);\r
-                                                       if (t == ERROR_SERVER_REMOTE_CLOSED)\r
-                                                               return t;\r
-                                                       \r
-                                                       t_con->line_size = 0;\r
-                                                       t_con->line_cursor = 0;\r
-                                               }\r
-                                               else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) /* delete character */\r
-                                               {\r
-                                                       if (t_con->line_cursor > 0)\r
-                                                       {\r
-                                                               if (t_con->line_cursor != t_con->line_size)\r
-                                                               {\r
-                                                                       int i;\r
-                                                                       telnet_write(connection, "\b", 1);\r
-                                                                       t_con->line_cursor--;\r
-                                                                       t_con->line_size--;\r
-                                                                       memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor);\r
-                                                                       \r
-                                                                       telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);\r
-                                                                       telnet_write(connection, " \b", 2);\r
-                                                                       for (i = t_con->line_cursor; i < t_con->line_size; i++)\r
-                                                                       {\r
-                                                                               telnet_write(connection, "\b", 1);\r
-                                                                       }\r
-                                                               }\r
-                                                               else\r
-                                                               {\r
-                                                                       t_con->line_size--;\r
-                                                                       t_con->line_cursor--;\r
-                                                                       /* back space: move the 'printer' head one char back, overwrite with space, move back again */\r
-                                                                       telnet_write(connection, "\b \b", 3);\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                               else if (*buf_p == 0x15) /* clear line */\r
-                                               {\r
-                                                       telnet_clear_line(connection, t_con);\r
-                                               }\r
-                                               else if (*buf_p == CTRL('B')) /* cursor left */\r
-                                               {\r
-                                                       if (t_con->line_cursor > 0)\r
-                                                       {\r
-                                                               telnet_write(connection, "\b", 1);\r
-                                                               t_con->line_cursor--;\r
-                                                       }\r
-                                                       t_con->state = TELNET_STATE_DATA;\r
-                                               }\r
-                                               else if (*buf_p == CTRL('F')) /* cursor right */\r
-                                               {\r
-                                                       if (t_con->line_cursor < t_con->line_size)\r
-                                                       {\r
-                                                               telnet_write(connection, t_con->line + t_con->line_cursor++, 1);\r
-                                                       }\r
-                                                       t_con->state = TELNET_STATE_DATA;\r
-                                               }\r
-                                               else\r
-                                               {\r
-                                                       DEBUG("unhandled nonprintable: %2.2x", *buf_p);\r
-                                               }\r
-                                       }\r
-                               }\r
-                               break;\r
-                       case TELNET_STATE_IAC:\r
-                               switch (*buf_p)\r
-                               {\r
-                                       case '\xfe':\r
-                                               t_con->state = TELNET_STATE_DONT;\r
-                                               break;\r
-                                       case '\xfd':\r
-                                               t_con->state = TELNET_STATE_DO;\r
-                                               break;\r
-                                       case '\xfc':\r
-                                               t_con->state = TELNET_STATE_WONT;\r
-                                               break;\r
-                                       case '\xfb':\r
-                                               t_con->state = TELNET_STATE_WILL;\r
-                                               break;\r
-                               }\r
-                               break;\r
-                       case TELNET_STATE_SB:\r
-                               break;\r
-                       case TELNET_STATE_SE:\r
-                               break;\r
-                       case TELNET_STATE_WILL:\r
-                       case TELNET_STATE_WONT:\r
-                       case TELNET_STATE_DO:\r
-                       case TELNET_STATE_DONT:\r
-                               t_con->state = TELNET_STATE_DATA;\r
-                               break;\r
-                       case TELNET_STATE_ESCAPE:\r
-                               if (t_con->last_escape == '[')\r
-                               {\r
-                                       if (*buf_p == 'D') /* cursor left */\r
-                                       {\r
-                                               if (t_con->line_cursor > 0)\r
-                                               {\r
-                                                       telnet_write(connection, "\b", 1);\r
-                                                       t_con->line_cursor--;\r
-                                               }\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                                       else if (*buf_p == 'C') /* cursor right */\r
-                                       {\r
-                                               if (t_con->line_cursor < t_con->line_size)\r
-                                               {\r
-                                                       telnet_write(connection, t_con->line + t_con->line_cursor++, 1);\r
-                                               }\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                                       else if (*buf_p == 'A') /* cursor up */\r
-                                       {\r
-                                               int last_history = (t_con->current_history > 0) ? t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1;\r
-                                               if (t_con->history[last_history])\r
-                                               {\r
-                                                       telnet_clear_line(connection, t_con);\r
-                                                       t_con->line_size = strlen(t_con->history[last_history]);\r
-                                                       t_con->line_cursor = t_con->line_size;\r
-                                                       memcpy(t_con->line, t_con->history[last_history], t_con->line_size + 1);\r
-                                                       telnet_write(connection, t_con->line, t_con->line_size);\r
-                                                       t_con->current_history = last_history;\r
-                                               }\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                                       else if (*buf_p == 'B') /* cursor down */\r
-                                       {\r
-                                               int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE;\r
-                                               if (t_con->history[next_history])\r
-                                               {\r
-                                                       telnet_clear_line(connection, t_con);\r
-                                                       t_con->line_size = strlen(t_con->history[next_history]);\r
-                                                       t_con->line_cursor = t_con->line_size;\r
-                                                       memcpy(t_con->line, t_con->history[next_history], t_con->line_size + 1);\r
-                                                       telnet_write(connection, t_con->line, t_con->line_size);\r
-                                                       t_con->current_history = next_history;\r
-                                               }\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                                       else if (*buf_p == '3')\r
-                                       {\r
-                                               t_con->last_escape = *buf_p;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                               }\r
-                               else if (t_con->last_escape == '3')\r
-                               {\r
-                                       /* Remove character */\r
-                                       if (*buf_p == '~')\r
-                                       {\r
-                                               if (t_con->line_cursor < t_con->line_size)\r
-                                               {\r
-                                                       int i;\r
-                                                       t_con->line_size--;\r
-                                                       /* remove char from line buffer */\r
-                                                       memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor);\r
-                                                       \r
-                                                       /* print remainder of buffer */\r
-                                                       telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);\r
-                                                       /* overwrite last char with whitespace */\r
-                                                       telnet_write(connection, " \b", 2);\r
-                                                       \r
-                                                       /* move back to cursor position*/\r
-                                                       for (i = t_con->line_cursor; i < t_con->line_size; i++)\r
-                                                       {\r
-                                                               telnet_write(connection, "\b", 1);\r
-                                                       }\r
-                                               }\r
-                                                       \r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                               }\r
-                               else if (t_con->last_escape == '\x00')\r
-                               {\r
-                                       if (*buf_p == '[')\r
-                                       {\r
-                                               t_con->last_escape = *buf_p;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               t_con->state = TELNET_STATE_DATA;\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       ERROR("BUG: unexpected value in t_con->last_escape");\r
-                                       t_con->state = TELNET_STATE_DATA;\r
-                               }\r
-                               \r
-                               break;\r
-                       default:\r
-                               ERROR("unknown telnet state");\r
-                               exit(-1);\r
-               }\r
-\r
-               bytes_read--;\r
-               buf_p++;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int telnet_connection_closed(connection_t *connection)\r
-{\r
-       telnet_connection_t *t_con = connection->priv;\r
-       int i;\r
-       \r
-       if (t_con->prompt)\r
-       {\r
-               free(t_con->prompt);\r
-               t_con->prompt = NULL;\r
-       }\r
-       \r
-       for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)\r
-       {\r
-               if (t_con->history[i])\r
-               {\r
-                       free(t_con->history[i]);\r
-                       t_con->history[i] = NULL;\r
-               }\r
-       }\r
-       \r
-       /* if this connection registered a debug-message receiver delete it */\r
-       delete_debug_msg_receiver(connection->cmd_ctx, NULL);\r
-       \r
-       if (connection->priv)\r
-       {\r
-               free(connection->priv);\r
-               connection->priv = NULL;\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: connection->priv == NULL");\r
-       }\r
-       \r
-       target_unregister_event_callback(telnet_target_callback_event_handler, connection->cmd_ctx);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int telnet_set_prompt(connection_t *connection, char *prompt)\r
-{\r
-       telnet_connection_t *t_con = connection->priv;\r
-\r
-       t_con->prompt = strdup(prompt);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int telnet_init(char *banner)\r
-{\r
-       telnet_service_t *telnet_service = malloc(sizeof(telnet_service_t));\r
-       \r
-       if (telnet_port == 0)\r
-       {\r
-               WARNING("no telnet port specified, using default port 4444");\r
-               telnet_port = 4444;\r
-       }\r
-       \r
-       telnet_service->banner = banner;\r
-       \r
-       add_service("telnet", CONNECTION_TELNET, telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int telnet_register_commands(command_context_t *command_context)\r
-{\r
-       register_command(command_context, NULL, "exit", handle_exit_command,\r
-                                        COMMAND_EXEC, "exit telnet session");\r
-       \r
-       register_command(command_context, NULL, "telnet_port", handle_telnet_port_command,\r
-                                        COMMAND_CONFIG, "");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/* daemon configuration command telnet_port */\r
-int handle_telnet_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 0)\r
-               return ERROR_OK;\r
-\r
-       /* only if the port wasn't overwritten by cmdline */\r
-       if (telnet_port == 0)\r
-               telnet_port = strtoul(args[0], NULL, 0);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       return ERROR_COMMAND_CLOSE_CONNECTION;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "telnet_server.h"
+
+#include "server.h"
+#include "log.h"
+#include "command.h"
+#include "target.h"
+#include "target_request.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+
+static unsigned short telnet_port = 0;
+
+int handle_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_telnet_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+static char *negotiate =
+               "\xFF\xFB\x03"          /* IAC WILL Suppress Go Ahead */
+               "\xFF\xFB\x01"          /* IAC WILL Echo */
+               "\xFF\xFD\x03"          /* IAC DO Suppress Go Ahead */
+               "\xFF\xFE\x01";         /* IAC DON'T Echo */
+               
+#define CTRL(c) (c - '@')
+       
+/* The only way we can detect that the socket is closed is the first time
+ * we write to it, we will fail. Subsequent write operations will
+ * succeed. Shudder!
+ */
+int telnet_write(connection_t *connection, void *data, int len)
+{
+       telnet_connection_t *t_con = connection->priv;
+       if (t_con->closed)
+               return ERROR_SERVER_REMOTE_CLOSED;
+
+       if (write_socket(connection->fd, data, len) == len)
+       {
+               return ERROR_OK;
+       }
+       t_con->closed = 1;
+       return ERROR_SERVER_REMOTE_CLOSED;
+}
+
+int telnet_prompt(connection_t *connection)
+{
+       telnet_connection_t *t_con = connection->priv;
+
+       return telnet_write(connection, t_con->prompt, strlen(t_con->prompt));
+}
+
+int telnet_outputline(connection_t *connection, char* line)
+{
+       telnet_write(connection, line, strlen(line));
+       return telnet_write(connection, "\r\n\0", 3);
+}
+
+int telnet_output(struct command_context_s *cmd_ctx, char* line)
+{
+       connection_t *connection = cmd_ctx->output_handler_priv;
+       
+       return telnet_outputline(connection, line);
+}
+
+void telnet_log_callback(void *priv, const char *file, int line, 
+               const char *function, const char *format, va_list args)
+{
+       connection_t *connection = priv;
+       char *t = alloc_printf(format, args);
+       char *t2;
+       if (t == NULL)
+               return;
+       t2=t;
+       char *endline;
+       do 
+       {
+               if ((endline=strchr(t2, '\n'))!=NULL)
+               {
+                       *endline=0;
+               }
+               telnet_outputline(connection, t2);
+               t2=endline+1;
+       } while (endline);
+       
+       free(t);
+}
+
+int telnet_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)
+{
+       struct command_context_s *cmd_ctx = priv;
+       connection_t *connection = cmd_ctx->output_handler_priv;
+       telnet_connection_t *t_con = connection->priv;
+       
+       switch (event)
+       {
+               case TARGET_EVENT_HALTED:
+                       target_arch_state(target);
+                       if (!t_con->suppress_prompt)
+                               telnet_prompt(connection);
+                       break;
+               case TARGET_EVENT_RESUMED:
+                       if (!t_con->suppress_prompt)
+                               telnet_prompt(connection);
+                       break;
+               default:
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int telnet_new_connection(connection_t *connection)
+{
+       telnet_connection_t *telnet_connection = malloc(sizeof(telnet_connection_t));
+       telnet_service_t *telnet_service = connection->service->priv;
+       int i;
+       
+       connection->priv = telnet_connection;
+       
+       /* initialize telnet connection information */
+       telnet_connection->closed = 0;
+       telnet_connection->line_size = 0;
+       telnet_connection->line_cursor = 0;
+       telnet_connection->option_size = 0;
+       telnet_connection->prompt = strdup("> ");
+       telnet_connection->suppress_prompt = 0;
+       telnet_connection->state = TELNET_STATE_DATA;
+       
+       /* output goes through telnet connection */
+       command_set_output_handler(connection->cmd_ctx, telnet_output, connection);
+       
+       /* negotiate telnet options */
+       telnet_write(connection, negotiate, strlen(negotiate));
+       
+       /* print connection banner */
+       if (telnet_service->banner)
+       {
+               telnet_write(connection, telnet_service->banner, strlen(telnet_service->banner));
+               telnet_write(connection, "\r\n\0", 3);
+       }
+       
+       telnet_prompt(connection);
+       
+       /* initialize history */
+       for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)
+       {
+               telnet_connection->history[i] = NULL;
+       }
+       telnet_connection->next_history = 0;
+       telnet_connection->current_history = 0;
+
+       target_register_event_callback(telnet_target_callback_event_handler, connection->cmd_ctx);
+       
+       return ERROR_OK;
+}
+
+void telnet_clear_line(connection_t *connection, telnet_connection_t *t_con)
+{
+       /* move to end of line */
+       if (t_con->line_cursor < t_con->line_size)
+       {
+               telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);
+       }
+                                                       
+       /* backspace, overwrite with space, backspace */
+       while (t_con->line_size > 0)
+       {
+               telnet_write(connection, "\b \b", 3);
+               t_con->line_size--;
+       }
+       t_con->line_cursor = 0;
+}
+
+int telnet_input(connection_t *connection)
+{
+       int bytes_read;
+       char buffer[TELNET_BUFFER_SIZE];
+       char *buf_p;
+       telnet_connection_t *t_con = connection->priv;
+       command_context_t *command_context = connection->cmd_ctx;
+       
+       bytes_read = read_socket(connection->fd, buffer, TELNET_BUFFER_SIZE);
+       
+       if (bytes_read == 0)
+               return ERROR_SERVER_REMOTE_CLOSED;
+       else if (bytes_read == -1)
+       {
+               ERROR("error during read: %s", strerror(errno));
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+       
+       buf_p = buffer;
+       while (bytes_read)
+       {
+               switch (t_con->state)
+               {
+                       case TELNET_STATE_DATA:
+                               if (*buf_p == '\xff')
+                               {
+                                       t_con->state = TELNET_STATE_IAC;
+                               }
+                               else
+                               {
+                                       if (isprint(*buf_p)) /* printable character */
+                                       {
+                                               telnet_write(connection, buf_p, 1);
+                                               if (t_con->line_cursor == t_con->line_size)
+                                               {
+                                                       t_con->line[t_con->line_size++] = *buf_p;
+                                                       t_con->line_cursor++;
+                                               }
+                                               else
+                                               {
+                                                       int i;
+                                                       memmove(t_con->line + t_con->line_cursor + 1, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);
+                                                       t_con->line[t_con->line_cursor++] = *buf_p;
+                                                       t_con->line_size++;
+                                                       telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);
+                                                       for (i = t_con->line_cursor; i < t_con->line_size; i++)
+                                                       {
+                                                               telnet_write(connection, "\b", 1);
+                                                       }
+                                               }
+                                       }
+                                       else /* non-printable */
+                                       {
+                                               if (*buf_p == 0x1b) /* escape */
+                                               {
+                                                       t_con->state = TELNET_STATE_ESCAPE;
+                                                       t_con->last_escape = '\x00';
+                                               }
+                                               else if ((*buf_p == 0xd) || (*buf_p == 0xa)) /* CR/LF */
+                                               {
+                                                       int retval;
+                                                       
+                                                       /* skip over combinations with CR/LF + NUL */
+                                                       if (((*(buf_p + 1) == 0xa) || (*(buf_p + 1) == 0xd)) && (bytes_read > 1))
+                                                       {
+                                                               buf_p++;
+                                                               bytes_read--;
+                                                       }
+                                                       if ((*(buf_p + 1) == 0) && (bytes_read > 1))
+                                                       {
+                                                               buf_p++;
+                                                               bytes_read--;
+                                                       }
+                                                       t_con->line[t_con->line_size] = 0;
+                                                       
+                                                       telnet_write(connection, "\r\n\x00", 3);
+                                                       
+                                                       if (strcmp(t_con->line, "history") == 0)
+                                                       {
+                                                               int i;
+                                                               for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)
+                                                               {
+                                                                       if (t_con->history[i])
+                                                                       {
+                                                                               telnet_write(connection, t_con->history[i], strlen(t_con->history[i]));
+                                                                               telnet_write(connection, "\r\n\x00", 3);
+                                                                       }
+                                                               }
+                                                               telnet_prompt(connection);
+                                                               t_con->line_size = 0;
+                                                               t_con->line_cursor = 0;
+                                                               continue;
+                                                       }
+                                                       
+                                                       log_add_callback(telnet_log_callback, connection);
+                                                       t_con->suppress_prompt = 1;
+
+                                                       retval = command_run_line(command_context, t_con->line);
+                                                       
+                                                       log_remove_callback(telnet_log_callback, connection);
+                                                       t_con->suppress_prompt = 0;
+
+                                                       if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
+                                                       {
+                                                               return ERROR_SERVER_REMOTE_CLOSED;
+                                                       }
+                                                       
+                                                       /* Save only non-blank lines in the history */
+                                                       if (t_con->line_size > 0)
+                                                       {
+                                                               /* if the history slot is already taken, free it */
+                                                               if (t_con->history[t_con->next_history])
+                                                               {
+                                                                       free(t_con->history[t_con->next_history]);
+                                                               }
+               
+                                                               /* add line to history */
+                                                               t_con->history[t_con->next_history] = strdup(t_con->line);
+
+                                                               /* wrap history at TELNET_LINE_HISTORY_SIZE */
+                                                               t_con->next_history = (t_con->next_history + 1) % TELNET_LINE_HISTORY_SIZE;
+                                                       
+                                                               /* current history line starts at the new entry */
+                                                               t_con->current_history = t_con->next_history;
+                                                       
+                                                               if (t_con->history[t_con->current_history])
+                                                               {
+                                                                       free(t_con->history[t_con->current_history]);
+                                                               }
+                                                               t_con->history[t_con->current_history] = strdup("");
+                                                       }
+                                                       
+                                                       int t = telnet_prompt(connection);
+                                                       if (t == ERROR_SERVER_REMOTE_CLOSED)
+                                                               return t;
+                                                       
+                                                       t_con->line_size = 0;
+                                                       t_con->line_cursor = 0;
+                                               }
+                                               else if ((*buf_p == 0x7f) || (*buf_p == 0x8)) /* delete character */
+                                               {
+                                                       if (t_con->line_cursor > 0)
+                                                       {
+                                                               if (t_con->line_cursor != t_con->line_size)
+                                                               {
+                                                                       int i;
+                                                                       telnet_write(connection, "\b", 1);
+                                                                       t_con->line_cursor--;
+                                                                       t_con->line_size--;
+                                                                       memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor);
+                                                                       
+                                                                       telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);
+                                                                       telnet_write(connection, " \b", 2);
+                                                                       for (i = t_con->line_cursor; i < t_con->line_size; i++)
+                                                                       {
+                                                                               telnet_write(connection, "\b", 1);
+                                                                       }
+                                                               }
+                                                               else
+                                                               {
+                                                                       t_con->line_size--;
+                                                                       t_con->line_cursor--;
+                                                                       /* back space: move the 'printer' head one char back, overwrite with space, move back again */
+                                                                       telnet_write(connection, "\b \b", 3);
+                                                               }
+                                                       }
+                                               }
+                                               else if (*buf_p == 0x15) /* clear line */
+                                               {
+                                                       telnet_clear_line(connection, t_con);
+                                               }
+                                               else if (*buf_p == CTRL('B')) /* cursor left */
+                                               {
+                                                       if (t_con->line_cursor > 0)
+                                                       {
+                                                               telnet_write(connection, "\b", 1);
+                                                               t_con->line_cursor--;
+                                                       }
+                                                       t_con->state = TELNET_STATE_DATA;
+                                               }
+                                               else if (*buf_p == CTRL('F')) /* cursor right */
+                                               {
+                                                       if (t_con->line_cursor < t_con->line_size)
+                                                       {
+                                                               telnet_write(connection, t_con->line + t_con->line_cursor++, 1);
+                                                       }
+                                                       t_con->state = TELNET_STATE_DATA;
+                                               }
+                                               else
+                                               {
+                                                       DEBUG("unhandled nonprintable: %2.2x", *buf_p);
+                                               }
+                                       }
+                               }
+                               break;
+                       case TELNET_STATE_IAC:
+                               switch (*buf_p)
+                               {
+                                       case '\xfe':
+                                               t_con->state = TELNET_STATE_DONT;
+                                               break;
+                                       case '\xfd':
+                                               t_con->state = TELNET_STATE_DO;
+                                               break;
+                                       case '\xfc':
+                                               t_con->state = TELNET_STATE_WONT;
+                                               break;
+                                       case '\xfb':
+                                               t_con->state = TELNET_STATE_WILL;
+                                               break;
+                               }
+                               break;
+                       case TELNET_STATE_SB:
+                               break;
+                       case TELNET_STATE_SE:
+                               break;
+                       case TELNET_STATE_WILL:
+                       case TELNET_STATE_WONT:
+                       case TELNET_STATE_DO:
+                       case TELNET_STATE_DONT:
+                               t_con->state = TELNET_STATE_DATA;
+                               break;
+                       case TELNET_STATE_ESCAPE:
+                               if (t_con->last_escape == '[')
+                               {
+                                       if (*buf_p == 'D') /* cursor left */
+                                       {
+                                               if (t_con->line_cursor > 0)
+                                               {
+                                                       telnet_write(connection, "\b", 1);
+                                                       t_con->line_cursor--;
+                                               }
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                                       else if (*buf_p == 'C') /* cursor right */
+                                       {
+                                               if (t_con->line_cursor < t_con->line_size)
+                                               {
+                                                       telnet_write(connection, t_con->line + t_con->line_cursor++, 1);
+                                               }
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                                       else if (*buf_p == 'A') /* cursor up */
+                                       {
+                                               int last_history = (t_con->current_history > 0) ? t_con->current_history - 1 : TELNET_LINE_HISTORY_SIZE-1;
+                                               if (t_con->history[last_history])
+                                               {
+                                                       telnet_clear_line(connection, t_con);
+                                                       t_con->line_size = strlen(t_con->history[last_history]);
+                                                       t_con->line_cursor = t_con->line_size;
+                                                       memcpy(t_con->line, t_con->history[last_history], t_con->line_size + 1);
+                                                       telnet_write(connection, t_con->line, t_con->line_size);
+                                                       t_con->current_history = last_history;
+                                               }
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                                       else if (*buf_p == 'B') /* cursor down */
+                                       {
+                                               int next_history = (t_con->current_history + 1) % TELNET_LINE_HISTORY_SIZE;
+                                               if (t_con->history[next_history])
+                                               {
+                                                       telnet_clear_line(connection, t_con);
+                                                       t_con->line_size = strlen(t_con->history[next_history]);
+                                                       t_con->line_cursor = t_con->line_size;
+                                                       memcpy(t_con->line, t_con->history[next_history], t_con->line_size + 1);
+                                                       telnet_write(connection, t_con->line, t_con->line_size);
+                                                       t_con->current_history = next_history;
+                                               }
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                                       else if (*buf_p == '3')
+                                       {
+                                               t_con->last_escape = *buf_p;
+                                       }
+                                       else
+                                       {
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                               }
+                               else if (t_con->last_escape == '3')
+                               {
+                                       /* Remove character */
+                                       if (*buf_p == '~')
+                                       {
+                                               if (t_con->line_cursor < t_con->line_size)
+                                               {
+                                                       int i;
+                                                       t_con->line_size--;
+                                                       /* remove char from line buffer */
+                                                       memmove(t_con->line + t_con->line_cursor, t_con->line + t_con->line_cursor + 1, t_con->line_size - t_con->line_cursor);
+                                                       
+                                                       /* print remainder of buffer */
+                                                       telnet_write(connection, t_con->line + t_con->line_cursor, t_con->line_size - t_con->line_cursor);
+                                                       /* overwrite last char with whitespace */
+                                                       telnet_write(connection, " \b", 2);
+                                                       
+                                                       /* move back to cursor position*/
+                                                       for (i = t_con->line_cursor; i < t_con->line_size; i++)
+                                                       {
+                                                               telnet_write(connection, "\b", 1);
+                                                       }
+                                               }
+                                                       
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                                       else
+                                       {
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                               }
+                               else if (t_con->last_escape == '\x00')
+                               {
+                                       if (*buf_p == '[')
+                                       {
+                                               t_con->last_escape = *buf_p;
+                                       }
+                                       else
+                                       {
+                                               t_con->state = TELNET_STATE_DATA;
+                                       }
+                               }
+                               else
+                               {
+                                       ERROR("BUG: unexpected value in t_con->last_escape");
+                                       t_con->state = TELNET_STATE_DATA;
+                               }
+                               
+                               break;
+                       default:
+                               ERROR("unknown telnet state");
+                               exit(-1);
+               }
+
+               bytes_read--;
+               buf_p++;
+       }
+       
+       return ERROR_OK;
+}
+
+int telnet_connection_closed(connection_t *connection)
+{
+       telnet_connection_t *t_con = connection->priv;
+       int i;
+       
+       if (t_con->prompt)
+       {
+               free(t_con->prompt);
+               t_con->prompt = NULL;
+       }
+       
+       for (i = 0; i < TELNET_LINE_HISTORY_SIZE; i++)
+       {
+               if (t_con->history[i])
+               {
+                       free(t_con->history[i]);
+                       t_con->history[i] = NULL;
+               }
+       }
+       
+       /* if this connection registered a debug-message receiver delete it */
+       delete_debug_msg_receiver(connection->cmd_ctx, NULL);
+       
+       if (connection->priv)
+       {
+               free(connection->priv);
+               connection->priv = NULL;
+       }
+       else
+       {
+               ERROR("BUG: connection->priv == NULL");
+       }
+       
+       target_unregister_event_callback(telnet_target_callback_event_handler, connection->cmd_ctx);
+
+       return ERROR_OK;
+}
+
+int telnet_set_prompt(connection_t *connection, char *prompt)
+{
+       telnet_connection_t *t_con = connection->priv;
+
+       t_con->prompt = strdup(prompt);
+       
+       return ERROR_OK;
+}
+
+int telnet_init(char *banner)
+{
+       telnet_service_t *telnet_service = malloc(sizeof(telnet_service_t));
+       
+       if (telnet_port == 0)
+       {
+               WARNING("no telnet port specified, using default port 4444");
+               telnet_port = 4444;
+       }
+       
+       telnet_service->banner = banner;
+       
+       add_service("telnet", CONNECTION_TELNET, telnet_port, 1, telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service);
+       
+       return ERROR_OK;
+}
+
+int telnet_register_commands(command_context_t *command_context)
+{
+       register_command(command_context, NULL, "exit", handle_exit_command,
+                                        COMMAND_EXEC, "exit telnet session");
+       
+       register_command(command_context, NULL, "telnet_port", handle_telnet_port_command,
+                                        COMMAND_CONFIG, "");
+       
+       return ERROR_OK;
+}
+
+/* daemon configuration command telnet_port */
+int handle_telnet_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               return ERROR_OK;
+
+       /* only if the port wasn't overwritten by cmdline */
+       if (telnet_port == 0)
+               telnet_port = strtoul(args[0], NULL, 0);
+
+       return ERROR_OK;
+}
+
+int handle_exit_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       return ERROR_COMMAND_CLOSE_CONNECTION;
+}
index 11e376a6e6b935e9107f60c1c1d01721d0da924d..d02518a2180c8a91f3a7efb41d3ca9d446e32422 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2008 digenius technology GmbH.                          *\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 "arm11.h"\r
-#include "jtag.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-\r
-#if 0\r
-#define FNC_INFO    DEBUG("-")\r
-#else\r
-#define FNC_INFO\r
-#endif\r
-\r
-#if 1\r
-#define FNC_INFO_NOTIMPLEMENTED    do { DEBUG("NOT IMPLEMENTED"); /*exit(-1);*/ } while (0)\r
-#else\r
-#define FNC_INFO_NOTIMPLEMENTED\r
-#endif\r
-\r
-static void arm11_on_enter_debug_state(arm11_common_t * arm11);\r
-\r
-\r
-#define ARM11_HANDLER(x)       \\r
-    .x                         = arm11_##x\r
-\r
-target_type_t arm11_target =\r
-{\r
-    .name                      = "arm11",\r
-\r
-    ARM11_HANDLER(poll),\r
-    ARM11_HANDLER(arch_state),\r
-\r
-    ARM11_HANDLER(target_request_data),\r
-\r
-    ARM11_HANDLER(halt),\r
-    ARM11_HANDLER(resume),\r
-    ARM11_HANDLER(step),\r
-\r
-    ARM11_HANDLER(assert_reset),\r
-    ARM11_HANDLER(deassert_reset),\r
-    ARM11_HANDLER(soft_reset_halt),\r
-    ARM11_HANDLER(prepare_reset_halt),\r
-       \r
-    ARM11_HANDLER(get_gdb_reg_list),\r
-       \r
-    ARM11_HANDLER(read_memory),\r
-    ARM11_HANDLER(write_memory),\r
-       \r
-    ARM11_HANDLER(bulk_write_memory),\r
-       \r
-    ARM11_HANDLER(checksum_memory),\r
-\r
-    ARM11_HANDLER(add_breakpoint),\r
-    ARM11_HANDLER(remove_breakpoint),\r
-    ARM11_HANDLER(add_watchpoint),\r
-    ARM11_HANDLER(remove_watchpoint),\r
-\r
-    ARM11_HANDLER(run_algorithm),\r
-       \r
-    ARM11_HANDLER(register_commands),\r
-    ARM11_HANDLER(target_command),\r
-    ARM11_HANDLER(init_target),\r
-    ARM11_HANDLER(quit),\r
-};\r
-\r
-int arm11_regs_arch_type = -1;\r
-\r
-\r
-enum arm11_regtype\r
-{\r
-    ARM11_REGISTER_CORE,\r
-    ARM11_REGISTER_CPSR,\r
-\r
-    ARM11_REGISTER_FX,\r
-    ARM11_REGISTER_FPS,\r
-\r
-    ARM11_REGISTER_FIQ,\r
-    ARM11_REGISTER_SVC,\r
-    ARM11_REGISTER_ABT,\r
-    ARM11_REGISTER_IRQ,\r
-    ARM11_REGISTER_UND,\r
-    ARM11_REGISTER_MON,\r
-\r
-    ARM11_REGISTER_SPSR_FIQ,\r
-    ARM11_REGISTER_SPSR_SVC,\r
-    ARM11_REGISTER_SPSR_ABT,\r
-    ARM11_REGISTER_SPSR_IRQ,\r
-    ARM11_REGISTER_SPSR_UND,\r
-    ARM11_REGISTER_SPSR_MON,\r
-\r
-    /* debug regs */\r
-    ARM11_REGISTER_DSCR,\r
-    ARM11_REGISTER_WDTR,\r
-    ARM11_REGISTER_RDTR,\r
-};\r
-\r
-\r
-typedef struct arm11_reg_defs_s\r
-{\r
-    char *                     name;\r
-    u32                                num;\r
-    int                                gdb_num;\r
-    enum arm11_regtype         type;\r
-} arm11_reg_defs_t;\r
-\r
-/* update arm11_regcache_ids when changing this */\r
-static const arm11_reg_defs_t arm11_reg_defs[] =\r
-{\r
-    {"r0",     0,      0,      ARM11_REGISTER_CORE},\r
-    {"r1",     1,      1,      ARM11_REGISTER_CORE},\r
-    {"r2",     2,      2,      ARM11_REGISTER_CORE},\r
-    {"r3",     3,      3,      ARM11_REGISTER_CORE},\r
-    {"r4",     4,      4,      ARM11_REGISTER_CORE},\r
-    {"r5",     5,      5,      ARM11_REGISTER_CORE},\r
-    {"r6",     6,      6,      ARM11_REGISTER_CORE},\r
-    {"r7",     7,      7,      ARM11_REGISTER_CORE},\r
-    {"r8",     8,      8,      ARM11_REGISTER_CORE},\r
-    {"r9",     9,      9,      ARM11_REGISTER_CORE},\r
-    {"r10",    10,     10,     ARM11_REGISTER_CORE},\r
-    {"r11",    11,     11,     ARM11_REGISTER_CORE},\r
-    {"r12",    12,     12,     ARM11_REGISTER_CORE},\r
-    {"sp",     13,     13,     ARM11_REGISTER_CORE},\r
-    {"lr",     14,     14,     ARM11_REGISTER_CORE},\r
-    {"pc",     15,     15,     ARM11_REGISTER_CORE},\r
-\r
-#if ARM11_REGCACHE_FREGS\r
-    {"f0",     0,      16,     ARM11_REGISTER_FX},\r
-    {"f1",     1,      17,     ARM11_REGISTER_FX},\r
-    {"f2",     2,      18,     ARM11_REGISTER_FX},\r
-    {"f3",     3,      19,     ARM11_REGISTER_FX},\r
-    {"f4",     4,      20,     ARM11_REGISTER_FX},\r
-    {"f5",     5,      21,     ARM11_REGISTER_FX},\r
-    {"f6",     6,      22,     ARM11_REGISTER_FX},\r
-    {"f7",     7,      23,     ARM11_REGISTER_FX},\r
-    {"fps",    0,      24,     ARM11_REGISTER_FPS},\r
-#endif\r
-\r
-    {"cpsr",   0,      25,     ARM11_REGISTER_CPSR},\r
-\r
-#if ARM11_REGCACHE_MODEREGS\r
-    {"r8_fiq", 8,      -1,     ARM11_REGISTER_FIQ},\r
-    {"r9_fiq", 9,      -1,     ARM11_REGISTER_FIQ},\r
-    {"r10_fiq",        10,     -1,     ARM11_REGISTER_FIQ},\r
-    {"r11_fiq",        11,     -1,     ARM11_REGISTER_FIQ},\r
-    {"r12_fiq",        12,     -1,     ARM11_REGISTER_FIQ},\r
-    {"r13_fiq",        13,     -1,     ARM11_REGISTER_FIQ},\r
-    {"r14_fiq",        14,     -1,     ARM11_REGISTER_FIQ},\r
-    {"spsr_fiq", 0,    -1,     ARM11_REGISTER_SPSR_FIQ},\r
-\r
-    {"r13_svc",        13,     -1,     ARM11_REGISTER_SVC},\r
-    {"r14_svc",        14,     -1,     ARM11_REGISTER_SVC},\r
-    {"spsr_svc", 0,    -1,     ARM11_REGISTER_SPSR_SVC},\r
-\r
-    {"r13_abt",        13,     -1,     ARM11_REGISTER_ABT},\r
-    {"r14_abt",        14,     -1,     ARM11_REGISTER_ABT},\r
-    {"spsr_abt", 0,    -1,     ARM11_REGISTER_SPSR_ABT},\r
-\r
-    {"r13_irq",        13,     -1,     ARM11_REGISTER_IRQ},\r
-    {"r14_irq",        14,     -1,     ARM11_REGISTER_IRQ},\r
-    {"spsr_irq", 0,    -1,     ARM11_REGISTER_SPSR_IRQ},\r
-\r
-    {"r13_und",        13,     -1,     ARM11_REGISTER_UND},\r
-    {"r14_und",        14,     -1,     ARM11_REGISTER_UND},\r
-    {"spsr_und", 0,    -1,     ARM11_REGISTER_SPSR_UND},\r
-\r
-    /* ARM1176 only */\r
-    {"r13_mon",        13,     -1,     ARM11_REGISTER_MON},\r
-    {"r14_mon",        14,     -1,     ARM11_REGISTER_MON},\r
-    {"spsr_mon", 0,    -1,     ARM11_REGISTER_SPSR_MON},\r
-#endif\r
-\r
-    /* Debug Registers */\r
-    {"dscr",   0,      -1,     ARM11_REGISTER_DSCR},\r
-    {"wdtr",   0,      -1,     ARM11_REGISTER_WDTR},\r
-    {"rdtr",   0,      -1,     ARM11_REGISTER_RDTR},\r
-};\r
-\r
-enum arm11_regcache_ids\r
-{\r
-    ARM11_RC_R0,\r
-    ARM11_RC_RX                        = ARM11_RC_R0,\r
-\r
-    ARM11_RC_R1,\r
-    ARM11_RC_R2,\r
-    ARM11_RC_R3,\r
-    ARM11_RC_R4,\r
-    ARM11_RC_R5,\r
-    ARM11_RC_R6,\r
-    ARM11_RC_R7,\r
-    ARM11_RC_R8,\r
-    ARM11_RC_R9,\r
-    ARM11_RC_R10,\r
-    ARM11_RC_R11,\r
-    ARM11_RC_R12,\r
-    ARM11_RC_R13,\r
-    ARM11_RC_SP                        = ARM11_RC_R13,\r
-    ARM11_RC_R14,\r
-    ARM11_RC_LR                        = ARM11_RC_R14,\r
-    ARM11_RC_R15,\r
-    ARM11_RC_PC                        = ARM11_RC_R15,\r
-\r
-#if ARM11_REGCACHE_FREGS\r
-    ARM11_RC_F0,\r
-    ARM11_RC_FX                        = ARM11_RC_F0,\r
-    ARM11_RC_F1,\r
-    ARM11_RC_F2,\r
-    ARM11_RC_F3,\r
-    ARM11_RC_F4,\r
-    ARM11_RC_F5,\r
-    ARM11_RC_F6,\r
-    ARM11_RC_F7,\r
-    ARM11_RC_FPS,\r
-#endif\r
-\r
-    ARM11_RC_CPSR,\r
-\r
-#if ARM11_REGCACHE_MODEREGS\r
-    ARM11_RC_R8_FIQ,\r
-    ARM11_RC_R9_FIQ,\r
-    ARM11_RC_R10_FIQ,\r
-    ARM11_RC_R11_FIQ,\r
-    ARM11_RC_R12_FIQ,\r
-    ARM11_RC_R13_FIQ,\r
-    ARM11_RC_R14_FIQ,\r
-    ARM11_RC_SPSR_FIQ,\r
-\r
-    ARM11_RC_R13_SVC,\r
-    ARM11_RC_R14_SVC,\r
-    ARM11_RC_SPSR_SVC,\r
-\r
-    ARM11_RC_R13_ABT,\r
-    ARM11_RC_R14_ABT,\r
-    ARM11_RC_SPSR_ABT,\r
-\r
-    ARM11_RC_R13_IRQ,\r
-    ARM11_RC_R14_IRQ,\r
-    ARM11_RC_SPSR_IRQ,\r
-\r
-    ARM11_RC_R13_UND,\r
-    ARM11_RC_R14_UND,\r
-    ARM11_RC_SPSR_UND,\r
-\r
-    ARM11_RC_R13_MON,\r
-    ARM11_RC_R14_MON,\r
-    ARM11_RC_SPSR_MON,\r
-#endif\r
-\r
-    ARM11_RC_DSCR,\r
-    ARM11_RC_WDTR,\r
-    ARM11_RC_RDTR,\r
-\r
-\r
-    ARM11_RC_MAX,\r
-};\r
-\r
-#define ARM11_GDB_REGISTER_COUNT       26\r
-\r
-u8 arm11_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r
-\r
-reg_t arm11_gdb_dummy_fp_reg =\r
-{\r
-    "GDB dummy floating-point register", arm11_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0\r
-};\r
-\r
-u8 arm11_gdb_dummy_fps_value[] = {0, 0, 0, 0};\r
-\r
-reg_t arm11_gdb_dummy_fps_reg =\r
-{\r
-    "GDB dummy floating-point status register", arm11_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0\r
-};\r
-\r
-\r
-\r
-/** Check and if necessary take control of the system\r
- *\r
- * \param arm11                Target state variable.\r
- * \param dscr         If the current DSCR content is\r
- *                     available a pointer to a word holding the\r
- *                     DSCR can be passed. Otherwise use NULL.\r
- */\r
-void arm11_check_init(arm11_common_t * arm11, u32 * dscr)\r
-{\r
-    FNC_INFO;\r
-\r
-    u32                        dscr_local_tmp_copy;\r
-\r
-    if (!dscr)\r
-    {\r
-       dscr = &dscr_local_tmp_copy;\r
-       *dscr = arm11_read_DSCR(arm11);\r
-    }\r
-\r
-    if (!(*dscr & ARM11_DSCR_MODE_SELECT))\r
-    {\r
-       DEBUG("Bringing target into debug mode");\r
-\r
-       *dscr |= ARM11_DSCR_MODE_SELECT;                /* Halt debug-mode */\r
-       arm11_write_DSCR(arm11, *dscr);\r
-\r
-       /* add further reset initialization here */\r
-\r
-       if (*dscr & ARM11_DSCR_CORE_HALTED)\r
-       {\r
-           arm11->target->state        = TARGET_HALTED;\r
-           arm11->target->debug_reason = arm11_get_DSCR_debug_reason(*dscr);\r
-       }\r
-       else\r
-       {\r
-           arm11->target->state        = TARGET_RUNNING;\r
-           arm11->target->debug_reason = DBG_REASON_NOTHALTED;\r
-       }\r
-\r
-       arm11_sc7_clear_bw(arm11);\r
-    }\r
-}\r
-\r
-\r
-\r
-#define R(x) \\r
-    (arm11->reg_values[ARM11_RC_##x])\r
-\r
-/** Save processor state.\r
-  *\r
-  * This is called when the HALT instruction has succeeded\r
-  * or on other occasions that stop the processor.\r
-  *\r
-  */\r
-static void arm11_on_enter_debug_state(arm11_common_t * arm11)\r
-{\r
-    FNC_INFO;\r
-\r
-    {size_t i;\r
-    for(i = 0; i < asizeof(arm11->reg_values); i++)\r
-    {\r
-       arm11->reg_list[i].valid        = 1;\r
-       arm11->reg_list[i].dirty        = 0;\r
-    }}\r
-\r
-    /* Save DSCR */\r
-\r
-    R(DSCR) = arm11_read_DSCR(arm11);\r
-\r
-    /* Save wDTR */\r
-\r
-    if (R(DSCR) & ARM11_DSCR_WDTR_FULL)\r
-    {\r
-       arm11_add_debug_SCAN_N(arm11, 0x05, -1);\r
-\r
-       arm11_add_IR(arm11, ARM11_INTEST, -1);\r
-\r
-       scan_field_t    chain5_fields[3];\r
-\r
-       arm11_setup_field(arm11, 32, NULL, &R(WDTR),    chain5_fields + 0);\r
-       arm11_setup_field(arm11,  1, NULL, NULL,        chain5_fields + 1);\r
-       arm11_setup_field(arm11,  1, NULL, NULL,        chain5_fields + 2);\r
-\r
-       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);\r
-    }\r
-    else\r
-    {\r
-       arm11->reg_list[ARM11_RC_WDTR].valid    = 0;\r
-    }\r
-\r
-\r
-    /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE */\r
-    /* ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", but not to issue ITRs\r
-       ARM1136 seems to require this to issue ITR's as well */\r
-\r
-    u32 new_dscr = R(DSCR) | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE;\r
-\r
-    /* this executes JTAG queue: */ \r
-\r
-    arm11_write_DSCR(arm11, new_dscr);\r
-\r
-//    jtag_execute_queue();\r
-\r
-\r
-\r
-//    DEBUG("SAVE DSCR %08x", R(DSCR));\r
-\r
-//    if (R(DSCR) & ARM11_DSCR_WDTR_FULL)\r
-//     DEBUG("SAVE wDTR %08x", R(WDTR));\r
-\r
-\r
-    /* From the spec:\r
-       Before executing any instruction in debug state you have to drain the write buffer.\r
-        This ensures that no imprecise Data Aborts can return at a later point:*/\r
-\r
-    /** \todo TODO: Test drain write buffer. */\r
-\r
-#if 0\r
-    while (1)\r
-    {\r
-       /* MRC p14,0,R0,c5,c10,0 */\r
-//     arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000);\r
-\r
-       /* mcr     15, 0, r0, cr7, cr10, {4} */\r
-       arm11_run_instr_no_data1(arm11, 0xee070f9a);\r
-               \r
-       u32 dscr = arm11_read_DSCR(arm11);\r
-\r
-       DEBUG("DRAIN, DSCR %08x", dscr);\r
-\r
-       if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT)\r
-       {\r
-           arm11_run_instr_no_data1(arm11, 0xe320f000);\r
-\r
-           dscr = arm11_read_DSCR(arm11);\r
-\r
-           DEBUG("DRAIN, DSCR %08x (DONE)", dscr);\r
-\r
-           break;\r
-       }\r
-    }\r
-#endif\r
-\r
-\r
-    arm11_run_instr_data_prepare(arm11);\r
-\r
-    /* save r0 - r14 */\r
-\r
-\r
-    /** \todo TODO: handle other mode registers */\r
-\r
-    {size_t i;\r
-    for (i = 0; i < 15; i++)\r
-    {\r
-       /* MCR p14,0,R?,c0,c5,0 */\r
-       arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);\r
-    }}\r
-\r
-\r
-    /* save rDTR */\r
-\r
-    /* check rDTRfull in DSCR */\r
-\r
-    if (R(DSCR) & ARM11_DSCR_RDTR_FULL)\r
-    {\r
-       /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */\r
-       arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));\r
-    }\r
-    else\r
-    {\r
-       arm11->reg_list[ARM11_RC_RDTR].valid    = 0;\r
-    }\r
-\r
-    /* save CPSR */\r
-\r
-    /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */\r
-    arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));\r
-\r
-    /* save PC */\r
-\r
-    /* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */\r
-    arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));\r
-\r
-    /* adjust PC depending on ARM state */\r
-\r
-    if (R(CPSR) & ARM11_CPSR_J)        /* Java state */\r
-    {\r
-       arm11->reg_values[ARM11_RC_PC] -= 0;\r
-    }\r
-    else if (R(CPSR) & ARM11_CPSR_T)   /* Thumb state */\r
-    {\r
-       arm11->reg_values[ARM11_RC_PC] -= 4;\r
-    }\r
-    else                                       /* ARM state */\r
-    {\r
-       arm11->reg_values[ARM11_RC_PC] -= 8;\r
-    }\r
-\r
-//    DEBUG("SAVE PC   %08x", R(PC));\r
-\r
-    arm11_run_instr_data_finish(arm11);\r
-\r
-\r
-    {size_t i;\r
-    for(i = 0; i < ARM11_REGCACHE_COUNT; i++)\r
-    {\r
-       if (!arm11->reg_list[i].valid)\r
-       {\r
-           if (arm11->reg_history[i].valid)\r
-               INFO("%8s INVALID    (%08x)", arm11_reg_defs[i].name, arm11->reg_history[i].value);\r
-       }\r
-       else\r
-       {\r
-           if (arm11->reg_history[i].valid)\r
-           {\r
-               if (arm11->reg_history[i].value != arm11->reg_values[i])\r
-                   INFO("%8s %08x (%08x)", arm11_reg_defs[i].name, arm11->reg_values[i], arm11->reg_history[i].value);\r
-           }\r
-           else\r
-           {\r
-               INFO("%8s %08x (INVALID)", arm11_reg_defs[i].name, arm11->reg_values[i]);\r
-           }\r
-       }\r
-    }}\r
-}\r
-\r
-\r
-/** Restore processor state\r
-  *\r
-  * This is called in preparation for the RESTART function.\r
-  *\r
-  */\r
-void arm11_leave_debug_state(arm11_common_t * arm11)\r
-{\r
-    FNC_INFO;\r
-\r
-    arm11_run_instr_data_prepare(arm11);\r
-\r
-    /** \todo TODO: handle other mode registers */\r
-\r
-    /* restore R1 - R14 */\r
-    {size_t i;\r
-    for (i = 1; i < 15; i++)\r
-    {\r
-       if (!arm11->reg_list[ARM11_RC_RX + i].dirty)\r
-           continue;\r
-\r
-       /* MRC p14,0,r?,c0,c5,0 */\r
-       arm11_run_instr_data_to_core1(arm11, 0xee100e15 | (i << 12), R(RX + i));\r
-\r
-//     DEBUG("RESTORE R%d %08x", i, R(RX + i));\r
-    }}\r
-\r
-    arm11_run_instr_data_finish(arm11);\r
-\r
-\r
-    /* spec says clear wDTR and rDTR; we assume they are clear as\r
-       otherwide out programming would be sloppy */\r
-\r
-    {\r
-       u32 DSCR = arm11_read_DSCR(arm11);\r
-\r
-       if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))\r
-       {\r
-           ERROR("wDTR/rDTR inconsistent (DSCR %08x)", DSCR);\r
-       }\r
-    }\r
-\r
-    arm11_run_instr_data_prepare(arm11);\r
-\r
-    /* restore original wDTR */\r
-\r
-    if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty)\r
-    {\r
-       /* MCR p14,0,R0,c0,c5,0 */\r
-       arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));\r
-    }\r
-\r
-    /* restore CPSR */\r
-\r
-    /* MSR CPSR,R0*/\r
-    arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));\r
-\r
-\r
-    /* restore PC */\r
-\r
-    /* MOV PC,R0 */\r
-    arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));\r
-\r
-\r
-    /* restore R0 */\r
-\r
-    /* MRC p14,0,r0,c0,c5,0 */\r
-    arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0));\r
-\r
-    arm11_run_instr_data_finish(arm11);\r
-\r
-\r
-    /* restore DSCR */\r
-\r
-    arm11_write_DSCR(arm11, R(DSCR));\r
-\r
-\r
-    /* restore rDTR */\r
-    \r
-    if (R(DSCR) & ARM11_DSCR_RDTR_FULL || arm11->reg_list[ARM11_RC_RDTR].dirty)\r
-    {\r
-       arm11_add_debug_SCAN_N(arm11, 0x05, -1);\r
-\r
-       arm11_add_IR(arm11, ARM11_EXTEST, -1);\r
-\r
-       scan_field_t    chain5_fields[3];\r
-\r
-       u8                      Ready       = 0;        /* ignored */\r
-       u8                      Valid       = 0;        /* ignored */\r
-\r
-       arm11_setup_field(arm11, 32, &R(RDTR),  NULL, chain5_fields + 0);\r
-       arm11_setup_field(arm11,  1, &Ready,    NULL, chain5_fields + 1);\r
-       arm11_setup_field(arm11,  1, &Valid,    NULL, chain5_fields + 2);\r
-\r
-       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);\r
-    }\r
-\r
-\r
-    {size_t i;\r
-    for(i = 0; i < ARM11_REGCACHE_COUNT; i++)\r
-    {\r
-       arm11->reg_history[i].value     = arm11->reg_values[i];\r
-       arm11->reg_history[i].valid     = arm11->reg_list[i].valid;\r
-\r
-       arm11->reg_list[i].valid        = 0;\r
-       arm11->reg_list[i].dirty        = 0;\r
-    }}\r
-}\r
-\r
-\r
-/* poll current target status */\r
-int arm11_poll(struct target_s *target)\r
-{\r
-    FNC_INFO;\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    if (arm11->trst_active)\r
-       return ERROR_OK;\r
-\r
-    u32        dscr = arm11_read_DSCR(arm11);\r
-\r
-    DEBUG("DSCR %08x", dscr);\r
-\r
-    arm11_check_init(arm11, &dscr);\r
-\r
-    if (dscr & ARM11_DSCR_CORE_HALTED)\r
-    {\r
-//     DEBUG("CH %d", target->state);\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-           DEBUG("enter TARGET_HALTED");\r
-           target->state               = TARGET_HALTED;\r
-           target->debug_reason        = arm11_get_DSCR_debug_reason(dscr);\r
-           arm11_on_enter_debug_state(arm11);\r
-       }\r
-    }\r
-    else\r
-    {\r
-//     DEBUG("CR %d", target->state);\r
-\r
-       if (target->state != TARGET_RUNNING)\r
-       {\r
-           DEBUG("enter TARGET_RUNNING");\r
-           target->state               = TARGET_RUNNING;\r
-           target->debug_reason        = DBG_REASON_NOTHALTED;\r
-       }\r
-    }\r
-\r
-    return ERROR_OK;\r
-}\r
-/* architecture specific status reply */\r
-int arm11_arch_state(struct target_s *target)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* target request support */\r
-int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-\r
-/* target execution control */\r
-int arm11_halt(struct target_s *target)\r
-{\r
-    FNC_INFO;\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    DEBUG("target->state: %s", target_state_strings[target->state]);\r
-\r
-    if (target->state == TARGET_HALTED)\r
-    {\r
-       WARNING("target was already halted");\r
-       return ERROR_TARGET_ALREADY_HALTED;\r
-    }\r
-\r
-    if (arm11->trst_active)\r
-    {\r
-       arm11->halt_requested = true;\r
-       return ERROR_OK;\r
-    }\r
-\r
-    arm11_add_IR(arm11, ARM11_HALT, TAP_RTI);\r
-\r
-    jtag_execute_queue();\r
-\r
-    u32 dscr;\r
-\r
-    while (1)\r
-    {\r
-       dscr = arm11_read_DSCR(arm11);\r
-\r
-       if (dscr & ARM11_DSCR_CORE_HALTED)\r
-           break;\r
-    }\r
-\r
-    arm11_on_enter_debug_state(arm11);\r
-\r
-    target->state              = TARGET_HALTED;\r
-    target->debug_reason       = arm11_get_DSCR_debug_reason(dscr);\r
-    \r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)\r
-{\r
-    FNC_INFO;\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    DEBUG("target->state: %s", target_state_strings[target->state]);\r
-\r
-    if (target->state != TARGET_HALTED)\r
-    {\r
-       WARNING("target was not halted");\r
-       return ERROR_TARGET_NOT_HALTED;\r
-    }\r
-\r
-    if (!current)\r
-       R(PC) = address;\r
-\r
-    target->state              = TARGET_RUNNING;\r
-    target->debug_reason       = DBG_REASON_NOTHALTED;\r
-\r
-    arm11_leave_debug_state(arm11);\r
-\r
-    arm11_add_IR(arm11, ARM11_RESTART, TAP_RTI);\r
-\r
-    jtag_execute_queue();\r
-\r
-    while (1)\r
-    {\r
-       u32 dscr = arm11_read_DSCR(arm11);\r
-\r
-       DEBUG("DSCR %08x", dscr);\r
-\r
-       if (dscr & ARM11_DSCR_CORE_RESTARTED)\r
-           break;\r
-    }\r
-\r
-    DEBUG("RES %d", target->state);\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints)\r
-{\r
-    FNC_INFO;\r
-\r
-    DEBUG("target->state: %s", target_state_strings[target->state]);\r
-\r
-    if (target->state != TARGET_HALTED)\r
-    {\r
-       WARNING("target was not halted");\r
-       return ERROR_TARGET_NOT_HALTED;\r
-    }\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    /** \todo TODO: check if break-/watchpoints make any sense at all in combination\r
-      * with this. */\r
-\r
-    /** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively\r
-        the VCR might be something worth looking into. */\r
-\r
-    /* Set up breakpoint for stepping */\r
-\r
-    arm11_sc7_action_t brp[2];\r
-\r
-    brp[0].write       = 1;\r
-    brp[0].address     = ARM11_SC7_BVR0;\r
-    brp[0].value       = R(PC);\r
-    brp[1].write       = 1;\r
-    brp[1].address     = ARM11_SC7_BCR0;\r
-    brp[1].value       = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);\r
-\r
-    arm11_sc7_run(arm11, brp, asizeof(brp));\r
-\r
-    /* resume */\r
-\r
-    arm11_leave_debug_state(arm11);\r
-\r
-    arm11_add_IR(arm11, ARM11_RESTART, TAP_RTI);\r
-\r
-    jtag_execute_queue();\r
-\r
-    /** \todo TODO: add a timeout */\r
-\r
-    /* wait for halt */\r
-\r
-    while (1)\r
-    {\r
-       u32 dscr = arm11_read_DSCR(arm11);\r
-\r
-       DEBUG("DSCR %08x", dscr);\r
-\r
-        if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==\r
-           (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))\r
-           break;\r
-    }\r
-\r
-\r
-    /* clear breakpoint */\r
-\r
-    arm11_sc7_clear_bw(arm11);\r
-\r
-\r
-    /* save state */\r
-\r
-    arm11_on_enter_debug_state(arm11);\r
-\r
-//    target->state            = TARGET_HALTED;\r
-    target->debug_reason       = DBG_REASON_SINGLESTEP;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* target reset control */\r
-int arm11_assert_reset(struct target_s *target)\r
-{\r
-    FNC_INFO;\r
-\r
-#if 0\r
-    /* assert reset lines */\r
-    /* resets only the DBGTAP, not the ARM */\r
-\r
-    jtag_add_reset(1, 0);\r
-    jtag_add_sleep(5000);\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-    arm11->trst_active = true;\r
-#endif\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_deassert_reset(struct target_s *target)\r
-{\r
-    FNC_INFO;\r
-\r
-#if 0\r
-    DEBUG("target->state: %s", target_state_strings[target->state]);\r
-\r
-    /* deassert reset lines */\r
-    jtag_add_reset(0, 0);\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-    arm11->trst_active = false;\r
-\r
-    if (arm11->halt_requested)\r
-       return arm11_halt(target);\r
-#endif\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_soft_reset_halt(struct target_s *target)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_prepare_reset_halt(struct target_s *target)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* target register access for gdb */\r
-int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size)\r
-{\r
-    FNC_INFO;\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    if (target->state != TARGET_HALTED)\r
-    {\r
-       return ERROR_TARGET_NOT_HALTED;\r
-    }\r
-       \r
-    *reg_list_size  = ARM11_GDB_REGISTER_COUNT;\r
-    *reg_list      = malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);\r
-\r
-    {size_t i;\r
-    for (i = 16; i < 24; i++)\r
-    {\r
-       (*reg_list)[i] = &arm11_gdb_dummy_fp_reg;\r
-    }}\r
-\r
-    (*reg_list)[24] = &arm11_gdb_dummy_fps_reg;\r
-\r
-\r
-    {size_t i;\r
-    for (i = 0; i < ARM11_REGCACHE_COUNT; i++)\r
-    {\r
-       if (arm11_reg_defs[i].gdb_num == -1)\r
-           continue;\r
-\r
-       (*reg_list)[arm11_reg_defs[i].gdb_num] = arm11->reg_list + i;\r
-    }}\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* target memory access \r
-* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)\r
-* count: number of items of <size>\r
-*/\r
-int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-    /** \todo TODO: check if buffer cast to u32* and u16* might cause alignment problems */\r
-\r
-    FNC_INFO;\r
-\r
-    DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    arm11_run_instr_data_prepare(arm11);\r
-\r
-    /* MRC p14,0,r0,c0,c5,0 */\r
-    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);\r
-\r
-    switch (size)\r
-    {\r
-    case 1:\r
-       /** \todo TODO: check if dirty is the right choice to force a rewrite on arm11_resume() */\r
-       arm11->reg_list[ARM11_RC_R1].dirty = 1;\r
-\r
-       while (count--)\r
-       {\r
-           /* ldrb    r1, [r0], #1 */\r
-           arm11_run_instr_no_data1(arm11, 0xe4d01001);\r
-\r
-           u32 res;\r
-           /* MCR p14,0,R1,c0,c5,0 */\r
-           arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);\r
-\r
-           *buffer++ = res;\r
-       }\r
-       break;\r
-\r
-    case 2:\r
-    {\r
-       arm11->reg_list[ARM11_RC_R1].dirty = 1;\r
-\r
-       u16 * buf16 = (u16*)buffer;\r
-\r
-       while (count--)\r
-       {\r
-           /* ldrh    r1, [r0], #2 */\r
-           arm11_run_instr_no_data1(arm11, 0xe0d010b2);\r
-\r
-           u32 res;\r
-\r
-           /* MCR p14,0,R1,c0,c5,0 */\r
-           arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);\r
-\r
-           *buf16++ = res;\r
-       }\r
-       break;\r
-    }\r
-\r
-    case 4:\r
-\r
-       /* LDC p14,c5,[R0],#4 */\r
-       arm11_run_instr_data_from_core(arm11, 0xecb05e01, (u32 *)buffer, count);\r
-       break;\r
-    }\r
-\r
-    arm11_run_instr_data_finish(arm11);\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-    FNC_INFO;\r
-\r
-    DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    arm11_run_instr_data_prepare(arm11);\r
-\r
-    /* MRC p14,0,r0,c0,c5,0 */\r
-    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);\r
-\r
-    switch (size)\r
-    {\r
-    case 1:\r
-       arm11->reg_list[ARM11_RC_R1].dirty = 1;\r
-\r
-       while (count--)\r
-       {\r
-           /* MRC p14,0,r1,c0,c5,0 */\r
-           arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);\r
-\r
-           /* strb    r1, [r0], #1 */\r
-           arm11_run_instr_no_data1(arm11, 0xe4c01001);\r
-       }\r
-       break;\r
-\r
-    case 2:\r
-    {\r
-       arm11->reg_list[ARM11_RC_R1].dirty = 1;\r
-\r
-       u16 * buf16 = (u16*)buffer;\r
-\r
-       while (count--)\r
-       {\r
-           /* MRC p14,0,r1,c0,c5,0 */\r
-           arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buf16++);\r
-\r
-           /* strh    r1, [r0], #2 */\r
-           arm11_run_instr_no_data1(arm11, 0xe0c010b2);\r
-       }\r
-       break;\r
-    }\r
-\r
-    case 4:\r
-       /** \todo TODO: check if buffer cast to u32* might cause alignment problems */\r
-\r
-       /* STC p14,c5,[R0],#4 */\r
-       arm11_run_instr_data_to_core(arm11, 0xeca05e01, (u32 *)buffer, count);\r
-       break;\r
-    }\r
-\r
-    arm11_run_instr_data_finish(arm11);\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */\r
-int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer)\r
-{\r
-    FNC_INFO;\r
-\r
-    return arm11_write_memory(target, address, 4, count, buffer);\r
-}\r
-\r
-\r
-int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* target break-/watchpoint control \r
-* rw: 0 = write, 1 = read, 2 = access\r
-*/\r
-int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-/* target algorithm support */\r
-int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-int arm11_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-    FNC_INFO;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-    FNC_INFO;\r
-\r
-    if (argc < 4)\r
-    {\r
-       ERROR("'target arm11' 4th argument <jtag chain pos>");\r
-       exit(-1);\r
-    }\r
-\r
-    int chain_pos = strtoul(args[3], NULL, 0);\r
-\r
-    NEW(arm11_common_t, arm11, 1);\r
-\r
-    arm11->target = target;\r
-\r
-    /* prepare JTAG information for the new target */\r
-    arm11->jtag_info.chain_pos = chain_pos;\r
-    arm11->jtag_info.scann_size        = 5;\r
-\r
-    arm_jtag_setup_connection(&arm11->jtag_info);\r
-\r
-    jtag_device_t *device = jtag_get_device(chain_pos);\r
-\r
-    if (device->ir_length != 5)\r
-    {\r
-       ERROR("'target arm11' expects 'jtag_device 5 0x01 0x1F 0x1E'");\r
-       exit(-1);\r
-    }\r
-\r
-    target->arch_info = arm11;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-    FNC_INFO;\r
-\r
-    arm11_common_t * arm11 = target->arch_info;\r
-\r
-    /* check IDCODE */\r
-\r
-    arm11_add_IR(arm11, ARM11_IDCODE, -1);\r
-\r
-    scan_field_t               idcode_field;\r
-\r
-    arm11_setup_field(arm11, 32, NULL, &arm11->device_id, &idcode_field);\r
-\r
-    jtag_add_dr_scan_vc(1, &idcode_field, TAP_PD);\r
-\r
-    /* check DIDR */\r
-\r
-    arm11_add_debug_SCAN_N(arm11, 0x00, -1);\r
-\r
-    arm11_add_IR(arm11, ARM11_INTEST, -1);\r
-\r
-    scan_field_t               chain0_fields[2];\r
-\r
-    arm11_setup_field(arm11, 32, NULL, &arm11->didr,           chain0_fields + 0);\r
-    arm11_setup_field(arm11,  8, NULL, &arm11->implementor,    chain0_fields + 1);\r
-\r
-    jtag_add_dr_scan_vc(asizeof(chain0_fields), chain0_fields, TAP_RTI);\r
-\r
-    jtag_execute_queue();\r
-\r
-\r
-    switch (arm11->device_id & 0x0FFFF000)\r
-    {\r
-    case 0x07B36000:   INFO("found ARM1136"); break;\r
-    case 0x07B56000:   INFO("found ARM1156"); break;\r
-    case 0x07B76000:   INFO("found ARM1176"); break;\r
-    default:\r
-    {\r
-       ERROR("'target arm11' expects IDCODE 0x*7B*7****");\r
-       exit(-1);\r
-    }\r
-    }\r
-\r
-    arm11->brp = ((arm11->didr >> 24) & 0x0F) + 1;\r
-    arm11->wrp = ((arm11->didr >> 28) & 0x0F) + 1;\r
-\r
-\r
-    DEBUG("IDCODE %08x IMPLEMENTOR %02x DIDR %08x",\r
-       arm11->device_id,\r
-       arm11->implementor,\r
-       arm11->didr);\r
-\r
-    arm11_build_reg_cache(target);\r
-\r
-\r
-    /* as a side-effect this reads DSCR and thus\r
-     * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag\r
-     * as suggested by the spec.\r
-     */\r
-\r
-    arm11_check_init(arm11, NULL);\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int arm11_quit(void)\r
-{\r
-    FNC_INFO_NOTIMPLEMENTED;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-/** Load a register that is marked !valid in the register cache */\r
-int arm11_get_reg(reg_t *reg)\r
-{\r
-    FNC_INFO;\r
-\r
-    target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;\r
-\r
-    if (target->state != TARGET_HALTED)\r
-    {\r
-       return ERROR_TARGET_NOT_HALTED;\r
-    }\r
-\r
-    /** \todo TODO: Check this. We assume that all registers are fetched debug entry. */\r
-\r
-#if 0\r
-    arm11_common_t *arm11 = target->arch_info;\r
-    const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;\r
-#endif\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-/** Change a value in the register cache */\r
-int arm11_set_reg(reg_t *reg, u8 *buf)\r
-{\r
-    FNC_INFO;\r
-\r
-    target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;\r
-    arm11_common_t *arm11 = target->arch_info;\r
-//    const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;\r
-\r
-    arm11->reg_values[((arm11_reg_state_t *)reg->arch_info)->def_index] = buf_get_u32(buf, 0, 32);\r
-    reg->valid = 1;\r
-    reg->dirty = 1;\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-\r
-void arm11_build_reg_cache(target_t *target)\r
-{\r
-    arm11_common_t *arm11 = target->arch_info;\r
-\r
-    NEW(reg_cache_t,           cache,                  1);\r
-    NEW(reg_t,                 reg_list,               ARM11_REGCACHE_COUNT);\r
-    NEW(arm11_reg_state_t,     arm11_reg_states,       ARM11_REGCACHE_COUNT);\r
-\r
-    if (arm11_regs_arch_type == -1)\r
-       arm11_regs_arch_type = register_reg_arch_type(arm11_get_reg, arm11_set_reg);\r
-\r
-    arm11->reg_list    = reg_list;\r
-\r
-    /* Build the process context cache */ \r
-    cache->name                = "arm11 registers";\r
-    cache->next                = NULL;\r
-    cache->reg_list    = reg_list;\r
-    cache->num_regs    = ARM11_REGCACHE_COUNT;\r
-\r
-    reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);\r
-    (*cache_p) = cache;\r
-\r
-//    armv7m->core_cache = cache;\r
-//    armv7m->process_context = cache;\r
-\r
-    size_t i;\r
-\r
-    /* Not very elegant assertion */\r
-    if (ARM11_REGCACHE_COUNT != asizeof(arm11->reg_values) ||\r
-       ARM11_REGCACHE_COUNT != asizeof(arm11_reg_defs) ||\r
-       ARM11_REGCACHE_COUNT != ARM11_RC_MAX)\r
-    {\r
-       ERROR("arm11->reg_values inconsistent (%d %d %d %d)", ARM11_REGCACHE_COUNT, asizeof(arm11->reg_values), asizeof(arm11_reg_defs), ARM11_RC_MAX);\r
-       exit(-1);\r
-    }\r
-\r
-    for (i = 0; i < ARM11_REGCACHE_COUNT; i++)\r
-    {\r
-       reg_t *                         r       = reg_list              + i;\r
-       const arm11_reg_defs_t *        rd      = arm11_reg_defs        + i;\r
-       arm11_reg_state_t *             rs      = arm11_reg_states      + i;\r
-\r
-       r->name                 = rd->name;\r
-       r->size                 = 32;\r
-       r->value                = (u8 *)(arm11->reg_values + i);\r
-       r->dirty                = 0;\r
-       r->valid                = 0;\r
-       r->bitfield_desc        = NULL;\r
-       r->num_bitfields        = 0;\r
-       r->arch_type            = arm11_regs_arch_type;\r
-       r->arch_info            = rs;\r
-\r
-       rs->def_index           = i;\r
-       rs->target              = target;\r
-    }\r
-}\r
-\r
-#if 0\r
-    arm11_run_instr_data_prepare(arm11);\r
-\r
-    /* MRC p14,0,r0,c0,c5,0 */\r
-    arm11_run_instr_data_to_core(arm11, 0xee100e15, 0xCA00003C);\r
-    /* MRC p14,0,r1,c0,c5,0 */\r
-    arm11_run_instr_data_to_core(arm11, 0xee101e15, 0xFFFFFFFF);\r
-\r
-    arm11_run_instr_data_finish(arm11);\r
-#endif\r
-\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2008 digenius technology GmbH.                          *
+ *                                                                         *
+ *   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 "arm11.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+
+#if 0
+#define FNC_INFO    DEBUG("-")
+#else
+#define FNC_INFO
+#endif
+
+#if 1
+#define FNC_INFO_NOTIMPLEMENTED    do { DEBUG("NOT IMPLEMENTED"); /*exit(-1);*/ } while (0)
+#else
+#define FNC_INFO_NOTIMPLEMENTED
+#endif
+
+static void arm11_on_enter_debug_state(arm11_common_t * arm11);
+
+
+#define ARM11_HANDLER(x)       \
+    .x                         = arm11_##x
+
+target_type_t arm11_target =
+{
+    .name                      = "arm11",
+
+    ARM11_HANDLER(poll),
+    ARM11_HANDLER(arch_state),
+
+    ARM11_HANDLER(target_request_data),
+
+    ARM11_HANDLER(halt),
+    ARM11_HANDLER(resume),
+    ARM11_HANDLER(step),
+
+    ARM11_HANDLER(assert_reset),
+    ARM11_HANDLER(deassert_reset),
+    ARM11_HANDLER(soft_reset_halt),
+    ARM11_HANDLER(prepare_reset_halt),
+       
+    ARM11_HANDLER(get_gdb_reg_list),
+       
+    ARM11_HANDLER(read_memory),
+    ARM11_HANDLER(write_memory),
+       
+    ARM11_HANDLER(bulk_write_memory),
+       
+    ARM11_HANDLER(checksum_memory),
+
+    ARM11_HANDLER(add_breakpoint),
+    ARM11_HANDLER(remove_breakpoint),
+    ARM11_HANDLER(add_watchpoint),
+    ARM11_HANDLER(remove_watchpoint),
+
+    ARM11_HANDLER(run_algorithm),
+       
+    ARM11_HANDLER(register_commands),
+    ARM11_HANDLER(target_command),
+    ARM11_HANDLER(init_target),
+    ARM11_HANDLER(quit),
+};
+
+int arm11_regs_arch_type = -1;
+
+
+enum arm11_regtype
+{
+    ARM11_REGISTER_CORE,
+    ARM11_REGISTER_CPSR,
+
+    ARM11_REGISTER_FX,
+    ARM11_REGISTER_FPS,
+
+    ARM11_REGISTER_FIQ,
+    ARM11_REGISTER_SVC,
+    ARM11_REGISTER_ABT,
+    ARM11_REGISTER_IRQ,
+    ARM11_REGISTER_UND,
+    ARM11_REGISTER_MON,
+
+    ARM11_REGISTER_SPSR_FIQ,
+    ARM11_REGISTER_SPSR_SVC,
+    ARM11_REGISTER_SPSR_ABT,
+    ARM11_REGISTER_SPSR_IRQ,
+    ARM11_REGISTER_SPSR_UND,
+    ARM11_REGISTER_SPSR_MON,
+
+    /* debug regs */
+    ARM11_REGISTER_DSCR,
+    ARM11_REGISTER_WDTR,
+    ARM11_REGISTER_RDTR,
+};
+
+
+typedef struct arm11_reg_defs_s
+{
+    char *                     name;
+    u32                                num;
+    int                                gdb_num;
+    enum arm11_regtype         type;
+} arm11_reg_defs_t;
+
+/* update arm11_regcache_ids when changing this */
+static const arm11_reg_defs_t arm11_reg_defs[] =
+{
+    {"r0",     0,      0,      ARM11_REGISTER_CORE},
+    {"r1",     1,      1,      ARM11_REGISTER_CORE},
+    {"r2",     2,      2,      ARM11_REGISTER_CORE},
+    {"r3",     3,      3,      ARM11_REGISTER_CORE},
+    {"r4",     4,      4,      ARM11_REGISTER_CORE},
+    {"r5",     5,      5,      ARM11_REGISTER_CORE},
+    {"r6",     6,      6,      ARM11_REGISTER_CORE},
+    {"r7",     7,      7,      ARM11_REGISTER_CORE},
+    {"r8",     8,      8,      ARM11_REGISTER_CORE},
+    {"r9",     9,      9,      ARM11_REGISTER_CORE},
+    {"r10",    10,     10,     ARM11_REGISTER_CORE},
+    {"r11",    11,     11,     ARM11_REGISTER_CORE},
+    {"r12",    12,     12,     ARM11_REGISTER_CORE},
+    {"sp",     13,     13,     ARM11_REGISTER_CORE},
+    {"lr",     14,     14,     ARM11_REGISTER_CORE},
+    {"pc",     15,     15,     ARM11_REGISTER_CORE},
+
+#if ARM11_REGCACHE_FREGS
+    {"f0",     0,      16,     ARM11_REGISTER_FX},
+    {"f1",     1,      17,     ARM11_REGISTER_FX},
+    {"f2",     2,      18,     ARM11_REGISTER_FX},
+    {"f3",     3,      19,     ARM11_REGISTER_FX},
+    {"f4",     4,      20,     ARM11_REGISTER_FX},
+    {"f5",     5,      21,     ARM11_REGISTER_FX},
+    {"f6",     6,      22,     ARM11_REGISTER_FX},
+    {"f7",     7,      23,     ARM11_REGISTER_FX},
+    {"fps",    0,      24,     ARM11_REGISTER_FPS},
+#endif
+
+    {"cpsr",   0,      25,     ARM11_REGISTER_CPSR},
+
+#if ARM11_REGCACHE_MODEREGS
+    {"r8_fiq", 8,      -1,     ARM11_REGISTER_FIQ},
+    {"r9_fiq", 9,      -1,     ARM11_REGISTER_FIQ},
+    {"r10_fiq",        10,     -1,     ARM11_REGISTER_FIQ},
+    {"r11_fiq",        11,     -1,     ARM11_REGISTER_FIQ},
+    {"r12_fiq",        12,     -1,     ARM11_REGISTER_FIQ},
+    {"r13_fiq",        13,     -1,     ARM11_REGISTER_FIQ},
+    {"r14_fiq",        14,     -1,     ARM11_REGISTER_FIQ},
+    {"spsr_fiq", 0,    -1,     ARM11_REGISTER_SPSR_FIQ},
+
+    {"r13_svc",        13,     -1,     ARM11_REGISTER_SVC},
+    {"r14_svc",        14,     -1,     ARM11_REGISTER_SVC},
+    {"spsr_svc", 0,    -1,     ARM11_REGISTER_SPSR_SVC},
+
+    {"r13_abt",        13,     -1,     ARM11_REGISTER_ABT},
+    {"r14_abt",        14,     -1,     ARM11_REGISTER_ABT},
+    {"spsr_abt", 0,    -1,     ARM11_REGISTER_SPSR_ABT},
+
+    {"r13_irq",        13,     -1,     ARM11_REGISTER_IRQ},
+    {"r14_irq",        14,     -1,     ARM11_REGISTER_IRQ},
+    {"spsr_irq", 0,    -1,     ARM11_REGISTER_SPSR_IRQ},
+
+    {"r13_und",        13,     -1,     ARM11_REGISTER_UND},
+    {"r14_und",        14,     -1,     ARM11_REGISTER_UND},
+    {"spsr_und", 0,    -1,     ARM11_REGISTER_SPSR_UND},
+
+    /* ARM1176 only */
+    {"r13_mon",        13,     -1,     ARM11_REGISTER_MON},
+    {"r14_mon",        14,     -1,     ARM11_REGISTER_MON},
+    {"spsr_mon", 0,    -1,     ARM11_REGISTER_SPSR_MON},
+#endif
+
+    /* Debug Registers */
+    {"dscr",   0,      -1,     ARM11_REGISTER_DSCR},
+    {"wdtr",   0,      -1,     ARM11_REGISTER_WDTR},
+    {"rdtr",   0,      -1,     ARM11_REGISTER_RDTR},
+};
+
+enum arm11_regcache_ids
+{
+    ARM11_RC_R0,
+    ARM11_RC_RX                        = ARM11_RC_R0,
+
+    ARM11_RC_R1,
+    ARM11_RC_R2,
+    ARM11_RC_R3,
+    ARM11_RC_R4,
+    ARM11_RC_R5,
+    ARM11_RC_R6,
+    ARM11_RC_R7,
+    ARM11_RC_R8,
+    ARM11_RC_R9,
+    ARM11_RC_R10,
+    ARM11_RC_R11,
+    ARM11_RC_R12,
+    ARM11_RC_R13,
+    ARM11_RC_SP                        = ARM11_RC_R13,
+    ARM11_RC_R14,
+    ARM11_RC_LR                        = ARM11_RC_R14,
+    ARM11_RC_R15,
+    ARM11_RC_PC                        = ARM11_RC_R15,
+
+#if ARM11_REGCACHE_FREGS
+    ARM11_RC_F0,
+    ARM11_RC_FX                        = ARM11_RC_F0,
+    ARM11_RC_F1,
+    ARM11_RC_F2,
+    ARM11_RC_F3,
+    ARM11_RC_F4,
+    ARM11_RC_F5,
+    ARM11_RC_F6,
+    ARM11_RC_F7,
+    ARM11_RC_FPS,
+#endif
+
+    ARM11_RC_CPSR,
+
+#if ARM11_REGCACHE_MODEREGS
+    ARM11_RC_R8_FIQ,
+    ARM11_RC_R9_FIQ,
+    ARM11_RC_R10_FIQ,
+    ARM11_RC_R11_FIQ,
+    ARM11_RC_R12_FIQ,
+    ARM11_RC_R13_FIQ,
+    ARM11_RC_R14_FIQ,
+    ARM11_RC_SPSR_FIQ,
+
+    ARM11_RC_R13_SVC,
+    ARM11_RC_R14_SVC,
+    ARM11_RC_SPSR_SVC,
+
+    ARM11_RC_R13_ABT,
+    ARM11_RC_R14_ABT,
+    ARM11_RC_SPSR_ABT,
+
+    ARM11_RC_R13_IRQ,
+    ARM11_RC_R14_IRQ,
+    ARM11_RC_SPSR_IRQ,
+
+    ARM11_RC_R13_UND,
+    ARM11_RC_R14_UND,
+    ARM11_RC_SPSR_UND,
+
+    ARM11_RC_R13_MON,
+    ARM11_RC_R14_MON,
+    ARM11_RC_SPSR_MON,
+#endif
+
+    ARM11_RC_DSCR,
+    ARM11_RC_WDTR,
+    ARM11_RC_RDTR,
+
+
+    ARM11_RC_MAX,
+};
+
+#define ARM11_GDB_REGISTER_COUNT       26
+
+u8 arm11_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+reg_t arm11_gdb_dummy_fp_reg =
+{
+    "GDB dummy floating-point register", arm11_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
+};
+
+u8 arm11_gdb_dummy_fps_value[] = {0, 0, 0, 0};
+
+reg_t arm11_gdb_dummy_fps_reg =
+{
+    "GDB dummy floating-point status register", arm11_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
+};
+
+
+
+/** Check and if necessary take control of the system
+ *
+ * \param arm11                Target state variable.
+ * \param dscr         If the current DSCR content is
+ *                     available a pointer to a word holding the
+ *                     DSCR can be passed. Otherwise use NULL.
+ */
+void arm11_check_init(arm11_common_t * arm11, u32 * dscr)
+{
+    FNC_INFO;
+
+    u32                        dscr_local_tmp_copy;
+
+    if (!dscr)
+    {
+       dscr = &dscr_local_tmp_copy;
+       *dscr = arm11_read_DSCR(arm11);
+    }
+
+    if (!(*dscr & ARM11_DSCR_MODE_SELECT))
+    {
+       DEBUG("Bringing target into debug mode");
+
+       *dscr |= ARM11_DSCR_MODE_SELECT;                /* Halt debug-mode */
+       arm11_write_DSCR(arm11, *dscr);
+
+       /* add further reset initialization here */
+
+       if (*dscr & ARM11_DSCR_CORE_HALTED)
+       {
+           arm11->target->state        = TARGET_HALTED;
+           arm11->target->debug_reason = arm11_get_DSCR_debug_reason(*dscr);
+       }
+       else
+       {
+           arm11->target->state        = TARGET_RUNNING;
+           arm11->target->debug_reason = DBG_REASON_NOTHALTED;
+       }
+
+       arm11_sc7_clear_bw(arm11);
+    }
+}
+
+
+
+#define R(x) \
+    (arm11->reg_values[ARM11_RC_##x])
+
+/** Save processor state.
+  *
+  * This is called when the HALT instruction has succeeded
+  * or on other occasions that stop the processor.
+  *
+  */
+static void arm11_on_enter_debug_state(arm11_common_t * arm11)
+{
+    FNC_INFO;
+
+    {size_t i;
+    for(i = 0; i < asizeof(arm11->reg_values); i++)
+    {
+       arm11->reg_list[i].valid        = 1;
+       arm11->reg_list[i].dirty        = 0;
+    }}
+
+    /* Save DSCR */
+
+    R(DSCR) = arm11_read_DSCR(arm11);
+
+    /* Save wDTR */
+
+    if (R(DSCR) & ARM11_DSCR_WDTR_FULL)
+    {
+       arm11_add_debug_SCAN_N(arm11, 0x05, -1);
+
+       arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+       scan_field_t    chain5_fields[3];
+
+       arm11_setup_field(arm11, 32, NULL, &R(WDTR),    chain5_fields + 0);
+       arm11_setup_field(arm11,  1, NULL, NULL,        chain5_fields + 1);
+       arm11_setup_field(arm11,  1, NULL, NULL,        chain5_fields + 2);
+
+       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+    }
+    else
+    {
+       arm11->reg_list[ARM11_RC_WDTR].valid    = 0;
+    }
+
+
+    /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE */
+    /* ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", but not to issue ITRs
+       ARM1136 seems to require this to issue ITR's as well */
+
+    u32 new_dscr = R(DSCR) | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE;
+
+    /* this executes JTAG queue: */ 
+
+    arm11_write_DSCR(arm11, new_dscr);
+
+//    jtag_execute_queue();
+
+
+
+//    DEBUG("SAVE DSCR %08x", R(DSCR));
+
+//    if (R(DSCR) & ARM11_DSCR_WDTR_FULL)
+//     DEBUG("SAVE wDTR %08x", R(WDTR));
+
+
+    /* From the spec:
+       Before executing any instruction in debug state you have to drain the write buffer.
+        This ensures that no imprecise Data Aborts can return at a later point:*/
+
+    /** \todo TODO: Test drain write buffer. */
+
+#if 0
+    while (1)
+    {
+       /* MRC p14,0,R0,c5,c10,0 */
+//     arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000);
+
+       /* mcr     15, 0, r0, cr7, cr10, {4} */
+       arm11_run_instr_no_data1(arm11, 0xee070f9a);
+               
+       u32 dscr = arm11_read_DSCR(arm11);
+
+       DEBUG("DRAIN, DSCR %08x", dscr);
+
+       if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT)
+       {
+           arm11_run_instr_no_data1(arm11, 0xe320f000);
+
+           dscr = arm11_read_DSCR(arm11);
+
+           DEBUG("DRAIN, DSCR %08x (DONE)", dscr);
+
+           break;
+       }
+    }
+#endif
+
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* save r0 - r14 */
+
+
+    /** \todo TODO: handle other mode registers */
+
+    {size_t i;
+    for (i = 0; i < 15; i++)
+    {
+       /* MCR p14,0,R?,c0,c5,0 */
+       arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
+    }}
+
+
+    /* save rDTR */
+
+    /* check rDTRfull in DSCR */
+
+    if (R(DSCR) & ARM11_DSCR_RDTR_FULL)
+    {
+       /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
+       arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
+    }
+    else
+    {
+       arm11->reg_list[ARM11_RC_RDTR].valid    = 0;
+    }
+
+    /* save CPSR */
+
+    /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */
+    arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));
+
+    /* save PC */
+
+    /* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */
+    arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));
+
+    /* adjust PC depending on ARM state */
+
+    if (R(CPSR) & ARM11_CPSR_J)        /* Java state */
+    {
+       arm11->reg_values[ARM11_RC_PC] -= 0;
+    }
+    else if (R(CPSR) & ARM11_CPSR_T)   /* Thumb state */
+    {
+       arm11->reg_values[ARM11_RC_PC] -= 4;
+    }
+    else                                       /* ARM state */
+    {
+       arm11->reg_values[ARM11_RC_PC] -= 8;
+    }
+
+//    DEBUG("SAVE PC   %08x", R(PC));
+
+    arm11_run_instr_data_finish(arm11);
+
+
+    {size_t i;
+    for(i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+       if (!arm11->reg_list[i].valid)
+       {
+           if (arm11->reg_history[i].valid)
+               INFO("%8s INVALID    (%08x)", arm11_reg_defs[i].name, arm11->reg_history[i].value);
+       }
+       else
+       {
+           if (arm11->reg_history[i].valid)
+           {
+               if (arm11->reg_history[i].value != arm11->reg_values[i])
+                   INFO("%8s %08x (%08x)", arm11_reg_defs[i].name, arm11->reg_values[i], arm11->reg_history[i].value);
+           }
+           else
+           {
+               INFO("%8s %08x (INVALID)", arm11_reg_defs[i].name, arm11->reg_values[i]);
+           }
+       }
+    }}
+}
+
+
+/** Restore processor state
+  *
+  * This is called in preparation for the RESTART function.
+  *
+  */
+void arm11_leave_debug_state(arm11_common_t * arm11)
+{
+    FNC_INFO;
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /** \todo TODO: handle other mode registers */
+
+    /* restore R1 - R14 */
+    {size_t i;
+    for (i = 1; i < 15; i++)
+    {
+       if (!arm11->reg_list[ARM11_RC_RX + i].dirty)
+           continue;
+
+       /* MRC p14,0,r?,c0,c5,0 */
+       arm11_run_instr_data_to_core1(arm11, 0xee100e15 | (i << 12), R(RX + i));
+
+//     DEBUG("RESTORE R%d %08x", i, R(RX + i));
+    }}
+
+    arm11_run_instr_data_finish(arm11);
+
+
+    /* spec says clear wDTR and rDTR; we assume they are clear as
+       otherwide out programming would be sloppy */
+
+    {
+       u32 DSCR = arm11_read_DSCR(arm11);
+
+       if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
+       {
+           ERROR("wDTR/rDTR inconsistent (DSCR %08x)", DSCR);
+       }
+    }
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* restore original wDTR */
+
+    if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty)
+    {
+       /* MCR p14,0,R0,c0,c5,0 */
+       arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
+    }
+
+    /* restore CPSR */
+
+    /* MSR CPSR,R0*/
+    arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
+
+
+    /* restore PC */
+
+    /* MOV PC,R0 */
+    arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
+
+
+    /* restore R0 */
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0));
+
+    arm11_run_instr_data_finish(arm11);
+
+
+    /* restore DSCR */
+
+    arm11_write_DSCR(arm11, R(DSCR));
+
+
+    /* restore rDTR */
+    
+    if (R(DSCR) & ARM11_DSCR_RDTR_FULL || arm11->reg_list[ARM11_RC_RDTR].dirty)
+    {
+       arm11_add_debug_SCAN_N(arm11, 0x05, -1);
+
+       arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+       scan_field_t    chain5_fields[3];
+
+       u8                      Ready       = 0;        /* ignored */
+       u8                      Valid       = 0;        /* ignored */
+
+       arm11_setup_field(arm11, 32, &R(RDTR),  NULL, chain5_fields + 0);
+       arm11_setup_field(arm11,  1, &Ready,    NULL, chain5_fields + 1);
+       arm11_setup_field(arm11,  1, &Valid,    NULL, chain5_fields + 2);
+
+       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+    }
+
+
+    {size_t i;
+    for(i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+       arm11->reg_history[i].value     = arm11->reg_values[i];
+       arm11->reg_history[i].valid     = arm11->reg_list[i].valid;
+
+       arm11->reg_list[i].valid        = 0;
+       arm11->reg_list[i].dirty        = 0;
+    }}
+}
+
+
+/* poll current target status */
+int arm11_poll(struct target_s *target)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    if (arm11->trst_active)
+       return ERROR_OK;
+
+    u32        dscr = arm11_read_DSCR(arm11);
+
+    DEBUG("DSCR %08x", dscr);
+
+    arm11_check_init(arm11, &dscr);
+
+    if (dscr & ARM11_DSCR_CORE_HALTED)
+    {
+//     DEBUG("CH %d", target->state);
+
+       if (target->state != TARGET_HALTED)
+       {
+           DEBUG("enter TARGET_HALTED");
+           target->state               = TARGET_HALTED;
+           target->debug_reason        = arm11_get_DSCR_debug_reason(dscr);
+           arm11_on_enter_debug_state(arm11);
+       }
+    }
+    else
+    {
+//     DEBUG("CR %d", target->state);
+
+       if (target->state != TARGET_RUNNING)
+       {
+           DEBUG("enter TARGET_RUNNING");
+           target->state               = TARGET_RUNNING;
+           target->debug_reason        = DBG_REASON_NOTHALTED;
+       }
+    }
+
+    return ERROR_OK;
+}
+/* architecture specific status reply */
+int arm11_arch_state(struct target_s *target)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target request support */
+int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+
+/* target execution control */
+int arm11_halt(struct target_s *target)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    if (target->state == TARGET_HALTED)
+    {
+       WARNING("target was already halted");
+       return ERROR_TARGET_ALREADY_HALTED;
+    }
+
+    if (arm11->trst_active)
+    {
+       arm11->halt_requested = true;
+       return ERROR_OK;
+    }
+
+    arm11_add_IR(arm11, ARM11_HALT, TAP_RTI);
+
+    jtag_execute_queue();
+
+    u32 dscr;
+
+    while (1)
+    {
+       dscr = arm11_read_DSCR(arm11);
+
+       if (dscr & ARM11_DSCR_CORE_HALTED)
+           break;
+    }
+
+    arm11_on_enter_debug_state(arm11);
+
+    target->state              = TARGET_HALTED;
+    target->debug_reason       = arm11_get_DSCR_debug_reason(dscr);
+    
+    return ERROR_OK;
+}
+
+
+int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    if (target->state != TARGET_HALTED)
+    {
+       WARNING("target was not halted");
+       return ERROR_TARGET_NOT_HALTED;
+    }
+
+    if (!current)
+       R(PC) = address;
+
+    target->state              = TARGET_RUNNING;
+    target->debug_reason       = DBG_REASON_NOTHALTED;
+
+    arm11_leave_debug_state(arm11);
+
+    arm11_add_IR(arm11, ARM11_RESTART, TAP_RTI);
+
+    jtag_execute_queue();
+
+    while (1)
+    {
+       u32 dscr = arm11_read_DSCR(arm11);
+
+       DEBUG("DSCR %08x", dscr);
+
+       if (dscr & ARM11_DSCR_CORE_RESTARTED)
+           break;
+    }
+
+    DEBUG("RES %d", target->state);
+
+    return ERROR_OK;
+}
+
+int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+    FNC_INFO;
+
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    if (target->state != TARGET_HALTED)
+    {
+       WARNING("target was not halted");
+       return ERROR_TARGET_NOT_HALTED;
+    }
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    /** \todo TODO: check if break-/watchpoints make any sense at all in combination
+      * with this. */
+
+    /** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively
+        the VCR might be something worth looking into. */
+
+    /* Set up breakpoint for stepping */
+
+    arm11_sc7_action_t brp[2];
+
+    brp[0].write       = 1;
+    brp[0].address     = ARM11_SC7_BVR0;
+    brp[0].value       = R(PC);
+    brp[1].write       = 1;
+    brp[1].address     = ARM11_SC7_BCR0;
+    brp[1].value       = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);
+
+    arm11_sc7_run(arm11, brp, asizeof(brp));
+
+    /* resume */
+
+    arm11_leave_debug_state(arm11);
+
+    arm11_add_IR(arm11, ARM11_RESTART, TAP_RTI);
+
+    jtag_execute_queue();
+
+    /** \todo TODO: add a timeout */
+
+    /* wait for halt */
+
+    while (1)
+    {
+       u32 dscr = arm11_read_DSCR(arm11);
+
+       DEBUG("DSCR %08x", dscr);
+
+        if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==
+           (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))
+           break;
+    }
+
+
+    /* clear breakpoint */
+
+    arm11_sc7_clear_bw(arm11);
+
+
+    /* save state */
+
+    arm11_on_enter_debug_state(arm11);
+
+//    target->state            = TARGET_HALTED;
+    target->debug_reason       = DBG_REASON_SINGLESTEP;
+
+    return ERROR_OK;
+}
+
+
+/* target reset control */
+int arm11_assert_reset(struct target_s *target)
+{
+    FNC_INFO;
+
+#if 0
+    /* assert reset lines */
+    /* resets only the DBGTAP, not the ARM */
+
+    jtag_add_reset(1, 0);
+    jtag_add_sleep(5000);
+
+    arm11_common_t * arm11 = target->arch_info;
+    arm11->trst_active = true;
+#endif
+
+    return ERROR_OK;
+}
+
+int arm11_deassert_reset(struct target_s *target)
+{
+    FNC_INFO;
+
+#if 0
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    /* deassert reset lines */
+    jtag_add_reset(0, 0);
+
+    arm11_common_t * arm11 = target->arch_info;
+    arm11->trst_active = false;
+
+    if (arm11->halt_requested)
+       return arm11_halt(target);
+#endif
+
+    return ERROR_OK;
+}
+
+int arm11_soft_reset_halt(struct target_s *target)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_prepare_reset_halt(struct target_s *target)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target register access for gdb */
+int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    if (target->state != TARGET_HALTED)
+    {
+       return ERROR_TARGET_NOT_HALTED;
+    }
+       
+    *reg_list_size  = ARM11_GDB_REGISTER_COUNT;
+    *reg_list      = malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);
+
+    {size_t i;
+    for (i = 16; i < 24; i++)
+    {
+       (*reg_list)[i] = &arm11_gdb_dummy_fp_reg;
+    }}
+
+    (*reg_list)[24] = &arm11_gdb_dummy_fps_reg;
+
+
+    {size_t i;
+    for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+       if (arm11_reg_defs[i].gdb_num == -1)
+           continue;
+
+       (*reg_list)[arm11_reg_defs[i].gdb_num] = arm11->reg_list + i;
+    }}
+
+    return ERROR_OK;
+}
+
+
+/* target memory access 
+* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
+* count: number of items of <size>
+*/
+int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+    /** \todo TODO: check if buffer cast to u32* and u16* might cause alignment problems */
+
+    FNC_INFO;
+
+    DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+
+    switch (size)
+    {
+    case 1:
+       /** \todo TODO: check if dirty is the right choice to force a rewrite on arm11_resume() */
+       arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+       while (count--)
+       {
+           /* ldrb    r1, [r0], #1 */
+           arm11_run_instr_no_data1(arm11, 0xe4d01001);
+
+           u32 res;
+           /* MCR p14,0,R1,c0,c5,0 */
+           arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
+
+           *buffer++ = res;
+       }
+       break;
+
+    case 2:
+    {
+       arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+       u16 * buf16 = (u16*)buffer;
+
+       while (count--)
+       {
+           /* ldrh    r1, [r0], #2 */
+           arm11_run_instr_no_data1(arm11, 0xe0d010b2);
+
+           u32 res;
+
+           /* MCR p14,0,R1,c0,c5,0 */
+           arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
+
+           *buf16++ = res;
+       }
+       break;
+    }
+
+    case 4:
+
+       /* LDC p14,c5,[R0],#4 */
+       arm11_run_instr_data_from_core(arm11, 0xecb05e01, (u32 *)buffer, count);
+       break;
+    }
+
+    arm11_run_instr_data_finish(arm11);
+
+    return ERROR_OK;
+}
+
+int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+    FNC_INFO;
+
+    DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+
+    switch (size)
+    {
+    case 1:
+       arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+       while (count--)
+       {
+           /* MRC p14,0,r1,c0,c5,0 */
+           arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+
+           /* strb    r1, [r0], #1 */
+           arm11_run_instr_no_data1(arm11, 0xe4c01001);
+       }
+       break;
+
+    case 2:
+    {
+       arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+       u16 * buf16 = (u16*)buffer;
+
+       while (count--)
+       {
+           /* MRC p14,0,r1,c0,c5,0 */
+           arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buf16++);
+
+           /* strh    r1, [r0], #2 */
+           arm11_run_instr_no_data1(arm11, 0xe0c010b2);
+       }
+       break;
+    }
+
+    case 4:
+       /** \todo TODO: check if buffer cast to u32* might cause alignment problems */
+
+       /* STC p14,c5,[R0],#4 */
+       arm11_run_instr_data_to_core(arm11, 0xeca05e01, (u32 *)buffer, count);
+       break;
+    }
+
+    arm11_run_instr_data_finish(arm11);
+
+    return ERROR_OK;
+}
+
+
+/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
+int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer)
+{
+    FNC_INFO;
+
+    return arm11_write_memory(target, address, 4, count, buffer);
+}
+
+
+int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target break-/watchpoint control 
+* rw: 0 = write, 1 = read, 2 = access
+*/
+int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target algorithm support */
+int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+int arm11_register_commands(struct command_context_s *cmd_ctx)
+{
+    FNC_INFO;
+
+    return ERROR_OK;
+}
+
+int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+    FNC_INFO;
+
+    if (argc < 4)
+    {
+       ERROR("'target arm11' 4th argument <jtag chain pos>");
+       exit(-1);
+    }
+
+    int chain_pos = strtoul(args[3], NULL, 0);
+
+    NEW(arm11_common_t, arm11, 1);
+
+    arm11->target = target;
+
+    /* prepare JTAG information for the new target */
+    arm11->jtag_info.chain_pos = chain_pos;
+    arm11->jtag_info.scann_size        = 5;
+
+    arm_jtag_setup_connection(&arm11->jtag_info);
+
+    jtag_device_t *device = jtag_get_device(chain_pos);
+
+    if (device->ir_length != 5)
+    {
+       ERROR("'target arm11' expects 'jtag_device 5 0x01 0x1F 0x1E'");
+       exit(-1);
+    }
+
+    target->arch_info = arm11;
+
+    return ERROR_OK;
+}
+
+int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    /* check IDCODE */
+
+    arm11_add_IR(arm11, ARM11_IDCODE, -1);
+
+    scan_field_t               idcode_field;
+
+    arm11_setup_field(arm11, 32, NULL, &arm11->device_id, &idcode_field);
+
+    jtag_add_dr_scan_vc(1, &idcode_field, TAP_PD);
+
+    /* check DIDR */
+
+    arm11_add_debug_SCAN_N(arm11, 0x00, -1);
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    scan_field_t               chain0_fields[2];
+
+    arm11_setup_field(arm11, 32, NULL, &arm11->didr,           chain0_fields + 0);
+    arm11_setup_field(arm11,  8, NULL, &arm11->implementor,    chain0_fields + 1);
+
+    jtag_add_dr_scan_vc(asizeof(chain0_fields), chain0_fields, TAP_RTI);
+
+    jtag_execute_queue();
+
+
+    switch (arm11->device_id & 0x0FFFF000)
+    {
+    case 0x07B36000:   INFO("found ARM1136"); break;
+    case 0x07B56000:   INFO("found ARM1156"); break;
+    case 0x07B76000:   INFO("found ARM1176"); break;
+    default:
+    {
+       ERROR("'target arm11' expects IDCODE 0x*7B*7****");
+       exit(-1);
+    }
+    }
+
+    arm11->brp = ((arm11->didr >> 24) & 0x0F) + 1;
+    arm11->wrp = ((arm11->didr >> 28) & 0x0F) + 1;
+
+
+    DEBUG("IDCODE %08x IMPLEMENTOR %02x DIDR %08x",
+       arm11->device_id,
+       arm11->implementor,
+       arm11->didr);
+
+    arm11_build_reg_cache(target);
+
+
+    /* as a side-effect this reads DSCR and thus
+     * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag
+     * as suggested by the spec.
+     */
+
+    arm11_check_init(arm11, NULL);
+
+    return ERROR_OK;
+}
+
+int arm11_quit(void)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+/** Load a register that is marked !valid in the register cache */
+int arm11_get_reg(reg_t *reg)
+{
+    FNC_INFO;
+
+    target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;
+
+    if (target->state != TARGET_HALTED)
+    {
+       return ERROR_TARGET_NOT_HALTED;
+    }
+
+    /** \todo TODO: Check this. We assume that all registers are fetched debug entry. */
+
+#if 0
+    arm11_common_t *arm11 = target->arch_info;
+    const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
+#endif
+
+    return ERROR_OK;
+}
+
+/** Change a value in the register cache */
+int arm11_set_reg(reg_t *reg, u8 *buf)
+{
+    FNC_INFO;
+
+    target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;
+    arm11_common_t *arm11 = target->arch_info;
+//    const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
+
+    arm11->reg_values[((arm11_reg_state_t *)reg->arch_info)->def_index] = buf_get_u32(buf, 0, 32);
+    reg->valid = 1;
+    reg->dirty = 1;
+
+    return ERROR_OK;
+}
+
+
+void arm11_build_reg_cache(target_t *target)
+{
+    arm11_common_t *arm11 = target->arch_info;
+
+    NEW(reg_cache_t,           cache,                  1);
+    NEW(reg_t,                 reg_list,               ARM11_REGCACHE_COUNT);
+    NEW(arm11_reg_state_t,     arm11_reg_states,       ARM11_REGCACHE_COUNT);
+
+    if (arm11_regs_arch_type == -1)
+       arm11_regs_arch_type = register_reg_arch_type(arm11_get_reg, arm11_set_reg);
+
+    arm11->reg_list    = reg_list;
+
+    /* Build the process context cache */ 
+    cache->name                = "arm11 registers";
+    cache->next                = NULL;
+    cache->reg_list    = reg_list;
+    cache->num_regs    = ARM11_REGCACHE_COUNT;
+
+    reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+    (*cache_p) = cache;
+
+//    armv7m->core_cache = cache;
+//    armv7m->process_context = cache;
+
+    size_t i;
+
+    /* Not very elegant assertion */
+    if (ARM11_REGCACHE_COUNT != asizeof(arm11->reg_values) ||
+       ARM11_REGCACHE_COUNT != asizeof(arm11_reg_defs) ||
+       ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
+    {
+       ERROR("arm11->reg_values inconsistent (%d %d %d %d)", ARM11_REGCACHE_COUNT, asizeof(arm11->reg_values), asizeof(arm11_reg_defs), ARM11_RC_MAX);
+       exit(-1);
+    }
+
+    for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+       reg_t *                         r       = reg_list              + i;
+       const arm11_reg_defs_t *        rd      = arm11_reg_defs        + i;
+       arm11_reg_state_t *             rs      = arm11_reg_states      + i;
+
+       r->name                 = rd->name;
+       r->size                 = 32;
+       r->value                = (u8 *)(arm11->reg_values + i);
+       r->dirty                = 0;
+       r->valid                = 0;
+       r->bitfield_desc        = NULL;
+       r->num_bitfields        = 0;
+       r->arch_type            = arm11_regs_arch_type;
+       r->arch_info            = rs;
+
+       rs->def_index           = i;
+       rs->target              = target;
+    }
+}
+
+#if 0
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core(arm11, 0xee100e15, 0xCA00003C);
+    /* MRC p14,0,r1,c0,c5,0 */
+    arm11_run_instr_data_to_core(arm11, 0xee101e15, 0xFFFFFFFF);
+
+    arm11_run_instr_data_finish(arm11);
+#endif
+
+
index 4e061ae48f40787d46fc6e669fbb51ce2e03b170..f2263b525d84e7fc306c826fa34a16ef1fd3af21 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2008 digenius technology GmbH.                          *\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
-#ifndef ARM11_H\r
-#define ARM11_H\r
-\r
-#include "target.h"\r
-#include "register.h"\r
-#include "embeddedice.h"\r
-#include "arm_jtag.h"\r
-\r
-\r
-#define bool   int\r
-#define true   1\r
-#define false  0\r
-\r
-#define asizeof(x)     (sizeof(x) / sizeof((x)[0]))\r
-\r
-#define NEW(type, variable, items) \\r
-    type * variable = malloc(sizeof(type) * items)\r
-\r
-\r
-#define ARM11_REGCACHE_MODEREGS                0\r
-#define ARM11_REGCACHE_FREGS           0\r
-\r
-#define ARM11_REGCACHE_COUNT           (20 +                                   \\r
-                                        23 * ARM11_REGCACHE_MODEREGS +         \\r
-                                         9 * ARM11_REGCACHE_FREGS)\r
-\r
-\r
-typedef struct arm11_register_history_s\r
-{\r
-    u32            value;\r
-    u8     valid;\r
-}arm11_register_history_t;\r
-\r
-\r
-\r
-typedef struct arm11_common_s\r
-{\r
-    target_t * target;\r
-\r
-    arm_jtag_t jtag_info;\r
-\r
-    /** \name Processor type detection */\r
-    /*@{*/\r
-\r
-    u32                device_id;          /**< IDCODE readout                         */\r
-    u32                didr;               /**< DIDR readout (debug capabilities)      */\r
-    u8         implementor;        /**< DIDR Implementor readout               */\r
-\r
-    size_t     brp;                /**< Number of Breakpoint Register Pairs    */\r
-    size_t     wrp;                /**< Number of Watchpoint Register Pairs    */\r
-\r
-    /*@}*/\r
-\r
-\r
-    u32                last_dscr;          /**< Last retrieved DSCR value;\r
-                                    *   Can be used to detect changes          */\r
-\r
-    u8         trst_active;\r
-    u8         halt_requested;\r
-\r
-    /** \name Shadow registers to save processor state */\r
-    /*@{*/\r
-\r
-    reg_t *    reg_list;                               /**< target register list */\r
-    u32                reg_values[ARM11_REGCACHE_COUNT];       /**< data for registers */\r
-\r
-    /*@}*/\r
-\r
-    arm11_register_history_t\r
-               reg_history[ARM11_REGCACHE_COUNT];      /**< register state before last resume */\r
-\r
-\r
-} arm11_common_t;\r
-\r
-\r
-/**\r
- * ARM11 DBGTAP instructions \r
- * \r
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html\r
- */\r
-enum arm11_instructions\r
-{\r
-    ARM11_EXTEST    = 0x00,\r
-    ARM11_SCAN_N    = 0x02,\r
-    ARM11_RESTART   = 0x04,\r
-    ARM11_HALT     = 0x08,\r
-    ARM11_INTEST    = 0x0C,\r
-    ARM11_ITRSEL    = 0x1D,\r
-    ARM11_IDCODE    = 0x1E,\r
-    ARM11_BYPASS    = 0x1F,\r
-};\r
-\r
-enum arm11_dscr\r
-{\r
-    ARM11_DSCR_CORE_HALTED                             = 1 << 0,\r
-    ARM11_DSCR_CORE_RESTARTED                          = 1 << 1,\r
-\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK              = 0x0F << 2,\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT              = 0x00 << 2,\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT                = 0x01 << 2,\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT                = 0x02 << 2,\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION  = 0x03 << 2,\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ            = 0x04 << 2,\r
-    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH      = 0x05 << 2,\r
-\r
-    ARM11_DSCR_STICKY_PRECISE_DATA_ABORT               = 1 << 6,\r
-    ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT             = 1 << 7,\r
-    ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE          = 1 << 13,\r
-    ARM11_DSCR_MODE_SELECT                             = 1 << 14,\r
-    ARM11_DSCR_WDTR_FULL                               = 1 << 29,\r
-    ARM11_DSCR_RDTR_FULL                               = 1 << 30,\r
-};\r
-\r
-enum arm11_cpsr\r
-{\r
-    ARM11_CPSR_T                               = 1 << 5,\r
-    ARM11_CPSR_J                               = 1 << 24,\r
-};\r
-\r
-enum arm11_sc7\r
-{\r
-    ARM11_SC7_NULL                             = 0,\r
-    ARM11_SC7_VCR                              = 7,\r
-    ARM11_SC7_PC                               = 8,\r
-    ARM11_SC7_BVR0                             = 64,\r
-    ARM11_SC7_BCR0                             = 80,\r
-    ARM11_SC7_WVR0                             = 96,\r
-    ARM11_SC7_WCR0                             = 112,\r
-};\r
-\r
-\r
-\r
-typedef struct arm11_reg_state_s\r
-{\r
-    u32                                def_index;\r
-    target_t *                 target;\r
-} arm11_reg_state_t;\r
-\r
-\r
-\r
-\r
-/* poll current target status */\r
-int arm11_poll(struct target_s *target);\r
-/* architecture specific status reply */\r
-int arm11_arch_state(struct target_s *target);\r
-\r
-/* target request support */\r
-int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer);\r
-\r
-/* target execution control */\r
-int arm11_halt(struct target_s *target);\r
-int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);\r
-int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints);\r
-\r
-/* target reset control */\r
-int arm11_assert_reset(struct target_s *target);\r
-int arm11_deassert_reset(struct target_s *target);\r
-int arm11_soft_reset_halt(struct target_s *target);\r
-int arm11_prepare_reset_halt(struct target_s *target);\r
-\r
-/* target register access for gdb */\r
-int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);\r
-\r
-/* target memory access \r
-* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)\r
-* count: number of items of <size>\r
-*/\r
-int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-\r
-/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */\r
-int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer);\r
-\r
-int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);\r
-\r
-/* target break-/watchpoint control \r
-* rw: 0 = write, 1 = read, 2 = access\r
-*/\r
-int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);\r
-int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);\r
-int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);\r
-int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);\r
-\r
-/* target algorithm support */\r
-int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);\r
-\r
-int arm11_register_commands(struct command_context_s *cmd_ctx);\r
-int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm11_quit(void);\r
-\r
-\r
-/* helpers */\r
-void arm11_build_reg_cache(target_t *target);\r
-\r
-\r
-/* internals */\r
-\r
-void arm11_setup_field         (arm11_common_t * arm11, int num_bits, void * in_data, void * out_data, scan_field_t * field);\r
-void arm11_add_IR              (arm11_common_t * arm11, u8 instr, enum tap_state state);\r
-void arm11_add_debug_SCAN_N    (arm11_common_t * arm11, u8 chain, enum tap_state state);\r
-void arm11_add_debug_INST      (arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state);\r
-u32  arm11_read_DSCR           (arm11_common_t * arm11);\r
-void arm11_write_DSCR          (arm11_common_t * arm11, u32 dscr);\r
-\r
-enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr);\r
-\r
-void arm11_run_instr_data_prepare              (arm11_common_t * arm11);\r
-void arm11_run_instr_data_finish               (arm11_common_t * arm11);\r
-void arm11_run_instr_no_data                   (arm11_common_t * arm11, u32 * opcode, size_t count);\r
-void arm11_run_instr_no_data1                  (arm11_common_t * arm11, u32 opcode);\r
-void arm11_run_instr_data_to_core              (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);\r
-void arm11_run_instr_data_to_core1             (arm11_common_t * arm11, u32 opcode, u32 data);\r
-void arm11_run_instr_data_from_core            (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);\r
-void arm11_run_instr_data_from_core_via_r0     (arm11_common_t * arm11, u32 opcode, u32 * data);\r
-void arm11_run_instr_data_to_core_via_r0       (arm11_common_t * arm11, u32 opcode, u32 data);\r
-\r
-\r
-typedef struct arm11_sc7_action_s\r
-{\r
-    bool    write;\r
-    u8     address;\r
-    u32            value;\r
-} arm11_sc7_action_t;\r
-\r
-void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count);\r
-void arm11_sc7_clear_bw(arm11_common_t * arm11);\r
-\r
-\r
-\r
-#endif /* ARM11_H */\r
+/***************************************************************************
+ *   Copyright (C) 2008 digenius technology GmbH.                          *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef ARM11_H
+#define ARM11_H
+
+#include "target.h"
+#include "register.h"
+#include "embeddedice.h"
+#include "arm_jtag.h"
+
+
+#define bool   int
+#define true   1
+#define false  0
+
+#define asizeof(x)     (sizeof(x) / sizeof((x)[0]))
+
+#define NEW(type, variable, items) \
+    type * variable = malloc(sizeof(type) * items)
+
+
+#define ARM11_REGCACHE_MODEREGS                0
+#define ARM11_REGCACHE_FREGS           0
+
+#define ARM11_REGCACHE_COUNT           (20 +                                   \
+                                        23 * ARM11_REGCACHE_MODEREGS +         \
+                                         9 * ARM11_REGCACHE_FREGS)
+
+
+typedef struct arm11_register_history_s
+{
+    u32            value;
+    u8     valid;
+}arm11_register_history_t;
+
+
+
+typedef struct arm11_common_s
+{
+    target_t * target;
+
+    arm_jtag_t jtag_info;
+
+    /** \name Processor type detection */
+    /*@{*/
+
+    u32                device_id;          /**< IDCODE readout                         */
+    u32                didr;               /**< DIDR readout (debug capabilities)      */
+    u8         implementor;        /**< DIDR Implementor readout               */
+
+    size_t     brp;                /**< Number of Breakpoint Register Pairs    */
+    size_t     wrp;                /**< Number of Watchpoint Register Pairs    */
+
+    /*@}*/
+
+
+    u32                last_dscr;          /**< Last retrieved DSCR value;
+                                    *   Can be used to detect changes          */
+
+    u8         trst_active;
+    u8         halt_requested;
+
+    /** \name Shadow registers to save processor state */
+    /*@{*/
+
+    reg_t *    reg_list;                               /**< target register list */
+    u32                reg_values[ARM11_REGCACHE_COUNT];       /**< data for registers */
+
+    /*@}*/
+
+    arm11_register_history_t
+               reg_history[ARM11_REGCACHE_COUNT];      /**< register state before last resume */
+
+
+} arm11_common_t;
+
+
+/**
+ * ARM11 DBGTAP instructions 
+ * 
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
+ */
+enum arm11_instructions
+{
+    ARM11_EXTEST    = 0x00,
+    ARM11_SCAN_N    = 0x02,
+    ARM11_RESTART   = 0x04,
+    ARM11_HALT     = 0x08,
+    ARM11_INTEST    = 0x0C,
+    ARM11_ITRSEL    = 0x1D,
+    ARM11_IDCODE    = 0x1E,
+    ARM11_BYPASS    = 0x1F,
+};
+
+enum arm11_dscr
+{
+    ARM11_DSCR_CORE_HALTED                             = 1 << 0,
+    ARM11_DSCR_CORE_RESTARTED                          = 1 << 1,
+
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK              = 0x0F << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT              = 0x00 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT                = 0x01 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT                = 0x02 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION  = 0x03 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ            = 0x04 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH      = 0x05 << 2,
+
+    ARM11_DSCR_STICKY_PRECISE_DATA_ABORT               = 1 << 6,
+    ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT             = 1 << 7,
+    ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE          = 1 << 13,
+    ARM11_DSCR_MODE_SELECT                             = 1 << 14,
+    ARM11_DSCR_WDTR_FULL                               = 1 << 29,
+    ARM11_DSCR_RDTR_FULL                               = 1 << 30,
+};
+
+enum arm11_cpsr
+{
+    ARM11_CPSR_T                               = 1 << 5,
+    ARM11_CPSR_J                               = 1 << 24,
+};
+
+enum arm11_sc7
+{
+    ARM11_SC7_NULL                             = 0,
+    ARM11_SC7_VCR                              = 7,
+    ARM11_SC7_PC                               = 8,
+    ARM11_SC7_BVR0                             = 64,
+    ARM11_SC7_BCR0                             = 80,
+    ARM11_SC7_WVR0                             = 96,
+    ARM11_SC7_WCR0                             = 112,
+};
+
+
+
+typedef struct arm11_reg_state_s
+{
+    u32                                def_index;
+    target_t *                 target;
+} arm11_reg_state_t;
+
+
+
+
+/* poll current target status */
+int arm11_poll(struct target_s *target);
+/* architecture specific status reply */
+int arm11_arch_state(struct target_s *target);
+
+/* target request support */
+int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer);
+
+/* target execution control */
+int arm11_halt(struct target_s *target);
+int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
+int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
+
+/* target reset control */
+int arm11_assert_reset(struct target_s *target);
+int arm11_deassert_reset(struct target_s *target);
+int arm11_soft_reset_halt(struct target_s *target);
+int arm11_prepare_reset_halt(struct target_s *target);
+
+/* target register access for gdb */
+int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
+
+/* target memory access 
+* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
+* count: number of items of <size>
+*/
+int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+
+/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
+int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer);
+
+int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
+
+/* target break-/watchpoint control 
+* rw: 0 = write, 1 = read, 2 = access
+*/
+int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+
+/* target algorithm support */
+int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);
+
+int arm11_register_commands(struct command_context_s *cmd_ctx);
+int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm11_quit(void);
+
+
+/* helpers */
+void arm11_build_reg_cache(target_t *target);
+
+
+/* internals */
+
+void arm11_setup_field         (arm11_common_t * arm11, int num_bits, void * in_data, void * out_data, scan_field_t * field);
+void arm11_add_IR              (arm11_common_t * arm11, u8 instr, enum tap_state state);
+void arm11_add_debug_SCAN_N    (arm11_common_t * arm11, u8 chain, enum tap_state state);
+void arm11_add_debug_INST      (arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state);
+u32  arm11_read_DSCR           (arm11_common_t * arm11);
+void arm11_write_DSCR          (arm11_common_t * arm11, u32 dscr);
+
+enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr);
+
+void arm11_run_instr_data_prepare              (arm11_common_t * arm11);
+void arm11_run_instr_data_finish               (arm11_common_t * arm11);
+void arm11_run_instr_no_data                   (arm11_common_t * arm11, u32 * opcode, size_t count);
+void arm11_run_instr_no_data1                  (arm11_common_t * arm11, u32 opcode);
+void arm11_run_instr_data_to_core              (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
+void arm11_run_instr_data_to_core1             (arm11_common_t * arm11, u32 opcode, u32 data);
+void arm11_run_instr_data_from_core            (arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
+void arm11_run_instr_data_from_core_via_r0     (arm11_common_t * arm11, u32 opcode, u32 * data);
+void arm11_run_instr_data_to_core_via_r0       (arm11_common_t * arm11, u32 opcode, u32 data);
+
+
+typedef struct arm11_sc7_action_s
+{
+    bool    write;
+    u8     address;
+    u32            value;
+} arm11_sc7_action_t;
+
+void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count);
+void arm11_sc7_clear_bw(arm11_common_t * arm11);
+
+
+
+#endif /* ARM11_H */
index 13b412c5c62a3b3efa5c662d24259300a4d56fce..d77c9535115ea2a0fae65c736b484d4f0f079c91 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2008 digenius technology GmbH.                          *\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 "arm11.h"\r
-#include "jtag.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define JTAG_DEBUG(expr ...) \\r
-       do { \\r
-           log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \\r
-       } while(0)\r
-#else\r
-#define JTAG_DEBUG(expr ...) \\r
-       do {} while(0)\r
-#endif\r
-\r
-/** Code de-clutter: Construct scan_field_t to write out a value\r
- *\r
- * \param arm11                Target state variable.\r
- * \param num_bits     Length of the data field\r
- * \param out_data     pointer to the data that will be sent out\r
- *                     <em>(data is read when it is added to the JTAG queue)</em>\r
- * \param in_data      pointer to the memory that will receive data that was clocked in\r
- *                     <em>(data is written when the JTAG queue is executed)</em>\r
- * \param field target data structure that will be initialized\r
- */\r
-void arm11_setup_field(arm11_common_t * arm11, int num_bits, void * out_data, void * in_data, scan_field_t * field)\r
-{\r
-    field->device              = arm11->jtag_info.chain_pos;\r
-    field->num_bits            = num_bits;\r
-    field->out_mask            = NULL;\r
-    field->in_check_mask       = NULL;\r
-    field->in_check_value      = NULL;\r
-    field->in_handler          = NULL;\r
-    field->in_handler_priv     = NULL;\r
-\r
-    field->out_value           = out_data;\r
-    field->in_value            = in_data;\r
-}\r
-\r
-\r
-/** Write JTAG instruction register\r
- *\r
- * \param arm11 Target state variable.\r
- * \param instr An ARM11 DBGTAP instruction. Use enum #arm11_instructions.\r
- * \param state Pass the final TAP state or -1 for the default value (Pause-IR).\r
- *\r
- * \remarks This adds to the JTAG command queue but does \em not execute it.\r
- */\r
-void arm11_add_IR(arm11_common_t * arm11, u8 instr, enum tap_state state)\r
-{\r
-    jtag_device_t *device = jtag_get_device(arm11->jtag_info.chain_pos);\r
-\r
-    if (buf_get_u32(device->cur_instr, 0, 5) == instr)\r
-    {\r
-       JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr);\r
-       return;\r
-    }\r
-\r
-    JTAG_DEBUG("IR <= 0x%02x", instr);\r
-\r
-    scan_field_t field;\r
-\r
-    arm11_setup_field(arm11, 5, &instr, NULL, &field);\r
-\r
-    jtag_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state);\r
-}\r
-\r
-/** Verify shifted out data from Scan Chain Register (SCREG)\r
- *  Used as parameter to scan_field_t::in_handler in\r
- *  arm11_add_debug_SCAN_N().\r
- *\r
- */\r
-static int arm11_in_handler_SCAN_N(u8 *in_value, void *priv, struct scan_field_s *field)\r
-{\r
-    /** \todo TODO: clarify why this isnt properly masked in jtag.c jtag_read_buffer() */\r
-    u8 v = *in_value & 0x1F;\r
-\r
-    if (v != 0x10)\r
-    {\r
-        ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v);\r
-        exit(-1);\r
-    }\r
-\r
-    JTAG_DEBUG("SCREG SCAN OUT 0x%02x", v);\r
-    return ERROR_OK;\r
-}\r
-\r
-/** Select and write to Scan Chain Register (SCREG)\r
- * \r
- * This function sets the instruction register to SCAN_N and writes\r
- * the data register with the selected chain number.\r
- *\r
- * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/Cacbjhfg.html\r
- *\r
- * \param arm11            Target state variable.\r
- * \param chain            Scan chain that will be selected.\r
- * \param state            Pass the final TAP state or -1 for the default\r
- *                 value (Pause-DR).\r
- *\r
- * The chain takes effect when Update-DR is passed (usually when subsequently\r
- * the INTEXT/EXTEST instructions are written).\r
- *\r
- * \warning (Obsolete) Using this twice in a row will \em fail. The first call will end\r
- *          in Pause-DR. The second call, due to the IR caching, will not\r
- *         go through Capture-DR when shifting in the new scan chain number.\r
- *         As a result the verification in arm11_in_handler_SCAN_N() must\r
- *         fail.\r
- *\r
- * \remarks This adds to the JTAG command queue but does \em not execute it.\r
- */\r
-\r
-void arm11_add_debug_SCAN_N(arm11_common_t * arm11, u8 chain, enum tap_state state)\r
-{\r
-    JTAG_DEBUG("SCREG <= 0x%02x", chain);\r
-\r
-    arm11_add_IR(arm11, ARM11_SCAN_N, -1);\r
-\r
-    scan_field_t               field;\r
-\r
-    arm11_setup_field(arm11, 5, &chain, NULL, &field);\r
-\r
-    field.in_handler = arm11_in_handler_SCAN_N;\r
-\r
-    jtag_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state);\r
-}\r
-\r
-/** Write an instruction into the ITR register\r
- * \r
- * \param arm11        Target state variable.\r
- * \param inst An ARM11 processor instruction/opcode.\r
- * \param flag Optional parameter to retrieve the InstCompl flag\r
- *             (this will be written when the JTAG chain is executed). \r
- * \param state        Pass the final TAP state or -1 for the default\r
- *             value (Run-Test/Idle).\r
- *\r
- * \remarks By default this ends with Run-Test/Idle state\r
- * and causes the instruction to be executed. If\r
- * a subsequent write to DTR is needed before\r
- * executing the instruction then TAP_PD should be\r
- * passed to \p state.\r
- *\r
- * \remarks This adds to the JTAG command queue but does \em not execute it.\r
- */\r
-void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state)\r
-{\r
-    JTAG_DEBUG("INST <= 0x%08x", inst);\r
-\r
-    scan_field_t               itr[2];\r
-\r
-    arm11_setup_field(arm11, 32,    &inst,     NULL, itr + 0);\r
-    arm11_setup_field(arm11, 1,            NULL,       flag, itr + 1);\r
-\r
-    jtag_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state);\r
-}\r
-\r
-/** Read the Debug Status and Control Register (DSCR)\r
- *\r
- * same as CP14 c1\r
- *\r
- * \param arm11 Target state variable.\r
- * \return DSCR content\r
- * \r
- * \remarks This is a stand-alone function that executes the JTAG command queue.\r
- */\r
-u32 arm11_read_DSCR(arm11_common_t * arm11)\r
-{\r
-    arm11_add_debug_SCAN_N(arm11, 0x01, -1);\r
-\r
-    arm11_add_IR(arm11, ARM11_INTEST, -1);\r
-\r
-    u32                        dscr;\r
-    scan_field_t       chain1_field;\r
-\r
-    arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field);\r
-\r
-    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);\r
-\r
-    jtag_execute_queue();\r
-\r
-    if (arm11->last_dscr != dscr)\r
-        JTAG_DEBUG("DSCR  = %08x (OLD %08x)", dscr, arm11->last_dscr);\r
-\r
-    arm11->last_dscr = dscr;\r
-\r
-    return dscr;\r
-}\r
-\r
-/** Write the Debug Status and Control Register (DSCR)\r
- *\r
- * same as CP14 c1\r
- *\r
- * \param arm11 Target state variable.\r
- * \param dscr DSCR content\r
- * \r
- * \remarks This is a stand-alone function that executes the JTAG command queue.\r
- */\r
-void arm11_write_DSCR(arm11_common_t * arm11, u32 dscr)\r
-{\r
-    arm11_add_debug_SCAN_N(arm11, 0x01, -1);\r
-\r
-    arm11_add_IR(arm11, ARM11_EXTEST, -1);\r
-\r
-    scan_field_t                   chain1_field;\r
-\r
-    arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field);\r
-\r
-    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);\r
-\r
-    jtag_execute_queue();\r
-\r
-    JTAG_DEBUG("DSCR <= %08x (OLD %08x)", dscr, arm11->last_dscr);\r
-\r
-    arm11->last_dscr = dscr;\r
-}\r
-\r
-\r
-\r
-/** Get the debug reason from Debug Status and Control Register (DSCR)\r
- *\r
- * \param dscr DSCR value to analyze\r
- * \return Debug reason\r
- * \r
- */\r
-enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr)\r
-{\r
-    switch (dscr & ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK)\r
-    {\r
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT:                        return DBG_REASON_DBGRQ;\r
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT:          return DBG_REASON_BREAKPOINT;\r
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT:          return DBG_REASON_WATCHPOINT;\r
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION:    return DBG_REASON_BREAKPOINT;\r
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ:              return DBG_REASON_DBGRQ;\r
-    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH:                return DBG_REASON_BREAKPOINT;\r
-\r
-    default:\r
-       return DBG_REASON_DBGRQ;\r
-    }\r
-};\r
-\r
-\r
-\r
-/** Prepare the stage for ITR/DTR operations\r
- * from the arm11_run_instr... group of functions.\r
- *\r
- * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()\r
- * around a block of arm11_run_instr_... calls.\r
- *\r
- * Select scan chain 5 to allow quick access to DTR. When scan\r
- * chain 4 is needed to put in a register the ITRSel instruction\r
- * shortcut is used instead of actually changing the Scan_N\r
- * register.\r
- *\r
- * \param arm11 Target state variable.\r
- *\r
- */\r
-void arm11_run_instr_data_prepare(arm11_common_t * arm11)\r
-{\r
-    arm11_add_debug_SCAN_N(arm11, 0x05, -1);\r
-}\r
-\r
-/** Cleanup after ITR/DTR operations\r
- * from the arm11_run_instr... group of functions\r
- *\r
- * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()\r
- * around a block of arm11_run_instr_... calls.\r
- *\r
- * Any RTI can lead to an instruction execution when\r
- * scan chains 4 or 5 are selected and the IR holds\r
- * INTEST or EXTEST. So we must disable that before\r
- * any following activities lead to an RTI.\r
- *\r
- * \param arm11 Target state variable.\r
- *\r
- */\r
-void arm11_run_instr_data_finish(arm11_common_t * arm11)\r
-{\r
-    arm11_add_debug_SCAN_N(arm11, 0x00, -1);\r
-}\r
-\r
-\r
-/** Execute one or multiple instructions via ITR\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       Pointer to sequence of ARM opcodes\r
- * \param count                Number of opcodes to execute\r
- *\r
- */\r
-void arm11_run_instr_no_data(arm11_common_t * arm11, u32 * opcode, size_t count)\r
-{\r
-    arm11_add_IR(arm11, ARM11_ITRSEL, -1);\r
-\r
-    while (count--)\r
-    {\r
-       arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_RTI);\r
-\r
-       while (1)\r
-       {\r
-           u8 flag;\r
-\r
-           arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_RTI : TAP_PD);\r
-\r
-           jtag_execute_queue();\r
-\r
-           if (flag)\r
-               break;\r
-       }\r
-    }\r
-}\r
-\r
-/** Execute one instruction via ITR\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       ARM opcode\r
- *\r
- */\r
-void arm11_run_instr_no_data1(arm11_common_t * arm11, u32 opcode)\r
-{\r
-    arm11_run_instr_no_data(arm11, &opcode, 1);\r
-}\r
-\r
-\r
-/** Execute one instruction via ITR repeatedly while\r
- *  passing data to the core via DTR on each execution.\r
- *\r
- *  The executed instruction \em must read data from DTR.\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       ARM opcode\r
- * \param data         Pointer to the data words to be passed to the core\r
- * \param count                Number of data words and instruction repetitions\r
- *\r
- */\r
-void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)\r
-{\r
-    arm11_add_IR(arm11, ARM11_ITRSEL, -1);\r
-\r
-    arm11_add_debug_INST(arm11, opcode, NULL, TAP_PD);\r
-\r
-    arm11_add_IR(arm11, ARM11_EXTEST, -1);\r
-\r
-    scan_field_t       chain5_fields[3];\r
-\r
-    u32                        Data;\r
-    u8                 Ready;\r
-    u8                 nRetry;\r
-\r
-    arm11_setup_field(arm11, 32,    &Data,  NULL,      chain5_fields + 0);\r
-    arm11_setup_field(arm11,  1,    NULL,   &Ready,    chain5_fields + 1);\r
-    arm11_setup_field(arm11,  1,    NULL,   &nRetry,   chain5_fields + 2);\r
-\r
-    while (count--)\r
-    {\r
-       do\r
-       {\r
-           Data            = *data;\r
-\r
-           jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI);\r
-           jtag_execute_queue();\r
-\r
-           JTAG_DEBUG("DTR  Ready %d  nRetry %d", Ready, nRetry);\r
-       }\r
-       while (!Ready);\r
-\r
-       data++;\r
-    }\r
-\r
-    arm11_add_IR(arm11, ARM11_INTEST, -1);\r
-\r
-    do\r
-    {\r
-       Data        = 0;\r
-\r
-       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);\r
-       jtag_execute_queue();\r
-\r
-       JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);\r
-    }\r
-    while (!Ready);\r
-\r
-\r
-}\r
-\r
-/** Execute an instruction via ITR while handing data into the core via DTR.\r
- *\r
- *  The executed instruction \em must read data from DTR.\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       ARM opcode\r
- * \param data         Data word to be passed to the core via DTR\r
- *\r
- */\r
-void arm11_run_instr_data_to_core1(arm11_common_t * arm11, u32 opcode, u32 data)\r
-{\r
-    arm11_run_instr_data_to_core(arm11, opcode, &data, 1);\r
-}\r
-\r
-\r
-/** Execute one instruction via ITR repeatedly while\r
- *  reading data from the core via DTR on each execution.\r
- *\r
- *  The executed instruction \em must write data to DTR.\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       ARM opcode\r
- * \param data         Pointer to an array that receives the data words from the core\r
- * \param count                Number of data words and instruction repetitions\r
- *\r
- */\r
-void arm11_run_instr_data_from_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)\r
-{\r
-    arm11_add_IR(arm11, ARM11_ITRSEL, -1);\r
-\r
-    arm11_add_debug_INST(arm11, opcode, NULL, TAP_RTI);\r
-\r
-    arm11_add_IR(arm11, ARM11_INTEST, -1);\r
-\r
-    scan_field_t       chain5_fields[3];\r
-\r
-    u32                        Data;\r
-    u8                 Ready;\r
-    u8                 nRetry;\r
-\r
-    arm11_setup_field(arm11, 32,    NULL,      &Data,      chain5_fields + 0);\r
-    arm11_setup_field(arm11,  1,    NULL,      &Ready,     chain5_fields + 1);\r
-    arm11_setup_field(arm11,  1,    NULL,      &nRetry,    chain5_fields + 2);\r
-\r
-    while (count--)\r
-    {\r
-       do\r
-       {\r
-           jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD);\r
-           jtag_execute_queue();\r
-\r
-           JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);\r
-       }\r
-       while (!Ready);\r
-\r
-       *data++ = Data;\r
-    }\r
-}\r
-\r
-/** Execute one instruction via ITR\r
- *  then load r0 into DTR and read DTR from core.\r
- *\r
- *  The first executed instruction (\p opcode) should write data to r0.\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       ARM opcode to write r0 with the value of interest\r
- * \param data         Pointer to a data word that receives the value from r0 after \p opcode was executed.\r
- *\r
- */\r
-void arm11_run_instr_data_from_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 * data)\r
-{\r
-    arm11_run_instr_no_data1(arm11, opcode);\r
-\r
-    /* MCR p14,0,R0,c0,c5,0 (move r0 -> wDTR -> local var) */\r
-    arm11_run_instr_data_from_core(arm11, 0xEE000E15, data, 1);\r
-}\r
-\r
-/** Load data into core via DTR then move it to r0 then\r
- *  execute one instruction via ITR\r
- *\r
- *  The final executed instruction (\p opcode) should read data from r0.\r
- *\r
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block\r
- *\r
- * \param arm11                Target state variable.\r
- * \param opcode       ARM opcode to read r0 act upon it\r
- * \param data         Data word that will be written to r0 before \p opcode is executed\r
- *\r
- */\r
-void arm11_run_instr_data_to_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 data)\r
-{\r
-    /* MRC p14,0,r0,c0,c5,0 */\r
-    arm11_run_instr_data_to_core1(arm11, 0xEE100E15, data);\r
-\r
-    arm11_run_instr_no_data1(arm11, opcode);\r
-}\r
-\r
-\r
-void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count)\r
-{\r
-    arm11_add_debug_SCAN_N(arm11, 0x07, -1);\r
-\r
-    arm11_add_IR(arm11, ARM11_EXTEST, -1);\r
-\r
-    scan_field_t       chain7_fields[3];\r
-\r
-    u8         nRW;\r
-    u32                DataOut;\r
-    u8         AddressOut;\r
-    u8         Ready;\r
-    u32                DataIn;\r
-    u8         AddressIn;\r
-\r
-    arm11_setup_field(arm11,  1, &nRW,         &Ready,         chain7_fields + 0);\r
-    arm11_setup_field(arm11, 32, &DataOut,     &DataIn,        chain7_fields + 1);\r
-    arm11_setup_field(arm11,  7, &AddressOut,  &AddressIn,     chain7_fields + 2);\r
-\r
-    {size_t i;\r
-    for (i = 0; i < count + 1; i++)\r
-    {\r
-       if (i < count)\r
-       {\r
-           nRW         = actions[i].write ? 1 : 0;\r
-           DataOut     = actions[i].value;\r
-           AddressOut  = actions[i].address;\r
-       }\r
-       else\r
-       {\r
-           nRW         = 0;\r
-           DataOut     = 0;\r
-           AddressOut  = 0;\r
-       }\r
-\r
-        do\r
-       {\r
-           JTAG_DEBUG("SC7 <= Address %02x  Data %08x    nRW %d", AddressOut, DataOut, nRW);\r
-\r
-           jtag_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD);\r
-           jtag_execute_queue();\r
-\r
-           JTAG_DEBUG("SC7 => Address %02x  Data %08x  Ready %d", AddressIn, DataIn, Ready);\r
-       }\r
-       while (!Ready); /* 'nRW' is 'Ready' on read out */\r
-\r
-       if (i > 0)\r
-       {\r
-           if (actions[i - 1].address != AddressIn)\r
-           {\r
-               WARNING("Scan chain 7 shifted out unexpected address");\r
-           }\r
-\r
-           if (!actions[i - 1].write)\r
-           {\r
-               actions[i - 1].value = DataIn;\r
-           }\r
-           else\r
-           {\r
-               if (actions[i - 1].value != DataIn)\r
-               {\r
-                   WARNING("Scan chain 7 shifted out unexpected data");\r
-               }\r
-           }\r
-       }\r
-    }}\r
-\r
-    {size_t i;\r
-    for (i = 0; i < count; i++)\r
-    {\r
-       JTAG_DEBUG("SC7 %02d: %02x %s %08x", i, actions[i].address, actions[i].write ? "<=" : "=>", actions[i].value);\r
-    }}\r
-}\r
-\r
-void arm11_sc7_clear_bw(arm11_common_t * arm11)\r
-{\r
-    size_t actions = arm11->brp + arm11->wrp;\r
-\r
-    arm11_sc7_action_t         clear_bw[actions];\r
-\r
-    {size_t i;\r
-    for (i = 0; i < actions; i++)\r
-    {\r
-       clear_bw[i].write       = true;\r
-       clear_bw[i].value       = 0;\r
-       clear_bw[i].address     =\r
-           i < arm11->brp ?\r
-               ARM11_SC7_BCR0 + i :\r
-               ARM11_SC7_WCR0 + i - arm11->brp;\r
-    }}\r
-\r
-    arm11_sc7_run(arm11, clear_bw, actions);\r
-}\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2008 digenius technology GmbH.                          *
+ *                                                                         *
+ *   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 "arm11.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define JTAG_DEBUG(expr ...) \
+       do { \
+           log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
+       } while(0)
+#else
+#define JTAG_DEBUG(expr ...) \
+       do {} while(0)
+#endif
+
+/** Code de-clutter: Construct scan_field_t to write out a value
+ *
+ * \param arm11                Target state variable.
+ * \param num_bits     Length of the data field
+ * \param out_data     pointer to the data that will be sent out
+ *                     <em>(data is read when it is added to the JTAG queue)</em>
+ * \param in_data      pointer to the memory that will receive data that was clocked in
+ *                     <em>(data is written when the JTAG queue is executed)</em>
+ * \param field target data structure that will be initialized
+ */
+void arm11_setup_field(arm11_common_t * arm11, int num_bits, void * out_data, void * in_data, scan_field_t * field)
+{
+    field->device              = arm11->jtag_info.chain_pos;
+    field->num_bits            = num_bits;
+    field->out_mask            = NULL;
+    field->in_check_mask       = NULL;
+    field->in_check_value      = NULL;
+    field->in_handler          = NULL;
+    field->in_handler_priv     = NULL;
+
+    field->out_value           = out_data;
+    field->in_value            = in_data;
+}
+
+
+/** Write JTAG instruction register
+ *
+ * \param arm11 Target state variable.
+ * \param instr An ARM11 DBGTAP instruction. Use enum #arm11_instructions.
+ * \param state Pass the final TAP state or -1 for the default value (Pause-IR).
+ *
+ * \remarks This adds to the JTAG command queue but does \em not execute it.
+ */
+void arm11_add_IR(arm11_common_t * arm11, u8 instr, enum tap_state state)
+{
+    jtag_device_t *device = jtag_get_device(arm11->jtag_info.chain_pos);
+
+    if (buf_get_u32(device->cur_instr, 0, 5) == instr)
+    {
+       JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr);
+       return;
+    }
+
+    JTAG_DEBUG("IR <= 0x%02x", instr);
+
+    scan_field_t field;
+
+    arm11_setup_field(arm11, 5, &instr, NULL, &field);
+
+    jtag_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state);
+}
+
+/** Verify shifted out data from Scan Chain Register (SCREG)
+ *  Used as parameter to scan_field_t::in_handler in
+ *  arm11_add_debug_SCAN_N().
+ *
+ */
+static int arm11_in_handler_SCAN_N(u8 *in_value, void *priv, struct scan_field_s *field)
+{
+    /** \todo TODO: clarify why this isnt properly masked in jtag.c jtag_read_buffer() */
+    u8 v = *in_value & 0x1F;
+
+    if (v != 0x10)
+    {
+        ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v);
+        exit(-1);
+    }
+
+    JTAG_DEBUG("SCREG SCAN OUT 0x%02x", v);
+    return ERROR_OK;
+}
+
+/** Select and write to Scan Chain Register (SCREG)
+ * 
+ * This function sets the instruction register to SCAN_N and writes
+ * the data register with the selected chain number.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/Cacbjhfg.html
+ *
+ * \param arm11            Target state variable.
+ * \param chain            Scan chain that will be selected.
+ * \param state            Pass the final TAP state or -1 for the default
+ *                 value (Pause-DR).
+ *
+ * The chain takes effect when Update-DR is passed (usually when subsequently
+ * the INTEXT/EXTEST instructions are written).
+ *
+ * \warning (Obsolete) Using this twice in a row will \em fail. The first call will end
+ *          in Pause-DR. The second call, due to the IR caching, will not
+ *         go through Capture-DR when shifting in the new scan chain number.
+ *         As a result the verification in arm11_in_handler_SCAN_N() must
+ *         fail.
+ *
+ * \remarks This adds to the JTAG command queue but does \em not execute it.
+ */
+
+void arm11_add_debug_SCAN_N(arm11_common_t * arm11, u8 chain, enum tap_state state)
+{
+    JTAG_DEBUG("SCREG <= 0x%02x", chain);
+
+    arm11_add_IR(arm11, ARM11_SCAN_N, -1);
+
+    scan_field_t               field;
+
+    arm11_setup_field(arm11, 5, &chain, NULL, &field);
+
+    field.in_handler = arm11_in_handler_SCAN_N;
+
+    jtag_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state);
+}
+
+/** Write an instruction into the ITR register
+ * 
+ * \param arm11        Target state variable.
+ * \param inst An ARM11 processor instruction/opcode.
+ * \param flag Optional parameter to retrieve the InstCompl flag
+ *             (this will be written when the JTAG chain is executed). 
+ * \param state        Pass the final TAP state or -1 for the default
+ *             value (Run-Test/Idle).
+ *
+ * \remarks By default this ends with Run-Test/Idle state
+ * and causes the instruction to be executed. If
+ * a subsequent write to DTR is needed before
+ * executing the instruction then TAP_PD should be
+ * passed to \p state.
+ *
+ * \remarks This adds to the JTAG command queue but does \em not execute it.
+ */
+void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state)
+{
+    JTAG_DEBUG("INST <= 0x%08x", inst);
+
+    scan_field_t               itr[2];
+
+    arm11_setup_field(arm11, 32,    &inst,     NULL, itr + 0);
+    arm11_setup_field(arm11, 1,            NULL,       flag, itr + 1);
+
+    jtag_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state);
+}
+
+/** Read the Debug Status and Control Register (DSCR)
+ *
+ * same as CP14 c1
+ *
+ * \param arm11 Target state variable.
+ * \return DSCR content
+ * 
+ * \remarks This is a stand-alone function that executes the JTAG command queue.
+ */
+u32 arm11_read_DSCR(arm11_common_t * arm11)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x01, -1);
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    u32                        dscr;
+    scan_field_t       chain1_field;
+
+    arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field);
+
+    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);
+
+    jtag_execute_queue();
+
+    if (arm11->last_dscr != dscr)
+        JTAG_DEBUG("DSCR  = %08x (OLD %08x)", dscr, arm11->last_dscr);
+
+    arm11->last_dscr = dscr;
+
+    return dscr;
+}
+
+/** Write the Debug Status and Control Register (DSCR)
+ *
+ * same as CP14 c1
+ *
+ * \param arm11 Target state variable.
+ * \param dscr DSCR content
+ * 
+ * \remarks This is a stand-alone function that executes the JTAG command queue.
+ */
+void arm11_write_DSCR(arm11_common_t * arm11, u32 dscr)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x01, -1);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t                   chain1_field;
+
+    arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field);
+
+    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);
+
+    jtag_execute_queue();
+
+    JTAG_DEBUG("DSCR <= %08x (OLD %08x)", dscr, arm11->last_dscr);
+
+    arm11->last_dscr = dscr;
+}
+
+
+
+/** Get the debug reason from Debug Status and Control Register (DSCR)
+ *
+ * \param dscr DSCR value to analyze
+ * \return Debug reason
+ * 
+ */
+enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr)
+{
+    switch (dscr & ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK)
+    {
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT:                        return DBG_REASON_DBGRQ;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT:          return DBG_REASON_BREAKPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT:          return DBG_REASON_WATCHPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION:    return DBG_REASON_BREAKPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ:              return DBG_REASON_DBGRQ;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH:                return DBG_REASON_BREAKPOINT;
+
+    default:
+       return DBG_REASON_DBGRQ;
+    }
+};
+
+
+
+/** Prepare the stage for ITR/DTR operations
+ * from the arm11_run_instr... group of functions.
+ *
+ * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()
+ * around a block of arm11_run_instr_... calls.
+ *
+ * Select scan chain 5 to allow quick access to DTR. When scan
+ * chain 4 is needed to put in a register the ITRSel instruction
+ * shortcut is used instead of actually changing the Scan_N
+ * register.
+ *
+ * \param arm11 Target state variable.
+ *
+ */
+void arm11_run_instr_data_prepare(arm11_common_t * arm11)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x05, -1);
+}
+
+/** Cleanup after ITR/DTR operations
+ * from the arm11_run_instr... group of functions
+ *
+ * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()
+ * around a block of arm11_run_instr_... calls.
+ *
+ * Any RTI can lead to an instruction execution when
+ * scan chains 4 or 5 are selected and the IR holds
+ * INTEST or EXTEST. So we must disable that before
+ * any following activities lead to an RTI.
+ *
+ * \param arm11 Target state variable.
+ *
+ */
+void arm11_run_instr_data_finish(arm11_common_t * arm11)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x00, -1);
+}
+
+
+/** Execute one or multiple instructions via ITR
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       Pointer to sequence of ARM opcodes
+ * \param count                Number of opcodes to execute
+ *
+ */
+void arm11_run_instr_no_data(arm11_common_t * arm11, u32 * opcode, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    while (count--)
+    {
+       arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_RTI);
+
+       while (1)
+       {
+           u8 flag;
+
+           arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_RTI : TAP_PD);
+
+           jtag_execute_queue();
+
+           if (flag)
+               break;
+       }
+    }
+}
+
+/** Execute one instruction via ITR
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode
+ *
+ */
+void arm11_run_instr_no_data1(arm11_common_t * arm11, u32 opcode)
+{
+    arm11_run_instr_no_data(arm11, &opcode, 1);
+}
+
+
+/** Execute one instruction via ITR repeatedly while
+ *  passing data to the core via DTR on each execution.
+ *
+ *  The executed instruction \em must read data from DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode
+ * \param data         Pointer to the data words to be passed to the core
+ * \param count                Number of data words and instruction repetitions
+ *
+ */
+void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    arm11_add_debug_INST(arm11, opcode, NULL, TAP_PD);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t       chain5_fields[3];
+
+    u32                        Data;
+    u8                 Ready;
+    u8                 nRetry;
+
+    arm11_setup_field(arm11, 32,    &Data,  NULL,      chain5_fields + 0);
+    arm11_setup_field(arm11,  1,    NULL,   &Ready,    chain5_fields + 1);
+    arm11_setup_field(arm11,  1,    NULL,   &nRetry,   chain5_fields + 2);
+
+    while (count--)
+    {
+       do
+       {
+           Data            = *data;
+
+           jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI);
+           jtag_execute_queue();
+
+           JTAG_DEBUG("DTR  Ready %d  nRetry %d", Ready, nRetry);
+       }
+       while (!Ready);
+
+       data++;
+    }
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    do
+    {
+       Data        = 0;
+
+       jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+       jtag_execute_queue();
+
+       JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);
+    }
+    while (!Ready);
+
+
+}
+
+/** Execute an instruction via ITR while handing data into the core via DTR.
+ *
+ *  The executed instruction \em must read data from DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode
+ * \param data         Data word to be passed to the core via DTR
+ *
+ */
+void arm11_run_instr_data_to_core1(arm11_common_t * arm11, u32 opcode, u32 data)
+{
+    arm11_run_instr_data_to_core(arm11, opcode, &data, 1);
+}
+
+
+/** Execute one instruction via ITR repeatedly while
+ *  reading data from the core via DTR on each execution.
+ *
+ *  The executed instruction \em must write data to DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode
+ * \param data         Pointer to an array that receives the data words from the core
+ * \param count                Number of data words and instruction repetitions
+ *
+ */
+void arm11_run_instr_data_from_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    arm11_add_debug_INST(arm11, opcode, NULL, TAP_RTI);
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    scan_field_t       chain5_fields[3];
+
+    u32                        Data;
+    u8                 Ready;
+    u8                 nRetry;
+
+    arm11_setup_field(arm11, 32,    NULL,      &Data,      chain5_fields + 0);
+    arm11_setup_field(arm11,  1,    NULL,      &Ready,     chain5_fields + 1);
+    arm11_setup_field(arm11,  1,    NULL,      &nRetry,    chain5_fields + 2);
+
+    while (count--)
+    {
+       do
+       {
+           jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD);
+           jtag_execute_queue();
+
+           JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);
+       }
+       while (!Ready);
+
+       *data++ = Data;
+    }
+}
+
+/** Execute one instruction via ITR
+ *  then load r0 into DTR and read DTR from core.
+ *
+ *  The first executed instruction (\p opcode) should write data to r0.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode to write r0 with the value of interest
+ * \param data         Pointer to a data word that receives the value from r0 after \p opcode was executed.
+ *
+ */
+void arm11_run_instr_data_from_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 * data)
+{
+    arm11_run_instr_no_data1(arm11, opcode);
+
+    /* MCR p14,0,R0,c0,c5,0 (move r0 -> wDTR -> local var) */
+    arm11_run_instr_data_from_core(arm11, 0xEE000E15, data, 1);
+}
+
+/** Load data into core via DTR then move it to r0 then
+ *  execute one instruction via ITR
+ *
+ *  The final executed instruction (\p opcode) should read data from r0.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode to read r0 act upon it
+ * \param data         Data word that will be written to r0 before \p opcode is executed
+ *
+ */
+void arm11_run_instr_data_to_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 data)
+{
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xEE100E15, data);
+
+    arm11_run_instr_no_data1(arm11, opcode);
+}
+
+
+void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x07, -1);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t       chain7_fields[3];
+
+    u8         nRW;
+    u32                DataOut;
+    u8         AddressOut;
+    u8         Ready;
+    u32                DataIn;
+    u8         AddressIn;
+
+    arm11_setup_field(arm11,  1, &nRW,         &Ready,         chain7_fields + 0);
+    arm11_setup_field(arm11, 32, &DataOut,     &DataIn,        chain7_fields + 1);
+    arm11_setup_field(arm11,  7, &AddressOut,  &AddressIn,     chain7_fields + 2);
+
+    {size_t i;
+    for (i = 0; i < count + 1; i++)
+    {
+       if (i < count)
+       {
+           nRW         = actions[i].write ? 1 : 0;
+           DataOut     = actions[i].value;
+           AddressOut  = actions[i].address;
+       }
+       else
+       {
+           nRW         = 0;
+           DataOut     = 0;
+           AddressOut  = 0;
+       }
+
+        do
+       {
+           JTAG_DEBUG("SC7 <= Address %02x  Data %08x    nRW %d", AddressOut, DataOut, nRW);
+
+           jtag_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD);
+           jtag_execute_queue();
+
+           JTAG_DEBUG("SC7 => Address %02x  Data %08x  Ready %d", AddressIn, DataIn, Ready);
+       }
+       while (!Ready); /* 'nRW' is 'Ready' on read out */
+
+       if (i > 0)
+       {
+           if (actions[i - 1].address != AddressIn)
+           {
+               WARNING("Scan chain 7 shifted out unexpected address");
+           }
+
+           if (!actions[i - 1].write)
+           {
+               actions[i - 1].value = DataIn;
+           }
+           else
+           {
+               if (actions[i - 1].value != DataIn)
+               {
+                   WARNING("Scan chain 7 shifted out unexpected data");
+               }
+           }
+       }
+    }}
+
+    {size_t i;
+    for (i = 0; i < count; i++)
+    {
+       JTAG_DEBUG("SC7 %02d: %02x %s %08x", i, actions[i].address, actions[i].write ? "<=" : "=>", actions[i].value);
+    }}
+}
+
+void arm11_sc7_clear_bw(arm11_common_t * arm11)
+{
+    size_t actions = arm11->brp + arm11->wrp;
+
+    arm11_sc7_action_t         clear_bw[actions];
+
+    {size_t i;
+    for (i = 0; i < actions; i++)
+    {
+       clear_bw[i].write       = true;
+       clear_bw[i].value       = 0;
+       clear_bw[i].address     =
+           i < arm11->brp ?
+               ARM11_SC7_BCR0 + i :
+               ARM11_SC7_WCR0 + i - arm11->brp;
+    }}
+
+    arm11_sc7_run(arm11, clear_bw, actions);
+}
+
index 87a1afb463074c674d5949ad6f1e12d00d29e984..2c7e2aea3495bb09f688952475bbfb3b2028b594 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm720t.h"\r
-#include "jtag.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-/* cli handling */\r
-int arm720t_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm720t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm720t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm720t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-/* forward declarations */\r
-int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm720t_quit();\r
-int arm720t_arch_state(struct target_s *target);\r
-int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm720t_soft_reset_halt(struct target_s *target);\r
-\r
-target_type_t arm720t_target =\r
-{\r
-       .name = "arm720t",\r
-\r
-       .poll = arm7_9_poll,\r
-       .arch_state = arm720t_arch_state,\r
-\r
-       .halt = arm7_9_halt,\r
-       .resume = arm7_9_resume,\r
-       .step = arm7_9_step,\r
-\r
-       .assert_reset = arm7_9_assert_reset,\r
-       .deassert_reset = arm7_9_deassert_reset,\r
-       .soft_reset_halt = arm720t_soft_reset_halt,\r
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
-       \r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-\r
-       .read_memory = arm720t_read_memory,\r
-       .write_memory = arm720t_write_memory,\r
-       .bulk_write_memory = arm7_9_bulk_write_memory,\r
-       .checksum_memory = arm7_9_checksum_memory,\r
-       \r
-       .run_algorithm = armv4_5_run_algorithm,\r
-\r
-       .add_breakpoint = arm7_9_add_breakpoint,\r
-       .remove_breakpoint = arm7_9_remove_breakpoint,\r
-       .add_watchpoint = arm7_9_add_watchpoint,\r
-       .remove_watchpoint = arm7_9_remove_watchpoint,\r
-\r
-       .register_commands = arm720t_register_commands,\r
-       .target_command = arm720t_target_command,\r
-       .init_target = arm720t_init_target,\r
-       .quit = arm720t_quit\r
-};\r
-\r
-int arm720t_scan_cp15(target_t *target, u32 out, u32 *in, int instruction, int clock)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       scan_field_t fields[2];\r
-       u8 out_buf[4];\r
-       u8 instruction_buf = instruction;\r
-       \r
-       buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));\r
-       \r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-               \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = &instruction_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = out_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       if (in)\r
-       {\r
-               fields[1].in_handler = arm_jtag_buf_to_u32_flip;\r
-               fields[1].in_handler_priv = in;\r
-       } else\r
-       {\r
-               fields[1].in_handler = NULL;\r
-               fields[1].in_handler_priv = NULL;\r
-       }\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       \r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       if (clock)\r
-               jtag_add_runtest(0, -1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       jtag_execute_queue();\r
-\r
-       if (in)\r
-               DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);\r
-       else\r
-               DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);\r
-#else\r
-               DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_read_cp15(target_t *target, u32 opcode, u32 *value)\r
-{\r
-       /* fetch CP15 opcode */\r
-       arm720t_scan_cp15(target, opcode, NULL, 1, 1);\r
-       /* "DECODE" stage */\r
-       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);\r
-       /* "EXECUTE" stage (1) */\r
-       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);\r
-       arm720t_scan_cp15(target, 0x0, NULL, 0, 1);\r
-       /* "EXECUTE" stage (2) */\r
-       arm720t_scan_cp15(target, 0x0, NULL, 0, 1);\r
-       /* "EXECUTE" stage (3), CDATA is read */\r
-       arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_write_cp15(target_t *target, u32 opcode, u32 value)\r
-{\r
-       /* fetch CP15 opcode */\r
-       arm720t_scan_cp15(target, opcode, NULL, 1, 1);\r
-       /* "DECODE" stage */\r
-       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);\r
-       /* "EXECUTE" stage (1) */\r
-       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);\r
-       arm720t_scan_cp15(target, 0x0, NULL, 0, 1);\r
-       /* "EXECUTE" stage (2) */\r
-       arm720t_scan_cp15(target, value, NULL, 0, 1);\r
-       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-u32 arm720t_get_ttb(target_t *target)\r
-{\r
-       u32 ttb = 0x0;\r
-\r
-       arm720t_read_cp15(target, 0xee120f10, &ttb);\r
-       jtag_execute_queue();\r
-       \r
-       ttb &= 0xffffc000;\r
-       \r
-       return ttb;\r
-}\r
-\r
-void arm720t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       arm720t_read_cp15(target, 0xee110f10, &cp15_control);\r
-       jtag_execute_queue();\r
-               \r
-       if (mmu)\r
-               cp15_control &= ~0x1U;\r
-       \r
-       if (d_u_cache || i_cache)\r
-               cp15_control &= ~0x4U;\r
-\r
-       arm720t_write_cp15(target, 0xee010f10, cp15_control);\r
-}\r
-\r
-void arm720t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       arm720t_read_cp15(target, 0xee110f10, &cp15_control);\r
-       jtag_execute_queue();\r
-               \r
-       if (mmu)\r
-               cp15_control |= 0x1U;\r
-       \r
-       if (d_u_cache || i_cache)\r
-               cp15_control |= 0x4U;\r
-       \r
-       arm720t_write_cp15(target, 0xee010f10, cp15_control);\r
-}\r
-\r
-void arm720t_post_debug_entry(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;\r
-       arm720t_common_t *arm720t = arm7tdmi->arch_info;\r
-       \r
-       /* examine cp15 control reg */\r
-       arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);\r
-       jtag_execute_queue();\r
-       DEBUG("cp15_control_reg: %8.8x", arm720t->cp15_control_reg);\r
-\r
-       arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;\r
-       arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;\r
-       arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;\r
-\r
-       /* save i/d fault status and address register */\r
-       arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);\r
-       arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);\r
-       jtag_execute_queue();\r
-}\r
-\r
-void arm720t_pre_restore_context(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;\r
-       arm720t_common_t *arm720t = arm7tdmi->arch_info;\r
-       \r
-       /* restore i/d fault status and address register */\r
-       arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);\r
-       arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);\r
-}\r
-\r
-int arm720t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm7tdmi_common_t **arm7tdmi_p, arm720t_common_t **arm720t_p)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9;\r
-       arm7tdmi_common_t *arm7tdmi;\r
-       arm720t_common_t *arm720t;\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm7_9 = armv4_5->arch_info;\r
-       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm7tdmi = arm7_9->arch_info;\r
-       if (arm7tdmi->common_magic != ARM7TDMI_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm720t = arm7tdmi->arch_info;\r
-       if (arm720t->common_magic != ARM720T_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       *armv4_5_p = armv4_5;\r
-       *arm7_9_p = arm7_9;\r
-       *arm7tdmi_p = arm7tdmi;\r
-       *arm720t_p = arm720t;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_arch_state(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;\r
-       arm720t_common_t *arm720t = arm7tdmi->arch_info;\r
-       \r
-       char *state[] = \r
-       {\r
-               "disabled", "enabled"\r
-       };\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               ERROR("BUG: called for a non-ARMv4/5 target");\r
-               exit(-1);\r
-       }\r
-       \r
-       USER("target halted in %s state due to %s, current mode: %s\n"\r
-                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"\r
-                       "MMU: %s, Cache: %s",\r
-                        armv4_5_state_strings[armv4_5->core_state],\r
-                        target_debug_reason_strings[target->debug_reason],\r
-                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),\r
-                        state[arm720t->armv4_5_mmu.mmu_enabled],\r
-                        state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       int retval;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;\r
-       arm720t_common_t *arm720t = arm7tdmi->arch_info;\r
-       \r
-       /* disable cache, but leave MMU enabled */\r
-       if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)\r
-               arm720t_disable_mmu_caches(target, 0, 1, 0);\r
-       \r
-       retval = arm7_9_read_memory(target, address, size, count, buffer);\r
-       \r
-       if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)\r
-               arm720t_enable_mmu_caches(target, 0, 1, 0);\r
-       \r
-       return retval;\r
-}\r
-\r
-int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       int retval;\r
-       \r
-       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)\r
-               return retval;\r
-\r
-       return retval;\r
-}\r
-\r
-int arm720t_soft_reset_halt(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;\r
-       arm720t_common_t *arm720t = arm7tdmi->arch_info;\r
-       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
-       \r
-       if (target->state == TARGET_RUNNING)\r
-       {\r
-               target->type->halt(target);\r
-       }\r
-       \r
-       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)\r
-       {\r
-               embeddedice_read_reg(dbg_stat);\r
-               jtag_execute_queue();\r
-       }\r
-       \r
-       target->state = TARGET_HALTED;\r
-       \r
-       /* SVC, ARM state, IRQ and FIQ disabled */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;\r
-       \r
-       /* start fetching from 0x0 */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);\r
-       armv4_5->core_cache->reg_list[15].dirty = 1;\r
-       armv4_5->core_cache->reg_list[15].valid = 1;\r
-       \r
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;\r
-       armv4_5->core_state = ARMV4_5_STATE_ARM;\r
-       \r
-       arm720t_disable_mmu_caches(target, 1, 1, 1);\r
-       arm720t->armv4_5_mmu.mmu_enabled = 0;\r
-       arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;\r
-       arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;\r
-\r
-       target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       arm7tdmi_init_target(cmd_ctx, target);\r
-               \r
-       return ERROR_OK;\r
-       \r
-}\r
-\r
-int arm720t_quit()\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_init_arch_info(target_t *target, arm720t_common_t *arm720t, int chain_pos, char *variant)\r
-{\r
-       arm7tdmi_common_t *arm7tdmi = &arm720t->arm7tdmi_common;\r
-       arm7_9_common_t *arm7_9 = &arm7tdmi->arm7_9_common;\r
-       \r
-       arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);\r
-\r
-       arm7tdmi->arch_info = arm720t;\r
-       arm720t->common_magic = ARM720T_COMMON_MAGIC;\r
-       \r
-       arm7_9->post_debug_entry = arm720t_post_debug_entry;\r
-       arm7_9->pre_restore_context = arm720t_pre_restore_context;\r
-       \r
-       arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;\r
-       arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;\r
-       arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;\r
-       arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;\r
-       arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;\r
-       arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;\r
-       arm720t->armv4_5_mmu.has_tiny_pages = 0;\r
-       arm720t->armv4_5_mmu.mmu_enabled = 0;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       arm720t_common_t *arm720t = malloc(sizeof(arm720t_common_t));\r
-       \r
-       if (argc < 4)\r
-       {\r
-               ERROR("'target arm720t' requires at least one additional argument");\r
-               exit(-1);\r
-       }\r
-       \r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-       \r
-       if (argc >= 5)\r
-               variant = args[4];\r
-       \r
-       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);\r
-       \r
-       arm720t_init_arch_info(target, arm720t, chain_pos, variant);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       command_t *arm720t_cmd;\r
-       \r
-               \r
-       retval = arm7tdmi_register_commands(cmd_ctx);\r
-       \r
-       arm720t_cmd = register_command(cmd_ctx, NULL, "arm720t", NULL, COMMAND_ANY, "arm720t specific commands");\r
-\r
-       register_command(cmd_ctx, arm720t_cmd, "cp15", arm720t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode> [value]");\r
-       register_command(cmd_ctx, arm720t_cmd, "virt2phys", arm720t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");\r
-\r
-       register_command(cmd_ctx, arm720t_cmd, "mdw_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");\r
-       register_command(cmd_ctx, arm720t_cmd, "mdh_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");\r
-       register_command(cmd_ctx, arm720t_cmd, "mdb_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");\r
-\r
-       register_command(cmd_ctx, arm720t_cmd, "mww_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");\r
-       register_command(cmd_ctx, arm720t_cmd, "mwh_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");\r
-       register_command(cmd_ctx, arm720t_cmd, "mwb_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm7tdmi_common_t *arm7tdmi;\r
-       arm720t_common_t *arm720t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM720t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       /* one or more argument, access a single register (write if second argument is given */\r
-       if (argc >= 1)\r
-       {\r
-               u32 opcode = strtoul(args[0], NULL, 0);\r
-\r
-               if (argc == 1)\r
-               {\r
-                       u32 value;\r
-                       if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);\r
-                               return ERROR_OK;\r
-                       }\r
-                       jtag_execute_queue();\r
-                       \r
-                       command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);\r
-               }\r
-               else if (argc == 2)\r
-               {\r
-                       u32 value = strtoul(args[1], NULL, 0);\r
-                       if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);\r
-                               return ERROR_OK;\r
-                       }\r
-                       command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm720t_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm7tdmi_common_t *arm7tdmi;\r
-       arm720t_common_t *arm720t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM720t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-               \r
-       return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);\r
-}\r
-\r
-int arm720t_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm7tdmi_common_t *arm7tdmi;\r
-       arm720t_common_t *arm720t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM720t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);\r
-}\r
-\r
-int arm720t_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm7tdmi_common_t *arm7tdmi;\r
-       arm720t_common_t *arm720t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM720t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);\r
-}\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm720t.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm720t_register_commands(struct command_context_s *cmd_ctx);
+
+int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm720t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm720t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm720t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm720t_quit();
+int arm720t_arch_state(struct target_s *target);
+int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm720t_soft_reset_halt(struct target_s *target);
+
+target_type_t arm720t_target =
+{
+       .name = "arm720t",
+
+       .poll = arm7_9_poll,
+       .arch_state = arm720t_arch_state,
+
+       .halt = arm7_9_halt,
+       .resume = arm7_9_resume,
+       .step = arm7_9_step,
+
+       .assert_reset = arm7_9_assert_reset,
+       .deassert_reset = arm7_9_deassert_reset,
+       .soft_reset_halt = arm720t_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
+       
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+       .read_memory = arm720t_read_memory,
+       .write_memory = arm720t_write_memory,
+       .bulk_write_memory = arm7_9_bulk_write_memory,
+       .checksum_memory = arm7_9_checksum_memory,
+       
+       .run_algorithm = armv4_5_run_algorithm,
+
+       .add_breakpoint = arm7_9_add_breakpoint,
+       .remove_breakpoint = arm7_9_remove_breakpoint,
+       .add_watchpoint = arm7_9_add_watchpoint,
+       .remove_watchpoint = arm7_9_remove_watchpoint,
+
+       .register_commands = arm720t_register_commands,
+       .target_command = arm720t_target_command,
+       .init_target = arm720t_init_target,
+       .quit = arm720t_quit
+};
+
+int arm720t_scan_cp15(target_t *target, u32 out, u32 *in, int instruction, int clock)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       scan_field_t fields[2];
+       u8 out_buf[4];
+       u8 instruction_buf = instruction;
+       
+       buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
+       
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+               
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = &instruction_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = out_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       if (in)
+       {
+               fields[1].in_handler = arm_jtag_buf_to_u32_flip;
+               fields[1].in_handler_priv = in;
+       } else
+       {
+               fields[1].in_handler = NULL;
+               fields[1].in_handler_priv = NULL;
+       }
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       
+       jtag_add_dr_scan(2, fields, -1);
+
+       if (clock)
+               jtag_add_runtest(0, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       jtag_execute_queue();
+
+       if (in)
+               DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
+       else
+               DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
+#else
+               DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
+#endif
+
+       return ERROR_OK;
+}
+
+int arm720t_read_cp15(target_t *target, u32 opcode, u32 *value)
+{
+       /* fetch CP15 opcode */
+       arm720t_scan_cp15(target, opcode, NULL, 1, 1);
+       /* "DECODE" stage */
+       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
+       /* "EXECUTE" stage (1) */
+       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
+       arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
+       /* "EXECUTE" stage (2) */
+       arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
+       /* "EXECUTE" stage (3), CDATA is read */
+       arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
+       
+       return ERROR_OK;
+}
+
+int arm720t_write_cp15(target_t *target, u32 opcode, u32 value)
+{
+       /* fetch CP15 opcode */
+       arm720t_scan_cp15(target, opcode, NULL, 1, 1);
+       /* "DECODE" stage */
+       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
+       /* "EXECUTE" stage (1) */
+       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
+       arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
+       /* "EXECUTE" stage (2) */
+       arm720t_scan_cp15(target, value, NULL, 0, 1);
+       arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
+
+       return ERROR_OK;
+}
+
+u32 arm720t_get_ttb(target_t *target)
+{
+       u32 ttb = 0x0;
+
+       arm720t_read_cp15(target, 0xee120f10, &ttb);
+       jtag_execute_queue();
+       
+       ttb &= 0xffffc000;
+       
+       return ttb;
+}
+
+void arm720t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       arm720t_read_cp15(target, 0xee110f10, &cp15_control);
+       jtag_execute_queue();
+               
+       if (mmu)
+               cp15_control &= ~0x1U;
+       
+       if (d_u_cache || i_cache)
+               cp15_control &= ~0x4U;
+
+       arm720t_write_cp15(target, 0xee010f10, cp15_control);
+}
+
+void arm720t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       arm720t_read_cp15(target, 0xee110f10, &cp15_control);
+       jtag_execute_queue();
+               
+       if (mmu)
+               cp15_control |= 0x1U;
+       
+       if (d_u_cache || i_cache)
+               cp15_control |= 0x4U;
+       
+       arm720t_write_cp15(target, 0xee010f10, cp15_control);
+}
+
+void arm720t_post_debug_entry(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+       arm720t_common_t *arm720t = arm7tdmi->arch_info;
+       
+       /* examine cp15 control reg */
+       arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
+       jtag_execute_queue();
+       DEBUG("cp15_control_reg: %8.8x", arm720t->cp15_control_reg);
+
+       arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
+       arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
+       arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+       /* save i/d fault status and address register */
+       arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
+       arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
+       jtag_execute_queue();
+}
+
+void arm720t_pre_restore_context(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+       arm720t_common_t *arm720t = arm7tdmi->arch_info;
+       
+       /* restore i/d fault status and address register */
+       arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
+       arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
+}
+
+int arm720t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm7tdmi_common_t **arm7tdmi_p, arm720t_common_t **arm720t_p)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9;
+       arm7tdmi_common_t *arm7tdmi;
+       arm720t_common_t *arm720t;
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm7_9 = armv4_5->arch_info;
+       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm7tdmi = arm7_9->arch_info;
+       if (arm7tdmi->common_magic != ARM7TDMI_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm720t = arm7tdmi->arch_info;
+       if (arm720t->common_magic != ARM720T_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       *armv4_5_p = armv4_5;
+       *arm7_9_p = arm7_9;
+       *arm7tdmi_p = arm7tdmi;
+       *arm720t_p = arm720t;
+       
+       return ERROR_OK;
+}
+
+int arm720t_arch_state(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+       arm720t_common_t *arm720t = arm7tdmi->arch_info;
+       
+       char *state[] = 
+       {
+               "disabled", "enabled"
+       };
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               ERROR("BUG: called for a non-ARMv4/5 target");
+               exit(-1);
+       }
+       
+       USER("target halted in %s state due to %s, current mode: %s\n"
+                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"
+                       "MMU: %s, Cache: %s",
+                        armv4_5_state_strings[armv4_5->core_state],
+                        target_debug_reason_strings[target->debug_reason],
+                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
+                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
+                        state[arm720t->armv4_5_mmu.mmu_enabled],
+                        state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
+       
+       return ERROR_OK;
+}
+
+int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       int retval;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+       arm720t_common_t *arm720t = arm7tdmi->arch_info;
+       
+       /* disable cache, but leave MMU enabled */
+       if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+               arm720t_disable_mmu_caches(target, 0, 1, 0);
+       
+       retval = arm7_9_read_memory(target, address, size, count, buffer);
+       
+       if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+               arm720t_enable_mmu_caches(target, 0, 1, 0);
+       
+       return retval;
+}
+
+int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       int retval;
+       
+       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+               return retval;
+
+       return retval;
+}
+
+int arm720t_soft_reset_halt(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+       arm720t_common_t *arm720t = arm7tdmi->arch_info;
+       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+       
+       if (target->state == TARGET_RUNNING)
+       {
+               target->type->halt(target);
+       }
+       
+       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
+       {
+               embeddedice_read_reg(dbg_stat);
+               jtag_execute_queue();
+       }
+       
+       target->state = TARGET_HALTED;
+       
+       /* SVC, ARM state, IRQ and FIQ disabled */
+       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+       
+       /* start fetching from 0x0 */
+       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+       armv4_5->core_cache->reg_list[15].dirty = 1;
+       armv4_5->core_cache->reg_list[15].valid = 1;
+       
+       armv4_5->core_mode = ARMV4_5_MODE_SVC;
+       armv4_5->core_state = ARMV4_5_STATE_ARM;
+       
+       arm720t_disable_mmu_caches(target, 1, 1, 1);
+       arm720t->armv4_5_mmu.mmu_enabled = 0;
+       arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+       arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+       
+       return ERROR_OK;
+}
+
+int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       arm7tdmi_init_target(cmd_ctx, target);
+               
+       return ERROR_OK;
+       
+}
+
+int arm720t_quit()
+{
+       
+       return ERROR_OK;
+}
+
+int arm720t_init_arch_info(target_t *target, arm720t_common_t *arm720t, int chain_pos, char *variant)
+{
+       arm7tdmi_common_t *arm7tdmi = &arm720t->arm7tdmi_common;
+       arm7_9_common_t *arm7_9 = &arm7tdmi->arm7_9_common;
+       
+       arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);
+
+       arm7tdmi->arch_info = arm720t;
+       arm720t->common_magic = ARM720T_COMMON_MAGIC;
+       
+       arm7_9->post_debug_entry = arm720t_post_debug_entry;
+       arm7_9->pre_restore_context = arm720t_pre_restore_context;
+       
+       arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
+       arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
+       arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
+       arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
+       arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
+       arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
+       arm720t->armv4_5_mmu.has_tiny_pages = 0;
+       arm720t->armv4_5_mmu.mmu_enabled = 0;
+       
+       return ERROR_OK;
+}
+
+int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       arm720t_common_t *arm720t = malloc(sizeof(arm720t_common_t));
+       
+       if (argc < 4)
+       {
+               ERROR("'target arm720t' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+       
+       arm720t_init_arch_info(target, arm720t, chain_pos, variant);
+
+       return ERROR_OK;
+}
+
+int arm720t_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       command_t *arm720t_cmd;
+       
+               
+       retval = arm7tdmi_register_commands(cmd_ctx);
+       
+       arm720t_cmd = register_command(cmd_ctx, NULL, "arm720t", NULL, COMMAND_ANY, "arm720t specific commands");
+
+       register_command(cmd_ctx, arm720t_cmd, "cp15", arm720t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode> [value]");
+       register_command(cmd_ctx, arm720t_cmd, "virt2phys", arm720t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
+
+       register_command(cmd_ctx, arm720t_cmd, "mdw_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
+       register_command(cmd_ctx, arm720t_cmd, "mdh_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
+       register_command(cmd_ctx, arm720t_cmd, "mdb_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
+
+       register_command(cmd_ctx, arm720t_cmd, "mww_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
+       register_command(cmd_ctx, arm720t_cmd, "mwh_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
+       register_command(cmd_ctx, arm720t_cmd, "mwb_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
+       
+       return ERROR_OK;
+}
+
+int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm7tdmi_common_t *arm7tdmi;
+       arm720t_common_t *arm720t;
+       arm_jtag_t *jtag_info;
+
+       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM720t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       /* one or more argument, access a single register (write if second argument is given */
+       if (argc >= 1)
+       {
+               u32 opcode = strtoul(args[0], NULL, 0);
+
+               if (argc == 1)
+               {
+                       u32 value;
+                       if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);
+                               return ERROR_OK;
+                       }
+                       jtag_execute_queue();
+                       
+                       command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);
+               }
+               else if (argc == 2)
+               {
+                       u32 value = strtoul(args[1], NULL, 0);
+                       if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);
+                               return ERROR_OK;
+                       }
+                       command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int arm720t_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm7tdmi_common_t *arm7tdmi;
+       arm720t_common_t *arm720t;
+       arm_jtag_t *jtag_info;
+
+       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM720t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+               
+       return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
+}
+
+int arm720t_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm7tdmi_common_t *arm7tdmi;
+       arm720t_common_t *arm720t;
+       arm_jtag_t *jtag_info;
+
+       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM720t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
+}
+
+int arm720t_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm7tdmi_common_t *arm7tdmi;
+       arm720t_common_t *arm720t;
+       arm_jtag_t *jtag_info;
+
+       if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM720t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
+}
+
index 2a149425be613df70eb6cf9e90aa434f43b59f92..af0205d6855b8371d6560dadbf1d63a77e53c337 100644 (file)
@@ -676,7 +676,7 @@ int arm7_9_handle_target_request(void *priv)
        return ERROR_OK;
 }
 
-int arm7_9_poll(target_t *target)\r
+int arm7_9_poll(target_t *target)
 {
        int retval;
        armv4_5_common_t *armv4_5 = target->arch_info;
@@ -692,15 +692,15 @@ int arm7_9_poll(target_t *target)
        embeddedice_read_reg(dbg_stat);
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
-               return retval;\r
+               return retval;
        }
        
        if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
        {
                DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));
-               if (target->state == TARGET_UNKNOWN)\r
+               if (target->state == TARGET_UNKNOWN)
                {
-                       WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");\r
+                       WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
                }
                if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
                {
@@ -718,18 +718,18 @@ int arm7_9_poll(target_t *target)
                        
                        target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
                }
-               if (target->state != TARGET_HALTED)\r
-               {\r
-                       WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);\r
+               if (target->state != TARGET_HALTED)
+               {
+                       WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
                }
-       }\r
+       }
        else
        {
                if (target->state != TARGET_DEBUG_RUNNING)
                        target->state = TARGET_RUNNING;
        }
        
-       return ERROR_OK;\r
+       return ERROR_OK;
 }
 
 int arm7_9_assert_reset(target_t *target)
index 5679bbc6e6d4898c05bb251187b08f5e16618fee..d8d5e57ed0f6c9f218ebcf16b61586c3d2dad154 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm7tdmi.h"\r
-\r
-#include "arm7_9_common.h"\r
-#include "register.h"\r
-#include "target.h"\r
-#include "armv4_5.h"\r
-#include "embeddedice.h"\r
-#include "etm.h"\r
-#include "log.h"\r
-#include "jtag.h"\r
-#include "arm_jtag.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-/* cli handling */\r
-int arm7tdmi_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-/* forward declarations */\r
-int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm7tdmi_quit();\r
-\r
-/* target function declarations */\r
-int arm7tdmi_poll(struct target_s *target);\r
-int arm7tdmi_halt(target_t *target);\r
-               \r
-target_type_t arm7tdmi_target =\r
-{\r
-       .name = "arm7tdmi",\r
-\r
-       .poll = arm7_9_poll,\r
-       .arch_state = armv4_5_arch_state,\r
-\r
-       .target_request_data = arm7_9_target_request_data,\r
-\r
-       .halt = arm7_9_halt,\r
-       .resume = arm7_9_resume,\r
-       .step = arm7_9_step,\r
-\r
-       .assert_reset = arm7_9_assert_reset,\r
-       .deassert_reset = arm7_9_deassert_reset,\r
-       .soft_reset_halt = arm7_9_soft_reset_halt,\r
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
-\r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-       \r
-       .read_memory = arm7_9_read_memory,\r
-       .write_memory = arm7_9_write_memory,\r
-       .bulk_write_memory = arm7_9_bulk_write_memory,\r
-       .checksum_memory = arm7_9_checksum_memory,\r
-       \r
-       .run_algorithm = armv4_5_run_algorithm,\r
-       \r
-       .add_breakpoint = arm7_9_add_breakpoint,\r
-       .remove_breakpoint = arm7_9_remove_breakpoint,\r
-       .add_watchpoint = arm7_9_add_watchpoint,\r
-       .remove_watchpoint = arm7_9_remove_watchpoint,\r
-\r
-       .register_commands = arm7tdmi_register_commands,\r
-       .target_command = arm7tdmi_target_command,\r
-       .init_target = arm7tdmi_init_target,\r
-       .quit = arm7tdmi_quit\r
-};\r
-\r
-int arm7tdmi_examine_debug_reason(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       \r
-       /* only check the debug reason if we don't know it already */\r
-       if ((target->debug_reason != DBG_REASON_DBGRQ)\r
-                       && (target->debug_reason != DBG_REASON_SINGLESTEP))\r
-       {\r
-               scan_field_t fields[2];\r
-               u8 databus[4];\r
-               u8 breakpoint;\r
-               \r
-               jtag_add_end_state(TAP_PD);\r
-\r
-               fields[0].device = arm7_9->jtag_info.chain_pos;\r
-               fields[0].num_bits = 1;\r
-               fields[0].out_value = NULL;\r
-               fields[0].out_mask = NULL;\r
-               fields[0].in_value = &breakpoint;\r
-               fields[0].in_check_value = NULL;\r
-               fields[0].in_check_mask = NULL;\r
-               fields[0].in_handler = NULL;\r
-               fields[0].in_handler_priv = NULL;\r
-               \r
-               fields[1].device = arm7_9->jtag_info.chain_pos;\r
-               fields[1].num_bits = 32;\r
-               fields[1].out_value = NULL;\r
-               fields[1].out_mask = NULL;\r
-               fields[1].in_value = databus;\r
-               fields[1].in_check_value = NULL;\r
-               fields[1].in_check_mask = NULL;\r
-               fields[1].in_handler = NULL;\r
-               fields[1].in_handler_priv = NULL;\r
-               \r
-               arm_jtag_scann(&arm7_9->jtag_info, 0x1);\r
-               arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);\r
-\r
-               jtag_add_dr_scan(2, fields, TAP_PD);\r
-               jtag_execute_queue();\r
-               \r
-               fields[0].in_value = NULL;\r
-               fields[0].out_value = &breakpoint;\r
-               fields[1].in_value = NULL;\r
-               fields[1].out_value = databus;\r
-               \r
-               jtag_add_dr_scan(2, fields, TAP_PD);\r
-\r
-               if (breakpoint & 1)\r
-                       target->debug_reason = DBG_REASON_WATCHPOINT; \r
-               else\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT; \r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* put an instruction in the ARM7TDMI pipeline or write the data bus, and optionally read data */\r
-int arm7tdmi_clock_out(arm_jtag_t *jtag_info, u32 out, u32 *in, int breakpoint)\r
-{\r
-       scan_field_t fields[2];\r
-       u8 out_buf[4];\r
-       u8 breakpoint_buf;\r
-       \r
-       buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));\r
-       buf_set_u32(&breakpoint_buf, 0, 1, breakpoint);\r
-\r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0x1);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = &breakpoint_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-               \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = out_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       if (in)\r
-       {\r
-               fields[1].in_handler = arm_jtag_buf_to_u32_flip;\r
-               fields[1].in_handler_priv = in;\r
-       }\r
-       else\r
-       {\r
-               fields[1].in_handler = NULL;\r
-               fields[1].in_handler_priv = NULL;\r
-       }\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       jtag_add_runtest(0, -1);\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-{\r
-               jtag_execute_queue();\r
-               \r
-               if (in)\r
-               {\r
-                       DEBUG("out: 0x%8.8x, in: 0x%8.8x", out, *in);\r
-               }\r
-               else\r
-                       DEBUG("out: 0x%8.8x", out);\r
-}\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* clock the target, reading the databus */\r
-int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)\r
-{\r
-       scan_field_t fields[2];\r
-\r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0x1);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-               \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = arm_jtag_buf_to_u32_flip;\r
-       fields[1].in_handler_priv = in;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       jtag_add_runtest(0, -1);\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-{\r
-               jtag_execute_queue();\r
-                       \r
-               if (in)\r
-               {\r
-                       DEBUG("in: 0x%8.8x", *in);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: called with in == NULL");\r
-               }\r
-}\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* clock the target, and read the databus\r
- * the *in pointer points to a buffer where elements of 'size' bytes\r
- * are stored in big (be==1) or little (be==0) endianness\r
- */ \r
-int arm7tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)\r
-{\r
-       scan_field_t fields[2];\r
-\r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0x1);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-               \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       switch (size)\r
-       {\r
-               case 4:\r
-                       fields[1].in_handler = (be) ? arm_jtag_buf_to_be32_flip : arm_jtag_buf_to_le32_flip;\r
-                       break;\r
-               case 2:\r
-                       fields[1].in_handler = (be) ? arm_jtag_buf_to_be16_flip : arm_jtag_buf_to_le16_flip;\r
-                       break;\r
-               case 1:\r
-                       fields[1].in_handler = arm_jtag_buf_to_8_flip;\r
-                       break;\r
-       }\r
-       fields[1].in_handler_priv = in;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       jtag_add_runtest(0, -1);\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-{\r
-               jtag_execute_queue();\r
-                       \r
-               if (in)\r
-               {\r
-                       DEBUG("in: 0x%8.8x", *in);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: called with in == NULL");\r
-               }\r
-}\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void arm7tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* save r0 before using it and put system in ARM state \r
-        * to allow common handling of ARM and THUMB debugging */\r
-       \r
-       /* fetch STR r0, [r0] */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       /* nothing fetched, STR r0, [r0] in Execute (2) */\r
-       arm7tdmi_clock_data_in(jtag_info, r0);\r
-\r
-       /* MOV r0, r15 fetched, STR in Decode */        \r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       /* nothing fetched, STR r0, [r0] in Execute (2) */\r
-       arm7tdmi_clock_data_in(jtag_info, pc);\r
-\r
-       /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       /* nothing fetched, data for LDR r0, [PC, #0] */\r
-       arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);\r
-       /* nothing fetched, data from previous cycle is written to register */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       \r
-       /* fetch BX */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);\r
-       /* NOP fetched, BX in Decode, MOV in Execute */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       /* NOP fetched, BX in Execute (1) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       \r
-       jtag_execute_queue();\r
-       \r
-       /* fix program counter:\r
-        * MOV r0, r15 was the 4th instruction (+6)\r
-        * reading PC in Thumb state gives address of instruction + 4\r
-        */\r
-       *pc -= 0xa;\r
-       \r
-}\r
-\r
-void arm7tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])\r
-{\r
-       int i;\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       /* STMIA r0-15, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);\r
-\r
-       /* fetch NOP, STM in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, STM in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-\r
-       for (i = 0; i <= 15; i++)\r
-       {\r
-               if (mask & (1 << i))\r
-                       /* nothing fetched, STM still in EXECUTE (1+i cycle) */\r
-                       arm7tdmi_clock_data_in(jtag_info, core_regs[i]);\r
-       }\r
-\r
-}\r
-\r
-void arm7tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)\r
-{\r
-       int i;\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;\r
-       u32 *buf_u32 = buffer;\r
-       u16 *buf_u16 = buffer;\r
-       u8 *buf_u8 = buffer;\r
-               \r
-       /* STMIA r0-15, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);\r
-\r
-       /* fetch NOP, STM in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, STM in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-\r
-       for (i = 0; i <= 15; i++)\r
-       {\r
-               /* nothing fetched, STM still in EXECUTE (1+i cycle), read databus */\r
-               if (mask & (1 << i))\r
-               {\r
-                       switch (size)\r
-                       {\r
-                               case 4:\r
-                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);\r
-                                       break;\r
-                               case 2:\r
-                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);\r
-                                       break;\r
-                               case 1:\r
-                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);\r
-                                       break;\r
-                       }\r
-               }\r
-       }\r
-       \r
-}\r
-\r
-void arm7tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       /* MRS r0, cpsr */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);\r
-       \r
-       /* STR r0, [r15] */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);\r
-       /* fetch NOP, STR in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, STR in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, STR still in EXECUTE (2nd cycle) */\r
-       arm7tdmi_clock_data_in(jtag_info, xpsr);\r
-\r
-}\r
-\r
-void arm7tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);\r
-\r
-       /* MSR1 fetched */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);\r
-       /* MSR2 fetched, MSR1 in DECODE */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);\r
-       /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);\r
-       /* nothing fetched, MSR1 in EXECUTE (2) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);\r
-       /* nothing fetched, MSR2 in EXECUTE (2) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, MSR3 in EXECUTE (2) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* NOP fetched, MSR4 in EXECUTE (1) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, MSR4 in EXECUTE (2) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-}\r
-\r
-void arm7tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);\r
-       \r
-       /* MSR fetched */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);\r
-       /* NOP fetched, MSR in DECODE */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* NOP fetched, MSR in EXECUTE (1) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, MSR in EXECUTE (2) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       \r
-}\r
-\r
-void arm7tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])\r
-{\r
-       int i;\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       /* LDMIA r0-15, [r0] at debug speed\r
-       * register values will start to appear on 4th DCLK\r
-       */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);\r
-\r
-       /* fetch NOP, LDM in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-\r
-       for (i = 0; i <= 15; i++)\r
-       {\r
-               if (mask & (1 << i))\r
-                       /* nothing fetched, LDM still in EXECUTE (1+i cycle) */\r
-                       arm7tdmi_clock_out(jtag_info, core_regs[i], NULL, 0);\r
-       }\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       \r
-}\r
-\r
-void arm7tdmi_load_word_regs(target_t *target, u32 mask)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed load-multiple into the pipeline */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);\r
-\r
-}\r
-\r
-void arm7tdmi_load_hword_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* put system-speed load half-word into the pipeline */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);\r
-\r
-}\r
-\r
-void arm7tdmi_load_byte_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed load byte into the pipeline */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);\r
-\r
-}\r
-\r
-void arm7tdmi_store_word_regs(target_t *target, u32 mask)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed store-multiple into the pipeline */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);\r
-       \r
-}\r
-\r
-void arm7tdmi_store_hword_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed store half-word into the pipeline */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);\r
-\r
-}\r
-\r
-void arm7tdmi_store_byte_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed store byte into the pipeline */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);\r
-\r
-}\r
-\r
-void arm7tdmi_write_pc(target_t *target, u32 pc)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* LDMIA r0-15, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);\r
-       /* fetch NOP, LDM in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */\r
-       arm7tdmi_clock_out(jtag_info, pc, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (4th cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (5th cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-}\r
-\r
-void arm7tdmi_branch_resume(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffa, 0), NULL, 0);\r
-\r
-}\r
-\r
-void arm7tdmi_branch_resume_thumb(target_t *target)\r
-{\r
-       DEBUG("-");\r
-       \r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
-\r
-       /* LDMIA r0, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);\r
-\r
-       /* fetch NOP, LDM in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */\r
-       arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-\r
-       /* Branch and eXchange */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);\r
-       \r
-       embeddedice_read_reg(dbg_stat);\r
-       \r
-       /* fetch NOP, BX in DECODE stage */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-       \r
-       /* target is now in Thumb state */\r
-       embeddedice_read_reg(dbg_stat);\r
-       \r
-       /* fetch NOP, BX in EXECUTE stage (1st cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);\r
-\r
-       /* target is now in Thumb state */\r
-       embeddedice_read_reg(dbg_stat);\r
-\r
-       /* load r0 value */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);\r
-       /* fetch NOP, LDR in Decode */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       /* fetch NOP, LDR in Execute */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */\r
-       arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);\r
-       /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       \r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);\r
-\r
-       embeddedice_read_reg(dbg_stat);\r
-       \r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);\r
-       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);\r
-\r
-}\r
-               \r
-void arm7tdmi_build_reg_cache(target_t *target)\r
-{\r
-       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);\r
-       armv4_5->core_cache = (*cache_p);\r
-       \r
-       (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);\r
-       arm7_9->eice_cache = (*cache_p)->next;\r
-       \r
-       if (arm7_9->etm_ctx)\r
-       {\r
-               (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);\r
-               arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;\r
-       }\r
-}\r
-\r
-int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       \r
-       arm7tdmi_build_reg_cache(target);\r
-       \r
-       return ERROR_OK;\r
-       \r
-}\r
-\r
-int arm7tdmi_quit()\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int chain_pos, char *variant)\r
-{\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       \r
-       arm7_9 = &arm7tdmi->arm7_9_common;\r
-       armv4_5 = &arm7_9->armv4_5_common;\r
-       \r
-       /* prepare JTAG information for the new target */\r
-       arm7_9->jtag_info.chain_pos = chain_pos;\r
-       arm7_9->jtag_info.scann_size = 4;\r
-       \r
-       /* register arch-specific functions */\r
-       arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;\r
-       arm7_9->change_to_arm = arm7tdmi_change_to_arm;\r
-       arm7_9->read_core_regs = arm7tdmi_read_core_regs;\r
-       arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;\r
-       arm7_9->read_xpsr = arm7tdmi_read_xpsr;\r
-       \r
-       arm7_9->write_xpsr = arm7tdmi_write_xpsr;\r
-       arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;\r
-       arm7_9->write_core_regs = arm7tdmi_write_core_regs;\r
-       \r
-       arm7_9->load_word_regs = arm7tdmi_load_word_regs;\r
-       arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;\r
-       arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;\r
-       \r
-       arm7_9->store_word_regs = arm7tdmi_store_word_regs;\r
-       arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;\r
-       arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;\r
-       \r
-       arm7_9->write_pc = arm7tdmi_write_pc;\r
-       arm7_9->branch_resume = arm7tdmi_branch_resume;\r
-       arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;\r
-       \r
-       arm7_9->enable_single_step = arm7_9_enable_eice_step;\r
-       arm7_9->disable_single_step = arm7_9_disable_eice_step;\r
-               \r
-       arm7_9->pre_debug_entry = NULL;\r
-       arm7_9->post_debug_entry = NULL;\r
-       \r
-       arm7_9->pre_restore_context = NULL;\r
-       arm7_9->post_restore_context = NULL;\r
-       \r
-       /* initialize arch-specific breakpoint handling */\r
-       arm7_9->arm_bkpt = 0xdeeedeee;\r
-       arm7_9->thumb_bkpt = 0xdeee;\r
-       \r
-       arm7_9->sw_bkpts_use_wp = 1;\r
-       arm7_9->sw_bkpts_enabled = 0;\r
-       arm7_9->dbgreq_adjust_pc = 2;\r
-       arm7_9->arch_info = arm7tdmi;\r
-\r
-       arm7tdmi->arch_info = NULL;\r
-       arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;\r
-       \r
-       if (variant)\r
-       {\r
-               arm7tdmi->variant = strdup(variant);\r
-       }\r
-       else\r
-       {\r
-               arm7tdmi->variant = strdup("");\r
-       }\r
-       \r
-       arm7_9_init_arch_info(target, arm7_9);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* target arm7tdmi <endianess> <startup_mode> <chain_pos> <variant> */\r
-int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       arm7tdmi_common_t *arm7tdmi = malloc(sizeof(arm7tdmi_common_t));\r
-\r
-       if (argc < 4)\r
-       {\r
-               ERROR("'target arm7tdmi' requires at least one additional argument");\r
-               exit(-1);\r
-       }\r
-       \r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-       \r
-       if (argc >= 5)\r
-               variant = args[4];\r
-       \r
-       arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm7tdmi_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       \r
-       retval = arm7_9_register_commands(cmd_ctx);\r
-       \r
-       return ERROR_OK;\r
-\r
-}\r
-\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm7tdmi.h"
+
+#include "arm7_9_common.h"
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "embeddedice.h"
+#include "etm.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm7tdmi_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm7tdmi_quit();
+
+/* target function declarations */
+int arm7tdmi_poll(struct target_s *target);
+int arm7tdmi_halt(target_t *target);
+               
+target_type_t arm7tdmi_target =
+{
+       .name = "arm7tdmi",
+
+       .poll = arm7_9_poll,
+       .arch_state = armv4_5_arch_state,
+
+       .target_request_data = arm7_9_target_request_data,
+
+       .halt = arm7_9_halt,
+       .resume = arm7_9_resume,
+       .step = arm7_9_step,
+
+       .assert_reset = arm7_9_assert_reset,
+       .deassert_reset = arm7_9_deassert_reset,
+       .soft_reset_halt = arm7_9_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
+
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+       
+       .read_memory = arm7_9_read_memory,
+       .write_memory = arm7_9_write_memory,
+       .bulk_write_memory = arm7_9_bulk_write_memory,
+       .checksum_memory = arm7_9_checksum_memory,
+       
+       .run_algorithm = armv4_5_run_algorithm,
+       
+       .add_breakpoint = arm7_9_add_breakpoint,
+       .remove_breakpoint = arm7_9_remove_breakpoint,
+       .add_watchpoint = arm7_9_add_watchpoint,
+       .remove_watchpoint = arm7_9_remove_watchpoint,
+
+       .register_commands = arm7tdmi_register_commands,
+       .target_command = arm7tdmi_target_command,
+       .init_target = arm7tdmi_init_target,
+       .quit = arm7tdmi_quit
+};
+
+int arm7tdmi_examine_debug_reason(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       
+       /* only check the debug reason if we don't know it already */
+       if ((target->debug_reason != DBG_REASON_DBGRQ)
+                       && (target->debug_reason != DBG_REASON_SINGLESTEP))
+       {
+               scan_field_t fields[2];
+               u8 databus[4];
+               u8 breakpoint;
+               
+               jtag_add_end_state(TAP_PD);
+
+               fields[0].device = arm7_9->jtag_info.chain_pos;
+               fields[0].num_bits = 1;
+               fields[0].out_value = NULL;
+               fields[0].out_mask = NULL;
+               fields[0].in_value = &breakpoint;
+               fields[0].in_check_value = NULL;
+               fields[0].in_check_mask = NULL;
+               fields[0].in_handler = NULL;
+               fields[0].in_handler_priv = NULL;
+               
+               fields[1].device = arm7_9->jtag_info.chain_pos;
+               fields[1].num_bits = 32;
+               fields[1].out_value = NULL;
+               fields[1].out_mask = NULL;
+               fields[1].in_value = databus;
+               fields[1].in_check_value = NULL;
+               fields[1].in_check_mask = NULL;
+               fields[1].in_handler = NULL;
+               fields[1].in_handler_priv = NULL;
+               
+               arm_jtag_scann(&arm7_9->jtag_info, 0x1);
+               arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
+
+               jtag_add_dr_scan(2, fields, TAP_PD);
+               jtag_execute_queue();
+               
+               fields[0].in_value = NULL;
+               fields[0].out_value = &breakpoint;
+               fields[1].in_value = NULL;
+               fields[1].out_value = databus;
+               
+               jtag_add_dr_scan(2, fields, TAP_PD);
+
+               if (breakpoint & 1)
+                       target->debug_reason = DBG_REASON_WATCHPOINT; 
+               else
+                       target->debug_reason = DBG_REASON_BREAKPOINT; 
+       }
+
+       return ERROR_OK;
+}
+
+/* put an instruction in the ARM7TDMI pipeline or write the data bus, and optionally read data */
+int arm7tdmi_clock_out(arm_jtag_t *jtag_info, u32 out, u32 *in, int breakpoint)
+{
+       scan_field_t fields[2];
+       u8 out_buf[4];
+       u8 breakpoint_buf;
+       
+       buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
+       buf_set_u32(&breakpoint_buf, 0, 1, breakpoint);
+
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+       
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = &breakpoint_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+               
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = out_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       if (in)
+       {
+               fields[1].in_handler = arm_jtag_buf_to_u32_flip;
+               fields[1].in_handler_priv = in;
+       }
+       else
+       {
+               fields[1].in_handler = NULL;
+               fields[1].in_handler_priv = NULL;
+       }
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+               jtag_execute_queue();
+               
+               if (in)
+               {
+                       DEBUG("out: 0x%8.8x, in: 0x%8.8x", out, *in);
+               }
+               else
+                       DEBUG("out: 0x%8.8x", out);
+}
+#endif
+
+       return ERROR_OK;
+}
+
+/* clock the target, reading the databus */
+int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
+{
+       scan_field_t fields[2];
+
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+       
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+               
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = arm_jtag_buf_to_u32_flip;
+       fields[1].in_handler_priv = in;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+               jtag_execute_queue();
+                       
+               if (in)
+               {
+                       DEBUG("in: 0x%8.8x", *in);
+               }
+               else
+               {
+                       ERROR("BUG: called with in == NULL");
+               }
+}
+#endif
+
+       return ERROR_OK;
+}
+
+/* clock the target, and read the databus
+ * the *in pointer points to a buffer where elements of 'size' bytes
+ * are stored in big (be==1) or little (be==0) endianness
+ */ 
+int arm7tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
+{
+       scan_field_t fields[2];
+
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+       
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+               
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       switch (size)
+       {
+               case 4:
+                       fields[1].in_handler = (be) ? arm_jtag_buf_to_be32_flip : arm_jtag_buf_to_le32_flip;
+                       break;
+               case 2:
+                       fields[1].in_handler = (be) ? arm_jtag_buf_to_be16_flip : arm_jtag_buf_to_le16_flip;
+                       break;
+               case 1:
+                       fields[1].in_handler = arm_jtag_buf_to_8_flip;
+                       break;
+       }
+       fields[1].in_handler_priv = in;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+               jtag_execute_queue();
+                       
+               if (in)
+               {
+                       DEBUG("in: 0x%8.8x", *in);
+               }
+               else
+               {
+                       ERROR("BUG: called with in == NULL");
+               }
+}
+#endif
+
+       return ERROR_OK;
+}
+
+void arm7tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       /* save r0 before using it and put system in ARM state 
+        * to allow common handling of ARM and THUMB debugging */
+       
+       /* fetch STR r0, [r0] */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* nothing fetched, STR r0, [r0] in Execute (2) */
+       arm7tdmi_clock_data_in(jtag_info, r0);
+
+       /* MOV r0, r15 fetched, STR in Decode */        
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* nothing fetched, STR r0, [r0] in Execute (2) */
+       arm7tdmi_clock_data_in(jtag_info, pc);
+
+       /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* nothing fetched, data for LDR r0, [PC, #0] */
+       arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
+       /* nothing fetched, data from previous cycle is written to register */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       
+       /* fetch BX */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
+       /* NOP fetched, BX in Decode, MOV in Execute */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* NOP fetched, BX in Execute (1) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       
+       jtag_execute_queue();
+       
+       /* fix program counter:
+        * MOV r0, r15 was the 4th instruction (+6)
+        * reading PC in Thumb state gives address of instruction + 4
+        */
+       *pc -= 0xa;
+       
+}
+
+void arm7tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       /* STMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+       /* fetch NOP, STM in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, STM in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               if (mask & (1 << i))
+                       /* nothing fetched, STM still in EXECUTE (1+i cycle) */
+                       arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
+       }
+
+}
+
+void arm7tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
+       u32 *buf_u32 = buffer;
+       u16 *buf_u16 = buffer;
+       u8 *buf_u8 = buffer;
+               
+       /* STMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+       /* fetch NOP, STM in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, STM in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               /* nothing fetched, STM still in EXECUTE (1+i cycle), read databus */
+               if (mask & (1 << i))
+               {
+                       switch (size)
+                       {
+                               case 4:
+                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+                                       break;
+                               case 2:
+                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+                                       break;
+                               case 1:
+                                       arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+                                       break;
+                       }
+               }
+       }
+       
+}
+
+void arm7tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       /* MRS r0, cpsr */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);
+       
+       /* STR r0, [r15] */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);
+       /* fetch NOP, STR in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, STR in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, STR still in EXECUTE (2nd cycle) */
+       arm7tdmi_clock_data_in(jtag_info, xpsr);
+
+}
+
+void arm7tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
+
+       /* MSR1 fetched */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);
+       /* MSR2 fetched, MSR1 in DECODE */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);
+       /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);
+       /* nothing fetched, MSR1 in EXECUTE (2) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);
+       /* nothing fetched, MSR2 in EXECUTE (2) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, MSR3 in EXECUTE (2) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* NOP fetched, MSR4 in EXECUTE (1) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, MSR4 in EXECUTE (2) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+}
+
+void arm7tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
+       
+       /* MSR fetched */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);
+       /* NOP fetched, MSR in DECODE */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* NOP fetched, MSR in EXECUTE (1) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, MSR in EXECUTE (2) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       
+}
+
+void arm7tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       /* LDMIA r0-15, [r0] at debug speed
+       * register values will start to appear on 4th DCLK
+       */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+       /* fetch NOP, LDM in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               if (mask & (1 << i))
+                       /* nothing fetched, LDM still in EXECUTE (1+i cycle) */
+                       arm7tdmi_clock_out(jtag_info, core_regs[i], NULL, 0);
+       }
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       
+}
+
+void arm7tdmi_load_word_regs(target_t *target, u32 mask)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed load-multiple into the pipeline */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);
+
+}
+
+void arm7tdmi_load_hword_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       /* put system-speed load half-word into the pipeline */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_load_byte_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed load byte into the pipeline */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_store_word_regs(target_t *target, u32 mask)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed store-multiple into the pipeline */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);
+       
+}
+
+void arm7tdmi_store_hword_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed store half-word into the pipeline */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_store_byte_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed store byte into the pipeline */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_write_pc(target_t *target, u32 pc)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       /* LDMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);
+       /* fetch NOP, LDM in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */
+       arm7tdmi_clock_out(jtag_info, pc, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+}
+
+void arm7tdmi_branch_resume(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffa, 0), NULL, 0);
+
+}
+
+void arm7tdmi_branch_resume_thumb(target_t *target)
+{
+       DEBUG("-");
+       
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+
+       /* LDMIA r0, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);
+
+       /* fetch NOP, LDM in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
+       arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+       /* Branch and eXchange */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);
+       
+       embeddedice_read_reg(dbg_stat);
+       
+       /* fetch NOP, BX in DECODE stage */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+       
+       /* target is now in Thumb state */
+       embeddedice_read_reg(dbg_stat);
+       
+       /* fetch NOP, BX in EXECUTE stage (1st cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+       /* target is now in Thumb state */
+       embeddedice_read_reg(dbg_stat);
+
+       /* load r0 value */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
+       /* fetch NOP, LDR in Decode */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* fetch NOP, LDR in Execute */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
+       arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
+       /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+
+       embeddedice_read_reg(dbg_stat);
+       
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
+       arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
+
+}
+               
+void arm7tdmi_build_reg_cache(target_t *target)
+{
+       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+       armv4_5->core_cache = (*cache_p);
+       
+       (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
+       arm7_9->eice_cache = (*cache_p)->next;
+       
+       if (arm7_9->etm_ctx)
+       {
+               (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
+               arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
+       }
+}
+
+int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       
+       arm7tdmi_build_reg_cache(target);
+       
+       return ERROR_OK;
+       
+}
+
+int arm7tdmi_quit()
+{
+       
+       return ERROR_OK;
+}
+
+int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int chain_pos, char *variant)
+{
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       
+       arm7_9 = &arm7tdmi->arm7_9_common;
+       armv4_5 = &arm7_9->armv4_5_common;
+       
+       /* prepare JTAG information for the new target */
+       arm7_9->jtag_info.chain_pos = chain_pos;
+       arm7_9->jtag_info.scann_size = 4;
+       
+       /* register arch-specific functions */
+       arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
+       arm7_9->change_to_arm = arm7tdmi_change_to_arm;
+       arm7_9->read_core_regs = arm7tdmi_read_core_regs;
+       arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
+       arm7_9->read_xpsr = arm7tdmi_read_xpsr;
+       
+       arm7_9->write_xpsr = arm7tdmi_write_xpsr;
+       arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;
+       arm7_9->write_core_regs = arm7tdmi_write_core_regs;
+       
+       arm7_9->load_word_regs = arm7tdmi_load_word_regs;
+       arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;
+       arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;
+       
+       arm7_9->store_word_regs = arm7tdmi_store_word_regs;
+       arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;
+       arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;
+       
+       arm7_9->write_pc = arm7tdmi_write_pc;
+       arm7_9->branch_resume = arm7tdmi_branch_resume;
+       arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;
+       
+       arm7_9->enable_single_step = arm7_9_enable_eice_step;
+       arm7_9->disable_single_step = arm7_9_disable_eice_step;
+               
+       arm7_9->pre_debug_entry = NULL;
+       arm7_9->post_debug_entry = NULL;
+       
+       arm7_9->pre_restore_context = NULL;
+       arm7_9->post_restore_context = NULL;
+       
+       /* initialize arch-specific breakpoint handling */
+       arm7_9->arm_bkpt = 0xdeeedeee;
+       arm7_9->thumb_bkpt = 0xdeee;
+       
+       arm7_9->sw_bkpts_use_wp = 1;
+       arm7_9->sw_bkpts_enabled = 0;
+       arm7_9->dbgreq_adjust_pc = 2;
+       arm7_9->arch_info = arm7tdmi;
+
+       arm7tdmi->arch_info = NULL;
+       arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;
+       
+       if (variant)
+       {
+               arm7tdmi->variant = strdup(variant);
+       }
+       else
+       {
+               arm7tdmi->variant = strdup("");
+       }
+       
+       arm7_9_init_arch_info(target, arm7_9);
+
+       return ERROR_OK;
+}
+
+/* target arm7tdmi <endianess> <startup_mode> <chain_pos> <variant> */
+int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       arm7tdmi_common_t *arm7tdmi = malloc(sizeof(arm7tdmi_common_t));
+
+       if (argc < 4)
+       {
+               ERROR("'target arm7tdmi' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);
+       
+       return ERROR_OK;
+}
+
+int arm7tdmi_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       
+       retval = arm7_9_register_commands(cmd_ctx);
+       
+       return ERROR_OK;
+
+}
+
index 17c539736d2ae77040e74385c7b86c0ebea48c48..e9a109a5981e27156b995ab20360d0dfa61bb155 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm920t.h"\r
-#include "jtag.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-/* cli handling */\r
-int arm920t_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm920t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm920t_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm920t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm920t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int arm920t_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm920t_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-/* forward declarations */\r
-int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm920t_quit();\r
-int arm920t_arch_state(struct target_s *target);\r
-int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm920t_soft_reset_halt(struct target_s *target);\r
-\r
-#define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z))\r
-\r
-target_type_t arm920t_target =\r
-{\r
-       .name = "arm920t",\r
-\r
-       .poll = arm7_9_poll,\r
-       .arch_state = arm920t_arch_state,\r
-\r
-       .target_request_data = arm7_9_target_request_data,\r
-\r
-       .halt = arm7_9_halt,\r
-       .resume = arm7_9_resume,\r
-       .step = arm7_9_step,\r
-\r
-       .assert_reset = arm7_9_assert_reset,\r
-       .deassert_reset = arm7_9_deassert_reset,\r
-       .soft_reset_halt = arm920t_soft_reset_halt,\r
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
-       \r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-\r
-       .read_memory = arm920t_read_memory,\r
-       .write_memory = arm920t_write_memory,\r
-       .bulk_write_memory = arm7_9_bulk_write_memory,\r
-       .checksum_memory = arm7_9_checksum_memory,\r
-       \r
-       .run_algorithm = armv4_5_run_algorithm,\r
-\r
-       .add_breakpoint = arm7_9_add_breakpoint,\r
-       .remove_breakpoint = arm7_9_remove_breakpoint,\r
-       .add_watchpoint = arm7_9_add_watchpoint,\r
-       .remove_watchpoint = arm7_9_remove_watchpoint,\r
-\r
-       .register_commands = arm920t_register_commands,\r
-       .target_command = arm920t_target_command,\r
-       .init_target = arm920t_init_target,\r
-       .quit = arm920t_quit\r
-};\r
-\r
-int arm920t_read_cp15_physical(target_t *target, int reg_addr, u32 *value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       scan_field_t fields[4];\r
-       u8 access_type_buf = 1;\r
-       u8 reg_addr_buf = reg_addr & 0x3f;\r
-       u8 nr_w_buf = 0;\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = &access_type_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 6;\r
-       fields[2].out_value = &reg_addr_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       fields[3].device = jtag_info->chain_pos;\r
-       fields[3].num_bits = 1;\r
-       fields[3].out_value = &nr_w_buf;\r
-       fields[3].out_mask = NULL;\r
-       fields[3].in_value = NULL;\r
-       fields[3].in_check_value = NULL;\r
-       fields[3].in_check_mask = NULL;\r
-       fields[3].in_handler = NULL;\r
-       fields[3].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(4, fields, -1);\r
-\r
-       fields[1].in_handler_priv = value;\r
-       fields[1].in_handler = arm_jtag_buf_to_u32;\r
-\r
-       jtag_add_dr_scan(4, fields, -1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       jtag_execute_queue();\r
-       DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_write_cp15_physical(target_t *target, int reg_addr, u32 value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       scan_field_t fields[4];\r
-       u8 access_type_buf = 1;\r
-       u8 reg_addr_buf = reg_addr & 0x3f;\r
-       u8 nr_w_buf = 1;\r
-       u8 value_buf[4];\r
-       \r
-       buf_set_u32(value_buf, 0, 32, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = &access_type_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = value_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 6;\r
-       fields[2].out_value = &reg_addr_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       fields[3].device = jtag_info->chain_pos;\r
-       fields[3].num_bits = 1;\r
-       fields[3].out_value = &nr_w_buf;\r
-       fields[3].out_mask = NULL;\r
-       fields[3].in_value = NULL;\r
-       fields[3].in_check_value = NULL;\r
-       fields[3].in_check_mask = NULL;\r
-       fields[3].in_handler = NULL;\r
-       fields[3].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(4, fields, -1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_execute_cp15(target_t *target, u32 cp15_opcode, u32 arm_opcode)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       scan_field_t fields[4];\r
-       u8 access_type_buf = 0;         /* interpreted access */\r
-       u8 reg_addr_buf = 0x0;\r
-       u8 nr_w_buf = 0;\r
-       u8 cp15_opcode_buf[4];\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-       \r
-       buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 1;\r
-       fields[0].out_value = &access_type_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = cp15_opcode_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 6;\r
-       fields[2].out_value = &reg_addr_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       fields[3].device = jtag_info->chain_pos;\r
-       fields[3].num_bits = 1;\r
-       fields[3].out_value = &nr_w_buf;\r
-       fields[3].out_mask = NULL;\r
-       fields[3].in_value = NULL;\r
-       fields[3].in_check_value = NULL;\r
-       fields[3].in_check_mask = NULL;\r
-       fields[3].in_handler = NULL;\r
-       fields[3].in_handler_priv = NULL;\r
-\r
-       jtag_add_dr_scan(4, fields, -1);\r
-\r
-       arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-       arm7_9_execute_sys_speed(target);\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("failed executing JTAG queue, exiting");\r
-               exit(-1);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_read_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 address, u32 *value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       u32* regs_p[1];\r
-       u32 regs[2];\r
-       u32 cp15c15 = 0x0;\r
-\r
-       /* load address into R1 */\r
-       regs[1] = address;\r
-       arm9tdmi_write_core_regs(target, 0x2, regs); \r
-       \r
-       /* read-modify-write CP15 test state register \r
-       * to enable interpreted access mode */\r
-       arm920t_read_cp15_physical(target, 0x1e, &cp15c15);     \r
-       jtag_execute_queue();\r
-       cp15c15 |= 1;   /* set interpret mode */\r
-       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-       /* execute CP15 instruction and ARM load (reading from coprocessor) */\r
-       arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1));\r
-       \r
-       /* disable interpreted access mode */\r
-       cp15c15 &= ~1U; /* clear interpret mode */\r
-       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-       /* retrieve value from R0 */\r
-       regs_p[0] = value;\r
-       arm9tdmi_read_core_regs(target, 0x1, regs_p);\r
-       jtag_execute_queue();\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x", cp15_opcode, address, *value);\r
-#endif\r
-\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_write_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 value, u32 address)\r
-{\r
-       u32 cp15c15 = 0x0;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       u32 regs[2];\r
-\r
-       /* load value, address into R0, R1 */\r
-       regs[0] = value;\r
-       regs[1] = address;\r
-       arm9tdmi_write_core_regs(target, 0x3, regs);\r
-\r
-       /* read-modify-write CP15 test state register \r
-       * to enable interpreted access mode */\r
-       arm920t_read_cp15_physical(target, 0x1e, &cp15c15);\r
-       jtag_execute_queue();\r
-       cp15c15 |= 1;   /* set interpret mode */\r
-       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-       /* execute CP15 instruction and ARM store (writing to coprocessor) */\r
-       arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1));\r
-\r
-       /* disable interpreted access mode */\r
-       cp15c15 &= ~1U; /* set interpret mode */\r
-       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x", cp15_opcode, value, address);\r
-#endif\r
-\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-u32 arm920t_get_ttb(target_t *target)\r
-{\r
-       int retval;\r
-       u32 ttb = 0x0;\r
-\r
-       if ((retval = arm920t_read_cp15_interpreted(target, 0xeebf0f51, 0x0, &ttb)) != ERROR_OK)\r
-               return retval;\r
-\r
-       return ttb;\r
-}\r
-\r
-void arm920t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       arm920t_read_cp15_physical(target, 0x2, &cp15_control);\r
-       jtag_execute_queue();\r
-               \r
-       if (mmu)\r
-               cp15_control &= ~0x1U;\r
-       \r
-       if (d_u_cache)\r
-               cp15_control &= ~0x4U;\r
-       \r
-       if (i_cache)\r
-               cp15_control &= ~0x1000U;\r
-\r
-       arm920t_write_cp15_physical(target, 0x2, cp15_control);\r
-}\r
-\r
-void arm920t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       arm920t_read_cp15_physical(target, 0x2, &cp15_control);\r
-       jtag_execute_queue();\r
-               \r
-       if (mmu)\r
-               cp15_control |= 0x1U;\r
-       \r
-       if (d_u_cache)\r
-               cp15_control |= 0x4U;\r
-       \r
-       if (i_cache)\r
-               cp15_control |= 0x1000U;\r
-       \r
-       arm920t_write_cp15_physical(target, 0x2, cp15_control);\r
-}\r
-\r
-void arm920t_post_debug_entry(target_t *target)\r
-{\r
-       u32 cp15c15;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm920t_common_t *arm920t = arm9tdmi->arch_info;\r
-       \r
-       /* examine cp15 control reg */\r
-       arm920t_read_cp15_physical(target, 0x2, &arm920t->cp15_control_reg);\r
-       jtag_execute_queue();\r
-       DEBUG("cp15_control_reg: %8.8x", arm920t->cp15_control_reg);\r
-\r
-       if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)\r
-       {\r
-               u32 cache_type_reg;\r
-               /* identify caches */\r
-               arm920t_read_cp15_physical(target, 0x1, &cache_type_reg);\r
-               jtag_execute_queue();\r
-               armv4_5_identify_cache(cache_type_reg, &arm920t->armv4_5_mmu.armv4_5_cache);\r
-       }\r
-\r
-       arm920t->armv4_5_mmu.mmu_enabled = (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;\r
-       arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;\r
-       arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;\r
-\r
-       /* save i/d fault status and address register */\r
-       arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);\r
-       arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);\r
-       arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);\r
-       arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);\r
-       \r
-       DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x, I FAR: 0x%8.8x",\r
-               arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);  \r
-\r
-       if (arm920t->preserve_cache)\r
-       {\r
-               /* read-modify-write CP15 test state register \r
-                * to disable I/D-cache linefills */\r
-               arm920t_read_cp15_physical(target, 0x1e, &cp15c15);\r
-               jtag_execute_queue();\r
-               cp15c15 |= 0x600;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-       }\r
-}\r
-\r
-void arm920t_pre_restore_context(target_t *target)\r
-{\r
-       u32 cp15c15;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm920t_common_t *arm920t = arm9tdmi->arch_info;\r
-       \r
-       /* restore i/d fault status and address register */\r
-       arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);\r
-       arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);\r
-       arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);\r
-       arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);\r
-       \r
-       /* read-modify-write CP15 test state register \r
-       * to reenable I/D-cache linefills */\r
-       if (arm920t->preserve_cache)\r
-       {\r
-               arm920t_read_cp15_physical(target, 0x1e, &cp15c15);\r
-               jtag_execute_queue();\r
-               cp15c15 &= ~0x600U;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-       }\r
-}\r
-\r
-int arm920t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm920t_common_t **arm920t_p)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm7_9 = armv4_5->arch_info;\r
-       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm9tdmi = arm7_9->arch_info;\r
-       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm920t = arm9tdmi->arch_info;\r
-       if (arm920t->common_magic != ARM920T_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       *armv4_5_p = armv4_5;\r
-       *arm7_9_p = arm7_9;\r
-       *arm9tdmi_p = arm9tdmi;\r
-       *arm920t_p = arm920t;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_arch_state(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm920t_common_t *arm920t = arm9tdmi->arch_info;\r
-       \r
-       char *state[] = \r
-       {\r
-               "disabled", "enabled"\r
-       };\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               ERROR("BUG: called for a non-ARMv4/5 target");\r
-               exit(-1);\r
-       }\r
-       \r
-       USER(   "target halted in %s state due to %s, current mode: %s\n"\r
-                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"\r
-                       "MMU: %s, D-Cache: %s, I-Cache: %s",\r
-                        armv4_5_state_strings[armv4_5->core_state],\r
-                        target_debug_reason_strings[target->debug_reason],\r
-                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),\r
-                        state[arm920t->armv4_5_mmu.mmu_enabled],\r
-                        state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], \r
-                        state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       int retval;\r
-       \r
-       retval = arm7_9_read_memory(target, address, size, count, buffer);\r
-       \r
-       return retval;\r
-}\r
-\r
-int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       int retval;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm920t_common_t *arm920t = arm9tdmi->arch_info;\r
-       \r
-       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)\r
-               return retval;\r
-\r
-       if (((size == 4) || (size == 2)) && (count == 1))\r
-       {\r
-               if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)\r
-               {\r
-                       DEBUG("D-Cache enabled, writing through to main memory");\r
-                       u32 pa, cb, ap;\r
-                       int type, domain;\r
-\r
-                       pa = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &type, &cb, &domain, &ap);\r
-                       if (type == -1)\r
-                               return ERROR_OK;\r
-                       /* cacheable & bufferable means write-back region */\r
-                       if (cb == 3)\r
-                               armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer);\r
-               }\r
-               \r
-               if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)\r
-               {\r
-                       DEBUG("I-Cache enabled, invalidating affected I-Cache line");\r
-                       arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address);\r
-               }\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int arm920t_soft_reset_halt(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm920t_common_t *arm920t = arm9tdmi->arch_info;\r
-       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
-       \r
-       if (target->state == TARGET_RUNNING)\r
-       {\r
-               target->type->halt(target);\r
-       }\r
-       \r
-       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)\r
-       {\r
-               embeddedice_read_reg(dbg_stat);\r
-               jtag_execute_queue();\r
-       }\r
-       \r
-       target->state = TARGET_HALTED;\r
-       \r
-       /* SVC, ARM state, IRQ and FIQ disabled */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;\r
-       \r
-       /* start fetching from 0x0 */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);\r
-       armv4_5->core_cache->reg_list[15].dirty = 1;\r
-       armv4_5->core_cache->reg_list[15].valid = 1;\r
-       \r
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;\r
-       armv4_5->core_state = ARMV4_5_STATE_ARM;\r
-       \r
-       arm920t_disable_mmu_caches(target, 1, 1, 1);\r
-       arm920t->armv4_5_mmu.mmu_enabled = 0;\r
-       arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;\r
-       arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;\r
-\r
-       target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       arm9tdmi_init_target(cmd_ctx, target);\r
-               \r
-       return ERROR_OK;\r
-       \r
-}\r
-\r
-int arm920t_quit()\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_init_arch_info(target_t *target, arm920t_common_t *arm920t, int chain_pos, char *variant)\r
-{\r
-       arm9tdmi_common_t *arm9tdmi = &arm920t->arm9tdmi_common;\r
-       arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;\r
-       \r
-       /* initialize arm9tdmi specific info (including arm7_9 and armv4_5)\r
-        */\r
-       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);\r
-\r
-       arm9tdmi->arch_info = arm920t;\r
-       arm920t->common_magic = ARM920T_COMMON_MAGIC;\r
-       \r
-       arm7_9->post_debug_entry = arm920t_post_debug_entry;\r
-       arm7_9->pre_restore_context = arm920t_pre_restore_context;\r
-       \r
-       arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;\r
-       arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;\r
-       arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;\r
-       arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;\r
-       arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;\r
-       arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;\r
-       arm920t->armv4_5_mmu.has_tiny_pages = 1;\r
-       arm920t->armv4_5_mmu.mmu_enabled = 0;\r
-       \r
-       /* disabling linefills leads to lockups, so keep them enabled for now\r
-        * this doesn't affect correctness, but might affect timing issues, if\r
-        * important data is evicted from the cache during the debug session\r
-        * */\r
-       arm920t->preserve_cache = 0;\r
-       \r
-       /* override hw single-step capability from ARM9TDMI */\r
-       arm7_9->has_single_step = 1;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       arm920t_common_t *arm920t = malloc(sizeof(arm920t_common_t));\r
-       \r
-       if (argc < 4)\r
-       {\r
-               ERROR("'target arm920t' requires at least one additional argument");\r
-               exit(-1);\r
-       }\r
-       \r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-       \r
-       if (argc >= 5)\r
-               variant = args[4];\r
-       \r
-       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);\r
-       \r
-       arm920t_init_arch_info(target, arm920t, chain_pos, variant);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       command_t *arm920t_cmd;\r
-       \r
-               \r
-       retval = arm9tdmi_register_commands(cmd_ctx);\r
-       \r
-       arm920t_cmd = register_command(cmd_ctx, NULL, "arm920t", NULL, COMMAND_ANY, "arm920t specific commands");\r
-\r
-       register_command(cmd_ctx, arm920t_cmd, "cp15", arm920t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");\r
-       register_command(cmd_ctx, arm920t_cmd, "cp15i", arm920t_handle_cp15i_command, COMMAND_EXEC, "display/modify cp15 (interpreted access) <opcode> [value] [address]");\r
-       register_command(cmd_ctx, arm920t_cmd, "cache_info", arm920t_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");\r
-       register_command(cmd_ctx, arm920t_cmd, "virt2phys", arm920t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");\r
-\r
-       register_command(cmd_ctx, arm920t_cmd, "mdw_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");\r
-       register_command(cmd_ctx, arm920t_cmd, "mdh_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");\r
-       register_command(cmd_ctx, arm920t_cmd, "mdb_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");\r
-\r
-       register_command(cmd_ctx, arm920t_cmd, "mww_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");\r
-       register_command(cmd_ctx, arm920t_cmd, "mwh_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");\r
-       register_command(cmd_ctx, arm920t_cmd, "mwb_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");\r
-\r
-       register_command(cmd_ctx, arm920t_cmd, "read_cache", arm920t_handle_read_cache_command, COMMAND_EXEC, "display I/D cache content");\r
-       register_command(cmd_ctx, arm920t_cmd, "read_mmu", arm920t_handle_read_mmu_command, COMMAND_EXEC, "display I/D mmu content");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-       u32 cp15c15;\r
-       u32 cp15_ctrl, cp15_ctrl_saved;\r
-       u32 regs[16];\r
-       u32 *regs_p[16];\r
-       u32 C15_C_D_Ind, C15_C_I_Ind;\r
-       int i;\r
-       FILE *output;\r
-       arm920t_cache_line_t d_cache[8][64], i_cache[8][64];\r
-       int segment, index;\r
-       \r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: arm920t read_cache <filename>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if ((output = fopen(args[0], "w")) == NULL)\r
-       {\r
-               DEBUG("error opening cache content file");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       for (i = 0; i < 16; i++)\r
-               regs_p[i] = &regs[i];\r
-               \r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* disable MMU and Caches */\r
-       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);\r
-       jtag_execute_queue();\r
-       cp15_ctrl_saved = cp15_ctrl;\r
-       cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);\r
-       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);\r
-\r
-       /* read CP15 test state register */ \r
-       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);\r
-       jtag_execute_queue();\r
-       \r
-       /* read DCache content */\r
-       fprintf(output, "DCache:\n");\r
-       \r
-       /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ \r
-       for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)\r
-       {\r
-               fprintf(output, "\nsegment: %i\n----------", segment);\r
-               \r
-               /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */\r
-               regs[0] = 0x0 | (segment << 5);\r
-               arm9tdmi_write_core_regs(target, 0x1, regs);\r
-               \r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-               \r
-               /* D CAM Read, loads current victim into C15.C.D.Ind */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(1, 0));\r
-       \r
-               /* read current victim */\r
-               arm920t_read_cp15_physical(target, 0x3d, &C15_C_D_Ind);\r
-\r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-               for (index = 0; index < 64; index++)\r
-               {\r
-                       /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */\r
-                       regs[0] = 0x0 | (segment << 5) | (index << 26);\r
-                       arm9tdmi_write_core_regs(target, 0x1, regs);\r
-\r
-                       /* set interpret mode */\r
-                       cp15c15 |= 0x1;\r
-                       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-       \r
-                       /* Write DCache victim */\r
-                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));\r
-       \r
-                       /* Read D RAM */\r
-                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,10,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));\r
-                       \r
-                       /* Read D CAM */\r
-                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(9, 0));\r
-                       \r
-                       /* clear interpret mode */\r
-                       cp15c15 &= ~0x1;\r
-                       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-                       /* read D RAM and CAM content */\r
-                       arm9tdmi_read_core_regs(target, 0x3fe, regs_p);\r
-                       jtag_execute_queue();\r
-\r
-                       d_cache[segment][index].cam = regs[9];\r
-                       \r
-                       /* mask LFSR[6] */\r
-                       regs[9] &= 0xfffffffe;\r
-                       fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");\r
-                       \r
-                       for (i = 1; i < 9; i++)\r
-                       {\r
-                                d_cache[segment][index].data[i] = regs[i];\r
-                                fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);\r
-                       }\r
-       \r
-               }\r
-               \r
-               /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */\r
-               regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);\r
-               arm9tdmi_write_core_regs(target, 0x1, regs);\r
-\r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-       \r
-               /* Write DCache victim */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));\r
-       \r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-       }\r
-\r
-       /* read ICache content */\r
-       fprintf(output, "ICache:\n");\r
-       \r
-       /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ \r
-       for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)\r
-       {\r
-               fprintf(output, "segment: %i\n----------", segment);\r
-               \r
-               /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */\r
-               regs[0] = 0x0 | (segment << 5);\r
-               arm9tdmi_write_core_regs(target, 0x1, regs);\r
-               \r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-               \r
-               /* I CAM Read, loads current victim into C15.C.I.Ind */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(1, 0));\r
-       \r
-               /* read current victim */\r
-               arm920t_read_cp15_physical(target, 0x3b, &C15_C_I_Ind);\r
-\r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-               for (index = 0; index < 64; index++)\r
-               {\r
-                       /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */\r
-                       regs[0] = 0x0 | (segment << 5) | (index << 26);\r
-                       arm9tdmi_write_core_regs(target, 0x1, regs);\r
-\r
-                       /* set interpret mode */\r
-                       cp15c15 |= 0x1;\r
-                       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-       \r
-                       /* Write ICache victim */\r
-                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));\r
-       \r
-                       /* Read I RAM */\r
-                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,9,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));\r
-                       \r
-                       /* Read I CAM */\r
-                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(9, 0));\r
-                       \r
-                       /* clear interpret mode */\r
-                       cp15c15 &= ~0x1;\r
-                       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-\r
-                       /* read I RAM and CAM content */\r
-                       arm9tdmi_read_core_regs(target, 0x3fe, regs_p);\r
-                       jtag_execute_queue();\r
-\r
-                       i_cache[segment][index].cam = regs[9];\r
-                       \r
-                       /* mask LFSR[6] */\r
-                       regs[9] &= 0xfffffffe;\r
-                       fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");\r
-                       \r
-                       for (i = 1; i < 9; i++)\r
-                       {\r
-                                i_cache[segment][index].data[i] = regs[i];\r
-                                fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);\r
-                       }\r
-       \r
-               }\r
-               \r
-       \r
-               /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */\r
-               regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);\r
-               arm9tdmi_write_core_regs(target, 0x1, regs);\r
-\r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-       \r
-               /* Write ICache victim */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));\r
-       \r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-       }\r
-       \r
-       /* restore CP15 MMU and Cache settings */\r
-       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);\r
-       \r
-       command_print(cmd_ctx, "cache content successfully output to %s", args[0]);\r
-       \r
-       fclose(output);\r
-       \r
-       /* mark registers dirty. */\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-       u32 cp15c15;\r
-       u32 cp15_ctrl, cp15_ctrl_saved;\r
-       u32 regs[16];\r
-       u32 *regs_p[16];\r
-       int i;\r
-       FILE *output;\r
-       u32 Dlockdown, Ilockdown;\r
-       arm920t_tlb_entry_t d_tlb[64], i_tlb[64];\r
-       int victim;\r
-       \r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: arm920t read_mmu <filename>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if ((output = fopen(args[0], "w")) == NULL)\r
-       {\r
-               DEBUG("error opening mmu content file");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       for (i = 0; i < 16; i++)\r
-               regs_p[i] = &regs[i];\r
-               \r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* disable MMU and Caches */\r
-       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);\r
-       jtag_execute_queue();\r
-       cp15_ctrl_saved = cp15_ctrl;\r
-       cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);\r
-       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);\r
-\r
-       /* read CP15 test state register */ \r
-       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);\r
-       jtag_execute_queue();\r
-\r
-       /* prepare reading D TLB content \r
-        * */\r
-       \r
-       /* set interpret mode */\r
-       cp15c15 |= 0x1;\r
-       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-       \r
-       /* Read D TLB lockdown */\r
-       arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,0), ARMV4_5_LDR(1, 0));\r
-       \r
-       /* clear interpret mode */\r
-       cp15c15 &= ~0x1;\r
-       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-       \r
-       /* read D TLB lockdown stored to r1 */\r
-       arm9tdmi_read_core_regs(target, 0x2, regs_p);\r
-       jtag_execute_queue();\r
-       Dlockdown = regs[1];\r
-       \r
-       for (victim = 0; victim < 64; victim += 8)\r
-       {\r
-               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] \r
-                * base remains unchanged, victim goes through entries 0 to 63 */\r
-               regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);\r
-               arm9tdmi_write_core_regs(target, 0x2, regs);\r
-               \r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-               \r
-               /* Write D TLB lockdown */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));\r
-       \r
-               /* Read D TLB CAM */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,6,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));\r
-               \r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-               \r
-               /* read D TLB CAM content stored to r2-r9 */\r
-               arm9tdmi_read_core_regs(target, 0x3fc, regs_p);\r
-               jtag_execute_queue();\r
-               \r
-               for (i = 0; i < 8; i++)\r
-                       d_tlb[victim + i].cam = regs[i + 2]; \r
-       }\r
-\r
-       for (victim = 0; victim < 64; victim++)\r
-       {\r
-               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] \r
-                * base remains unchanged, victim goes through entries 0 to 63 */\r
-               regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);\r
-               arm9tdmi_write_core_regs(target, 0x2, regs);\r
-               \r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-               \r
-               /* Write D TLB lockdown */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));\r
-       \r
-               /* Read D TLB RAM1 */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,10,4), ARMV4_5_LDR(2,0));\r
-\r
-               /* Read D TLB RAM2 */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,2,5), ARMV4_5_LDR(3,0));\r
-               \r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-               \r
-               /* read D TLB RAM content stored to r2 and r3 */\r
-               arm9tdmi_read_core_regs(target, 0xc, regs_p);\r
-               jtag_execute_queue();\r
-\r
-               d_tlb[victim].ram1 = regs[2]; \r
-               d_tlb[victim].ram2 = regs[3]; \r
-       }\r
-               \r
-       /* restore D TLB lockdown */\r
-       regs[1] = Dlockdown;\r
-       arm9tdmi_write_core_regs(target, 0x2, regs);\r
-       \r
-       /* Write D TLB lockdown */\r
-       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));\r
-\r
-       /* prepare reading I TLB content \r
-        * */\r
-       \r
-       /* set interpret mode */\r
-       cp15c15 |= 0x1;\r
-       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-       \r
-       /* Read I TLB lockdown */\r
-       arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,1), ARMV4_5_LDR(1, 0));\r
-       \r
-       /* clear interpret mode */\r
-       cp15c15 &= ~0x1;\r
-       arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-       \r
-       /* read I TLB lockdown stored to r1 */\r
-       arm9tdmi_read_core_regs(target, 0x2, regs_p);\r
-       jtag_execute_queue();\r
-       Ilockdown = regs[1];\r
-       \r
-       for (victim = 0; victim < 64; victim += 8)\r
-       {\r
-               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] \r
-                * base remains unchanged, victim goes through entries 0 to 63 */\r
-               regs[1] = (Ilockdown & 0xfc000000) | (victim << 20);\r
-               arm9tdmi_write_core_regs(target, 0x2, regs);\r
-               \r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-               \r
-               /* Write I TLB lockdown */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));\r
-       \r
-               /* Read I TLB CAM */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,5,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));\r
-               \r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-               \r
-               /* read I TLB CAM content stored to r2-r9 */\r
-               arm9tdmi_read_core_regs(target, 0x3fc, regs_p);\r
-               jtag_execute_queue();\r
-               \r
-               for (i = 0; i < 8; i++)\r
-                       i_tlb[i + victim].cam = regs[i + 2]; \r
-       }\r
-\r
-       for (victim = 0; victim < 64; victim++)\r
-       {\r
-               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] \r
-                * base remains unchanged, victim goes through entries 0 to 63 */\r
-               regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);\r
-               arm9tdmi_write_core_regs(target, 0x2, regs);\r
-               \r
-               /* set interpret mode */\r
-               cp15c15 |= 0x1;\r
-               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);\r
-               \r
-               /* Write I TLB lockdown */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));\r
-       \r
-               /* Read I TLB RAM1 */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,9,4), ARMV4_5_LDR(2,0));\r
-\r
-               /* Read I TLB RAM2 */\r
-               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,1,5), ARMV4_5_LDR(3,0));\r
-               \r
-               /* clear interpret mode */\r
-               cp15c15 &= ~0x1;\r
-               arm920t_write_cp15_physical(target, 0x1e, cp15c15);\r
-               \r
-               /* read I TLB RAM content stored to r2 and r3 */\r
-               arm9tdmi_read_core_regs(target, 0xc, regs_p);\r
-               jtag_execute_queue();\r
-\r
-               i_tlb[victim].ram1 = regs[2]; \r
-               i_tlb[victim].ram2 = regs[3]; \r
-       }\r
-               \r
-       /* restore I TLB lockdown */\r
-       regs[1] = Ilockdown;\r
-       arm9tdmi_write_core_regs(target, 0x2, regs);\r
-       \r
-       /* Write I TLB lockdown */\r
-       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));\r
-       \r
-       /* restore CP15 MMU and Cache settings */\r
-       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);\r
-\r
-       /* output data to file */       \r
-       fprintf(output, "D TLB content:\n");\r
-       for (i = 0; i < 64; i++)\r
-       {\r
-               fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2, (d_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");\r
-       }\r
-\r
-       fprintf(output, "\n\nI TLB content:\n");\r
-       for (i = 0; i < 64; i++)\r
-       {\r
-               fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2, (i_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");\r
-       }\r
-       \r
-       command_print(cmd_ctx, "mmu content successfully output to %s", args[0]);\r
-       \r
-       fclose(output);\r
-       \r
-       /* mark registers dirty */\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;\r
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;\r
-       \r
-       return ERROR_OK;\r
-}\r
-int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       /* one or more argument, access a single register (write if second argument is given */\r
-       if (argc >= 1)\r
-       {\r
-               int address = strtoul(args[0], NULL, 0);\r
-\r
-               if (argc == 1)\r
-               {\r
-                       u32 value;\r
-                       if ((retval = arm920t_read_cp15_physical(target, address, &value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't access reg %i", address);\r
-                               return ERROR_OK;\r
-                       }\r
-                       jtag_execute_queue();\r
-                       \r
-                       command_print(cmd_ctx, "%i: %8.8x", address, value);\r
-               }\r
-               else if (argc == 2)\r
-               {\r
-                       u32 value = strtoul(args[1], NULL, 0);\r
-                       if ((retval = arm920t_write_cp15_physical(target, address, value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't access reg %i", address);\r
-                               return ERROR_OK;\r
-                       }\r
-                       command_print(cmd_ctx, "%i: %8.8x", address, value);\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       /* one or more argument, access a single register (write if second argument is given */\r
-       if (argc >= 1)\r
-       {\r
-               u32 opcode = strtoul(args[0], NULL, 0);\r
-\r
-               if (argc == 1)\r
-               {\r
-                       u32 value;\r
-                       if ((retval = arm920t_read_cp15_interpreted(target, opcode, 0x0, &value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't execute %8.8x", opcode);\r
-                               return ERROR_OK;\r
-                       }\r
-                       \r
-                       command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);\r
-               }\r
-               else if (argc == 2)\r
-               {\r
-                       u32 value = strtoul(args[1], NULL, 0);\r
-                       if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, 0)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't execute %8.8x", opcode);\r
-                               return ERROR_OK;\r
-                       }\r
-                       command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);\r
-               }\r
-               else if (argc == 3)\r
-               {\r
-                       u32 value = strtoul(args[1], NULL, 0);\r
-                       u32 address = strtoul(args[2], NULL, 0);\r
-                       if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, address)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't execute %8.8x", opcode);\r
-                               return ERROR_OK;\r
-                       }\r
-                       command_print(cmd_ctx, "%8.8x: %8.8x %8.8x", opcode, value, address);\r
-               }\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "usage: arm920t cp15i <opcode> [value] [address]");\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm920t_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       \r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_handle_cache_info_command(cmd_ctx, &arm920t->armv4_5_mmu.armv4_5_cache);\r
-}\r
-\r
-int arm920t_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-               \r
-       return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);\r
-}\r
-\r
-int arm920t_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);\r
-}\r
-\r
-int arm920t_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm920t_common_t *arm920t;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM920t target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm920t.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm920t_register_commands(struct command_context_s *cmd_ctx);
+
+int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int arm920t_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm920t_quit();
+int arm920t_arch_state(struct target_s *target);
+int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm920t_soft_reset_halt(struct target_s *target);
+
+#define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z))
+
+target_type_t arm920t_target =
+{
+       .name = "arm920t",
+
+       .poll = arm7_9_poll,
+       .arch_state = arm920t_arch_state,
+
+       .target_request_data = arm7_9_target_request_data,
+
+       .halt = arm7_9_halt,
+       .resume = arm7_9_resume,
+       .step = arm7_9_step,
+
+       .assert_reset = arm7_9_assert_reset,
+       .deassert_reset = arm7_9_deassert_reset,
+       .soft_reset_halt = arm920t_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
+       
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+       .read_memory = arm920t_read_memory,
+       .write_memory = arm920t_write_memory,
+       .bulk_write_memory = arm7_9_bulk_write_memory,
+       .checksum_memory = arm7_9_checksum_memory,
+       
+       .run_algorithm = armv4_5_run_algorithm,
+
+       .add_breakpoint = arm7_9_add_breakpoint,
+       .remove_breakpoint = arm7_9_remove_breakpoint,
+       .add_watchpoint = arm7_9_add_watchpoint,
+       .remove_watchpoint = arm7_9_remove_watchpoint,
+
+       .register_commands = arm920t_register_commands,
+       .target_command = arm920t_target_command,
+       .init_target = arm920t_init_target,
+       .quit = arm920t_quit
+};
+
+int arm920t_read_cp15_physical(target_t *target, int reg_addr, u32 *value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       scan_field_t fields[4];
+       u8 access_type_buf = 1;
+       u8 reg_addr_buf = reg_addr & 0x3f;
+       u8 nr_w_buf = 0;
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = &access_type_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 6;
+       fields[2].out_value = &reg_addr_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       fields[3].device = jtag_info->chain_pos;
+       fields[3].num_bits = 1;
+       fields[3].out_value = &nr_w_buf;
+       fields[3].out_mask = NULL;
+       fields[3].in_value = NULL;
+       fields[3].in_check_value = NULL;
+       fields[3].in_check_mask = NULL;
+       fields[3].in_handler = NULL;
+       fields[3].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(4, fields, -1);
+
+       fields[1].in_handler_priv = value;
+       fields[1].in_handler = arm_jtag_buf_to_u32;
+
+       jtag_add_dr_scan(4, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       jtag_execute_queue();
+       DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
+#endif
+
+       return ERROR_OK;
+}
+
+int arm920t_write_cp15_physical(target_t *target, int reg_addr, u32 value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       scan_field_t fields[4];
+       u8 access_type_buf = 1;
+       u8 reg_addr_buf = reg_addr & 0x3f;
+       u8 nr_w_buf = 1;
+       u8 value_buf[4];
+       
+       buf_set_u32(value_buf, 0, 32, value);
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = &access_type_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = value_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 6;
+       fields[2].out_value = &reg_addr_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       fields[3].device = jtag_info->chain_pos;
+       fields[3].num_bits = 1;
+       fields[3].out_value = &nr_w_buf;
+       fields[3].out_mask = NULL;
+       fields[3].in_value = NULL;
+       fields[3].in_check_value = NULL;
+       fields[3].in_check_mask = NULL;
+       fields[3].in_handler = NULL;
+       fields[3].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(4, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
+#endif
+
+       return ERROR_OK;
+}
+
+int arm920t_execute_cp15(target_t *target, u32 cp15_opcode, u32 arm_opcode)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       scan_field_t fields[4];
+       u8 access_type_buf = 0;         /* interpreted access */
+       u8 reg_addr_buf = 0x0;
+       u8 nr_w_buf = 0;
+       u8 cp15_opcode_buf[4];
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+       
+       buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 1;
+       fields[0].out_value = &access_type_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = cp15_opcode_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 6;
+       fields[2].out_value = &reg_addr_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       fields[3].device = jtag_info->chain_pos;
+       fields[3].num_bits = 1;
+       fields[3].out_value = &nr_w_buf;
+       fields[3].out_mask = NULL;
+       fields[3].in_value = NULL;
+       fields[3].in_check_value = NULL;
+       fields[3].in_check_mask = NULL;
+       fields[3].in_handler = NULL;
+       fields[3].in_handler_priv = NULL;
+
+       jtag_add_dr_scan(4, fields, -1);
+
+       arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+       arm7_9_execute_sys_speed(target);
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("failed executing JTAG queue, exiting");
+               exit(-1);
+       }
+       
+       return ERROR_OK;
+}
+
+int arm920t_read_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 address, u32 *value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       u32* regs_p[1];
+       u32 regs[2];
+       u32 cp15c15 = 0x0;
+
+       /* load address into R1 */
+       regs[1] = address;
+       arm9tdmi_write_core_regs(target, 0x2, regs); 
+       
+       /* read-modify-write CP15 test state register 
+       * to enable interpreted access mode */
+       arm920t_read_cp15_physical(target, 0x1e, &cp15c15);     
+       jtag_execute_queue();
+       cp15c15 |= 1;   /* set interpret mode */
+       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+       /* execute CP15 instruction and ARM load (reading from coprocessor) */
+       arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1));
+       
+       /* disable interpreted access mode */
+       cp15c15 &= ~1U; /* clear interpret mode */
+       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+       /* retrieve value from R0 */
+       regs_p[0] = value;
+       arm9tdmi_read_core_regs(target, 0x1, regs_p);
+       jtag_execute_queue();
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x", cp15_opcode, address, *value);
+#endif
+
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;
+
+       return ERROR_OK;
+}
+
+int arm920t_write_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 value, u32 address)
+{
+       u32 cp15c15 = 0x0;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       u32 regs[2];
+
+       /* load value, address into R0, R1 */
+       regs[0] = value;
+       regs[1] = address;
+       arm9tdmi_write_core_regs(target, 0x3, regs);
+
+       /* read-modify-write CP15 test state register 
+       * to enable interpreted access mode */
+       arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
+       jtag_execute_queue();
+       cp15c15 |= 1;   /* set interpret mode */
+       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+       /* execute CP15 instruction and ARM store (writing to coprocessor) */
+       arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1));
+
+       /* disable interpreted access mode */
+       cp15c15 &= ~1U; /* set interpret mode */
+       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x", cp15_opcode, value, address);
+#endif
+
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;
+       
+       return ERROR_OK;
+}
+
+u32 arm920t_get_ttb(target_t *target)
+{
+       int retval;
+       u32 ttb = 0x0;
+
+       if ((retval = arm920t_read_cp15_interpreted(target, 0xeebf0f51, 0x0, &ttb)) != ERROR_OK)
+               return retval;
+
+       return ttb;
+}
+
+void arm920t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       arm920t_read_cp15_physical(target, 0x2, &cp15_control);
+       jtag_execute_queue();
+               
+       if (mmu)
+               cp15_control &= ~0x1U;
+       
+       if (d_u_cache)
+               cp15_control &= ~0x4U;
+       
+       if (i_cache)
+               cp15_control &= ~0x1000U;
+
+       arm920t_write_cp15_physical(target, 0x2, cp15_control);
+}
+
+void arm920t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       arm920t_read_cp15_physical(target, 0x2, &cp15_control);
+       jtag_execute_queue();
+               
+       if (mmu)
+               cp15_control |= 0x1U;
+       
+       if (d_u_cache)
+               cp15_control |= 0x4U;
+       
+       if (i_cache)
+               cp15_control |= 0x1000U;
+       
+       arm920t_write_cp15_physical(target, 0x2, cp15_control);
+}
+
+void arm920t_post_debug_entry(target_t *target)
+{
+       u32 cp15c15;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm920t_common_t *arm920t = arm9tdmi->arch_info;
+       
+       /* examine cp15 control reg */
+       arm920t_read_cp15_physical(target, 0x2, &arm920t->cp15_control_reg);
+       jtag_execute_queue();
+       DEBUG("cp15_control_reg: %8.8x", arm920t->cp15_control_reg);
+
+       if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)
+       {
+               u32 cache_type_reg;
+               /* identify caches */
+               arm920t_read_cp15_physical(target, 0x1, &cache_type_reg);
+               jtag_execute_queue();
+               armv4_5_identify_cache(cache_type_reg, &arm920t->armv4_5_mmu.armv4_5_cache);
+       }
+
+       arm920t->armv4_5_mmu.mmu_enabled = (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
+       arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
+       arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
+
+       /* save i/d fault status and address register */
+       arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
+       arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);
+       arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);
+       arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);
+       
+       DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x, I FAR: 0x%8.8x",
+               arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);  
+
+       if (arm920t->preserve_cache)
+       {
+               /* read-modify-write CP15 test state register 
+                * to disable I/D-cache linefills */
+               arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
+               jtag_execute_queue();
+               cp15c15 |= 0x600;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+       }
+}
+
+void arm920t_pre_restore_context(target_t *target)
+{
+       u32 cp15c15;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm920t_common_t *arm920t = arm9tdmi->arch_info;
+       
+       /* restore i/d fault status and address register */
+       arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);
+       arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);
+       arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);
+       arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);
+       
+       /* read-modify-write CP15 test state register 
+       * to reenable I/D-cache linefills */
+       if (arm920t->preserve_cache)
+       {
+               arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
+               jtag_execute_queue();
+               cp15c15 &= ~0x600U;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+       }
+}
+
+int arm920t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm920t_common_t **arm920t_p)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm7_9 = armv4_5->arch_info;
+       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm9tdmi = arm7_9->arch_info;
+       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm920t = arm9tdmi->arch_info;
+       if (arm920t->common_magic != ARM920T_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       *armv4_5_p = armv4_5;
+       *arm7_9_p = arm7_9;
+       *arm9tdmi_p = arm9tdmi;
+       *arm920t_p = arm920t;
+       
+       return ERROR_OK;
+}
+
+int arm920t_arch_state(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm920t_common_t *arm920t = arm9tdmi->arch_info;
+       
+       char *state[] = 
+       {
+               "disabled", "enabled"
+       };
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               ERROR("BUG: called for a non-ARMv4/5 target");
+               exit(-1);
+       }
+       
+       USER(   "target halted in %s state due to %s, current mode: %s\n"
+                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"
+                       "MMU: %s, D-Cache: %s, I-Cache: %s",
+                        armv4_5_state_strings[armv4_5->core_state],
+                        target_debug_reason_strings[target->debug_reason],
+                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
+                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
+                        state[arm920t->armv4_5_mmu.mmu_enabled],
+                        state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], 
+                        state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
+       
+       return ERROR_OK;
+}
+
+int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       int retval;
+       
+       retval = arm7_9_read_memory(target, address, size, count, buffer);
+       
+       return retval;
+}
+
+int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       int retval;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm920t_common_t *arm920t = arm9tdmi->arch_info;
+       
+       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+               return retval;
+
+       if (((size == 4) || (size == 2)) && (count == 1))
+       {
+               if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+               {
+                       DEBUG("D-Cache enabled, writing through to main memory");
+                       u32 pa, cb, ap;
+                       int type, domain;
+
+                       pa = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &type, &cb, &domain, &ap);
+                       if (type == -1)
+                               return ERROR_OK;
+                       /* cacheable & bufferable means write-back region */
+                       if (cb == 3)
+                               armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer);
+               }
+               
+               if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+               {
+                       DEBUG("I-Cache enabled, invalidating affected I-Cache line");
+                       arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address);
+               }
+       }
+
+       return retval;
+}
+
+int arm920t_soft_reset_halt(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm920t_common_t *arm920t = arm9tdmi->arch_info;
+       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+       
+       if (target->state == TARGET_RUNNING)
+       {
+               target->type->halt(target);
+       }
+       
+       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
+       {
+               embeddedice_read_reg(dbg_stat);
+               jtag_execute_queue();
+       }
+       
+       target->state = TARGET_HALTED;
+       
+       /* SVC, ARM state, IRQ and FIQ disabled */
+       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+       
+       /* start fetching from 0x0 */
+       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+       armv4_5->core_cache->reg_list[15].dirty = 1;
+       armv4_5->core_cache->reg_list[15].valid = 1;
+       
+       armv4_5->core_mode = ARMV4_5_MODE_SVC;
+       armv4_5->core_state = ARMV4_5_STATE_ARM;
+       
+       arm920t_disable_mmu_caches(target, 1, 1, 1);
+       arm920t->armv4_5_mmu.mmu_enabled = 0;
+       arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+       arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+       
+       return ERROR_OK;
+}
+
+int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       arm9tdmi_init_target(cmd_ctx, target);
+               
+       return ERROR_OK;
+       
+}
+
+int arm920t_quit()
+{
+       
+       return ERROR_OK;
+}
+
+int arm920t_init_arch_info(target_t *target, arm920t_common_t *arm920t, int chain_pos, char *variant)
+{
+       arm9tdmi_common_t *arm9tdmi = &arm920t->arm9tdmi_common;
+       arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
+       
+       /* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
+        */
+       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+       arm9tdmi->arch_info = arm920t;
+       arm920t->common_magic = ARM920T_COMMON_MAGIC;
+       
+       arm7_9->post_debug_entry = arm920t_post_debug_entry;
+       arm7_9->pre_restore_context = arm920t_pre_restore_context;
+       
+       arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
+       arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
+       arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
+       arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
+       arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
+       arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
+       arm920t->armv4_5_mmu.has_tiny_pages = 1;
+       arm920t->armv4_5_mmu.mmu_enabled = 0;
+       
+       /* disabling linefills leads to lockups, so keep them enabled for now
+        * this doesn't affect correctness, but might affect timing issues, if
+        * important data is evicted from the cache during the debug session
+        * */
+       arm920t->preserve_cache = 0;
+       
+       /* override hw single-step capability from ARM9TDMI */
+       arm7_9->has_single_step = 1;
+       
+       return ERROR_OK;
+}
+
+int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       arm920t_common_t *arm920t = malloc(sizeof(arm920t_common_t));
+       
+       if (argc < 4)
+       {
+               ERROR("'target arm920t' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+       
+       arm920t_init_arch_info(target, arm920t, chain_pos, variant);
+
+       return ERROR_OK;
+}
+
+int arm920t_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       command_t *arm920t_cmd;
+       
+               
+       retval = arm9tdmi_register_commands(cmd_ctx);
+       
+       arm920t_cmd = register_command(cmd_ctx, NULL, "arm920t", NULL, COMMAND_ANY, "arm920t specific commands");
+
+       register_command(cmd_ctx, arm920t_cmd, "cp15", arm920t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
+       register_command(cmd_ctx, arm920t_cmd, "cp15i", arm920t_handle_cp15i_command, COMMAND_EXEC, "display/modify cp15 (interpreted access) <opcode> [value] [address]");
+       register_command(cmd_ctx, arm920t_cmd, "cache_info", arm920t_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");
+       register_command(cmd_ctx, arm920t_cmd, "virt2phys", arm920t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
+
+       register_command(cmd_ctx, arm920t_cmd, "mdw_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
+       register_command(cmd_ctx, arm920t_cmd, "mdh_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
+       register_command(cmd_ctx, arm920t_cmd, "mdb_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
+
+       register_command(cmd_ctx, arm920t_cmd, "mww_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
+       register_command(cmd_ctx, arm920t_cmd, "mwh_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
+       register_command(cmd_ctx, arm920t_cmd, "mwb_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
+
+       register_command(cmd_ctx, arm920t_cmd, "read_cache", arm920t_handle_read_cache_command, COMMAND_EXEC, "display I/D cache content");
+       register_command(cmd_ctx, arm920t_cmd, "read_mmu", arm920t_handle_read_mmu_command, COMMAND_EXEC, "display I/D mmu content");
+
+       return ERROR_OK;
+}
+
+int arm920t_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+       u32 cp15c15;
+       u32 cp15_ctrl, cp15_ctrl_saved;
+       u32 regs[16];
+       u32 *regs_p[16];
+       u32 C15_C_D_Ind, C15_C_I_Ind;
+       int i;
+       FILE *output;
+       arm920t_cache_line_t d_cache[8][64], i_cache[8][64];
+       int segment, index;
+       
+       if (argc != 1)
+       {
+               command_print(cmd_ctx, "usage: arm920t read_cache <filename>");
+               return ERROR_OK;
+       }
+       
+       if ((output = fopen(args[0], "w")) == NULL)
+       {
+               DEBUG("error opening cache content file");
+               return ERROR_OK;
+       }
+       
+       for (i = 0; i < 16; i++)
+               regs_p[i] = &regs[i];
+               
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       /* disable MMU and Caches */
+       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
+       jtag_execute_queue();
+       cp15_ctrl_saved = cp15_ctrl;
+       cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
+       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);
+
+       /* read CP15 test state register */ 
+       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
+       jtag_execute_queue();
+       
+       /* read DCache content */
+       fprintf(output, "DCache:\n");
+       
+       /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ 
+       for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
+       {
+               fprintf(output, "\nsegment: %i\n----------", segment);
+               
+               /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
+               regs[0] = 0x0 | (segment << 5);
+               arm9tdmi_write_core_regs(target, 0x1, regs);
+               
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+               
+               /* D CAM Read, loads current victim into C15.C.D.Ind */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(1, 0));
+       
+               /* read current victim */
+               arm920t_read_cp15_physical(target, 0x3d, &C15_C_D_Ind);
+
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+               for (index = 0; index < 64; index++)
+               {
+                       /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+                       regs[0] = 0x0 | (segment << 5) | (index << 26);
+                       arm9tdmi_write_core_regs(target, 0x1, regs);
+
+                       /* set interpret mode */
+                       cp15c15 |= 0x1;
+                       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+       
+                       /* Write DCache victim */
+                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
+       
+                       /* Read D RAM */
+                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,10,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
+                       
+                       /* Read D CAM */
+                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(9, 0));
+                       
+                       /* clear interpret mode */
+                       cp15c15 &= ~0x1;
+                       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+                       /* read D RAM and CAM content */
+                       arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
+                       jtag_execute_queue();
+
+                       d_cache[segment][index].cam = regs[9];
+                       
+                       /* mask LFSR[6] */
+                       regs[9] &= 0xfffffffe;
+                       fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
+                       
+                       for (i = 1; i < 9; i++)
+                       {
+                                d_cache[segment][index].data[i] = regs[i];
+                                fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);
+                       }
+       
+               }
+               
+               /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+               regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
+               arm9tdmi_write_core_regs(target, 0x1, regs);
+
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+       
+               /* Write DCache victim */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
+       
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+       }
+
+       /* read ICache content */
+       fprintf(output, "ICache:\n");
+       
+       /* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ 
+       for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
+       {
+               fprintf(output, "segment: %i\n----------", segment);
+               
+               /* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
+               regs[0] = 0x0 | (segment << 5);
+               arm9tdmi_write_core_regs(target, 0x1, regs);
+               
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+               
+               /* I CAM Read, loads current victim into C15.C.I.Ind */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(1, 0));
+       
+               /* read current victim */
+               arm920t_read_cp15_physical(target, 0x3b, &C15_C_I_Ind);
+
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+               for (index = 0; index < 64; index++)
+               {
+                       /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+                       regs[0] = 0x0 | (segment << 5) | (index << 26);
+                       arm9tdmi_write_core_regs(target, 0x1, regs);
+
+                       /* set interpret mode */
+                       cp15c15 |= 0x1;
+                       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+       
+                       /* Write ICache victim */
+                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
+       
+                       /* Read I RAM */
+                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,9,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
+                       
+                       /* Read I CAM */
+                       arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(9, 0));
+                       
+                       /* clear interpret mode */
+                       cp15c15 &= ~0x1;
+                       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+                       /* read I RAM and CAM content */
+                       arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
+                       jtag_execute_queue();
+
+                       i_cache[segment][index].cam = regs[9];
+                       
+                       /* mask LFSR[6] */
+                       regs[9] &= 0xfffffffe;
+                       fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
+                       
+                       for (i = 1; i < 9; i++)
+                       {
+                                i_cache[segment][index].data[i] = regs[i];
+                                fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);
+                       }
+       
+               }
+               
+       
+               /* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+               regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
+               arm9tdmi_write_core_regs(target, 0x1, regs);
+
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+       
+               /* Write ICache victim */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
+       
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+       }
+       
+       /* restore CP15 MMU and Cache settings */
+       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);
+       
+       command_print(cmd_ctx, "cache content successfully output to %s", args[0]);
+       
+       fclose(output);
+       
+       /* mark registers dirty. */
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;
+       
+       return ERROR_OK;
+}
+
+int arm920t_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+       u32 cp15c15;
+       u32 cp15_ctrl, cp15_ctrl_saved;
+       u32 regs[16];
+       u32 *regs_p[16];
+       int i;
+       FILE *output;
+       u32 Dlockdown, Ilockdown;
+       arm920t_tlb_entry_t d_tlb[64], i_tlb[64];
+       int victim;
+       
+       if (argc != 1)
+       {
+               command_print(cmd_ctx, "usage: arm920t read_mmu <filename>");
+               return ERROR_OK;
+       }
+       
+       if ((output = fopen(args[0], "w")) == NULL)
+       {
+               DEBUG("error opening mmu content file");
+               return ERROR_OK;
+       }
+       
+       for (i = 0; i < 16; i++)
+               regs_p[i] = &regs[i];
+               
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       /* disable MMU and Caches */
+       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
+       jtag_execute_queue();
+       cp15_ctrl_saved = cp15_ctrl;
+       cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
+       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);
+
+       /* read CP15 test state register */ 
+       arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
+       jtag_execute_queue();
+
+       /* prepare reading D TLB content 
+        * */
+       
+       /* set interpret mode */
+       cp15c15 |= 0x1;
+       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+       
+       /* Read D TLB lockdown */
+       arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,0), ARMV4_5_LDR(1, 0));
+       
+       /* clear interpret mode */
+       cp15c15 &= ~0x1;
+       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+       
+       /* read D TLB lockdown stored to r1 */
+       arm9tdmi_read_core_regs(target, 0x2, regs_p);
+       jtag_execute_queue();
+       Dlockdown = regs[1];
+       
+       for (victim = 0; victim < 64; victim += 8)
+       {
+               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+                * base remains unchanged, victim goes through entries 0 to 63 */
+               regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
+               arm9tdmi_write_core_regs(target, 0x2, regs);
+               
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+               
+               /* Write D TLB lockdown */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
+       
+               /* Read D TLB CAM */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,6,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
+               
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+               
+               /* read D TLB CAM content stored to r2-r9 */
+               arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
+               jtag_execute_queue();
+               
+               for (i = 0; i < 8; i++)
+                       d_tlb[victim + i].cam = regs[i + 2]; 
+       }
+
+       for (victim = 0; victim < 64; victim++)
+       {
+               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+                * base remains unchanged, victim goes through entries 0 to 63 */
+               regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
+               arm9tdmi_write_core_regs(target, 0x2, regs);
+               
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+               
+               /* Write D TLB lockdown */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
+       
+               /* Read D TLB RAM1 */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,10,4), ARMV4_5_LDR(2,0));
+
+               /* Read D TLB RAM2 */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,2,5), ARMV4_5_LDR(3,0));
+               
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+               
+               /* read D TLB RAM content stored to r2 and r3 */
+               arm9tdmi_read_core_regs(target, 0xc, regs_p);
+               jtag_execute_queue();
+
+               d_tlb[victim].ram1 = regs[2]; 
+               d_tlb[victim].ram2 = regs[3]; 
+       }
+               
+       /* restore D TLB lockdown */
+       regs[1] = Dlockdown;
+       arm9tdmi_write_core_regs(target, 0x2, regs);
+       
+       /* Write D TLB lockdown */
+       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
+
+       /* prepare reading I TLB content 
+        * */
+       
+       /* set interpret mode */
+       cp15c15 |= 0x1;
+       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+       
+       /* Read I TLB lockdown */
+       arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,1), ARMV4_5_LDR(1, 0));
+       
+       /* clear interpret mode */
+       cp15c15 &= ~0x1;
+       arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+       
+       /* read I TLB lockdown stored to r1 */
+       arm9tdmi_read_core_regs(target, 0x2, regs_p);
+       jtag_execute_queue();
+       Ilockdown = regs[1];
+       
+       for (victim = 0; victim < 64; victim += 8)
+       {
+               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+                * base remains unchanged, victim goes through entries 0 to 63 */
+               regs[1] = (Ilockdown & 0xfc000000) | (victim << 20);
+               arm9tdmi_write_core_regs(target, 0x2, regs);
+               
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+               
+               /* Write I TLB lockdown */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
+       
+               /* Read I TLB CAM */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,5,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
+               
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+               
+               /* read I TLB CAM content stored to r2-r9 */
+               arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
+               jtag_execute_queue();
+               
+               for (i = 0; i < 8; i++)
+                       i_tlb[i + victim].cam = regs[i + 2]; 
+       }
+
+       for (victim = 0; victim < 64; victim++)
+       {
+               /* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+                * base remains unchanged, victim goes through entries 0 to 63 */
+               regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
+               arm9tdmi_write_core_regs(target, 0x2, regs);
+               
+               /* set interpret mode */
+               cp15c15 |= 0x1;
+               arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+               
+               /* Write I TLB lockdown */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
+       
+               /* Read I TLB RAM1 */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,9,4), ARMV4_5_LDR(2,0));
+
+               /* Read I TLB RAM2 */
+               arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,1,5), ARMV4_5_LDR(3,0));
+               
+               /* clear interpret mode */
+               cp15c15 &= ~0x1;
+               arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+               
+               /* read I TLB RAM content stored to r2 and r3 */
+               arm9tdmi_read_core_regs(target, 0xc, regs_p);
+               jtag_execute_queue();
+
+               i_tlb[victim].ram1 = regs[2]; 
+               i_tlb[victim].ram2 = regs[3]; 
+       }
+               
+       /* restore I TLB lockdown */
+       regs[1] = Ilockdown;
+       arm9tdmi_write_core_regs(target, 0x2, regs);
+       
+       /* Write I TLB lockdown */
+       arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
+       
+       /* restore CP15 MMU and Cache settings */
+       arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);
+
+       /* output data to file */       
+       fprintf(output, "D TLB content:\n");
+       for (i = 0; i < 64; i++)
+       {
+               fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2, (d_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
+       }
+
+       fprintf(output, "\n\nI TLB content:\n");
+       for (i = 0; i < 64; i++)
+       {
+               fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2, (i_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
+       }
+       
+       command_print(cmd_ctx, "mmu content successfully output to %s", args[0]);
+       
+       fclose(output);
+       
+       /* mark registers dirty */
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;
+       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;
+       
+       return ERROR_OK;
+}
+int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       /* one or more argument, access a single register (write if second argument is given */
+       if (argc >= 1)
+       {
+               int address = strtoul(args[0], NULL, 0);
+
+               if (argc == 1)
+               {
+                       u32 value;
+                       if ((retval = arm920t_read_cp15_physical(target, address, &value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't access reg %i", address);
+                               return ERROR_OK;
+                       }
+                       jtag_execute_queue();
+                       
+                       command_print(cmd_ctx, "%i: %8.8x", address, value);
+               }
+               else if (argc == 2)
+               {
+                       u32 value = strtoul(args[1], NULL, 0);
+                       if ((retval = arm920t_write_cp15_physical(target, address, value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't access reg %i", address);
+                               return ERROR_OK;
+                       }
+                       command_print(cmd_ctx, "%i: %8.8x", address, value);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       /* one or more argument, access a single register (write if second argument is given */
+       if (argc >= 1)
+       {
+               u32 opcode = strtoul(args[0], NULL, 0);
+
+               if (argc == 1)
+               {
+                       u32 value;
+                       if ((retval = arm920t_read_cp15_interpreted(target, opcode, 0x0, &value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
+                               return ERROR_OK;
+                       }
+                       
+                       command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);
+               }
+               else if (argc == 2)
+               {
+                       u32 value = strtoul(args[1], NULL, 0);
+                       if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, 0)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
+                               return ERROR_OK;
+                       }
+                       command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);
+               }
+               else if (argc == 3)
+               {
+                       u32 value = strtoul(args[1], NULL, 0);
+                       u32 address = strtoul(args[2], NULL, 0);
+                       if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, address)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
+                               return ERROR_OK;
+                       }
+                       command_print(cmd_ctx, "%8.8x: %8.8x %8.8x", opcode, value, address);
+               }
+       }
+       else
+       {
+               command_print(cmd_ctx, "usage: arm920t cp15i <opcode> [value] [address]");
+       }
+
+       return ERROR_OK;
+}
+
+int arm920t_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       return armv4_5_handle_cache_info_command(cmd_ctx, &arm920t->armv4_5_mmu.armv4_5_cache);
+}
+
+int arm920t_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+               
+       return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
+}
+
+int arm920t_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
+}
+
+int arm920t_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm920t_common_t *arm920t;
+       arm_jtag_t *jtag_info;
+
+       if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM920t target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
+}
index a02c27ae79bd3289aac7c4b797c4928ec18685d7..afe9226c7fc06db913413310432d34942619f7c4 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm926ejs.h"\r
-#include "jtag.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 1\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-/* cli handling */\r
-int arm926ejs_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm926ejs_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm926ejs_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm926ejs_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm926ejs_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int arm926ejs_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int arm926ejs_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-/* forward declarations */\r
-int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm926ejs_quit();\r
-int arm926ejs_arch_state(struct target_s *target);\r
-int arm926ejs_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int arm926ejs_soft_reset_halt(struct target_s *target);\r
-static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical);\r
-static int arm926ejs_mmu(struct target_s *target, int *enabled);\r
-\r
-target_type_t arm926ejs_target =\r
-{\r
-       .name = "arm926ejs",\r
-\r
-       .poll = arm7_9_poll,\r
-       .arch_state = arm926ejs_arch_state,\r
-\r
-       .target_request_data = arm7_9_target_request_data,\r
-\r
-       .halt = arm7_9_halt,\r
-       .resume = arm7_9_resume,\r
-       .step = arm7_9_step,\r
-\r
-       .assert_reset = arm7_9_assert_reset,\r
-       .deassert_reset = arm7_9_deassert_reset,\r
-       .soft_reset_halt = arm926ejs_soft_reset_halt,\r
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
-       \r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-\r
-       .read_memory = arm7_9_read_memory,\r
-       .write_memory = arm926ejs_write_memory,\r
-       .bulk_write_memory = arm7_9_bulk_write_memory,\r
-       .checksum_memory = arm7_9_checksum_memory,\r
-       \r
-       .run_algorithm = armv4_5_run_algorithm,\r
-\r
-       .add_breakpoint = arm7_9_add_breakpoint,\r
-       .remove_breakpoint = arm7_9_remove_breakpoint,\r
-       .add_watchpoint = arm7_9_add_watchpoint,\r
-       .remove_watchpoint = arm7_9_remove_watchpoint,\r
-\r
-       .register_commands = arm926ejs_register_commands,\r
-       .target_command = arm926ejs_target_command,\r
-       .init_target = arm926ejs_init_target,\r
-       .quit = arm926ejs_quit,\r
-       .virt2phys = arm926ejs_virt2phys,\r
-       .mmu = arm926ejs_mmu\r
-};\r
-\r
-\r
-int arm926ejs_catch_broken_irscan(u8 *captured, void *priv, scan_field_t *field)\r
-{\r
-       /* The ARM926EJ-S' instruction register is 4 bits wide */\r
-       u8 t = *captured & 0xf;\r
-       u8 t2 = *field->in_check_value & 0xf;\r
-       if (t == t2)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-       else if ((t == 0x0f) || (t == 0x00))\r
-       {\r
-               DEBUG("caught ARM926EJ-S invalid Capture-IR result after CP15 access");\r
-               return ERROR_OK;\r
-       }\r
-       return ERROR_JTAG_QUEUE_FAILED;;\r
-}\r
-\r
-#define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))\r
-\r
-int arm926ejs_cp15_read(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);\r
-       scan_field_t fields[4];\r
-       u8 address_buf[2];\r
-       u8 nr_w_buf = 0;\r
-       u8 access = 1;\r
-       \r
-       buf_set_u32(address_buf, 0, 14, address);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 1;\r
-       fields[1].out_value = &access;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = &access;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 14;\r
-       fields[2].out_value = address_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       fields[3].device = jtag_info->chain_pos;\r
-       fields[3].num_bits = 1;\r
-       fields[3].out_value = &nr_w_buf;\r
-       fields[3].out_mask = NULL;\r
-       fields[3].in_value = NULL;\r
-       fields[3].in_check_value = NULL;\r
-       fields[3].in_check_mask = NULL;\r
-       fields[3].in_handler = NULL;\r
-       fields[3].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(4, fields, -1);\r
-\r
-       fields[0].in_handler_priv = value;\r
-       fields[0].in_handler = arm_jtag_buf_to_u32;\r
-       \r
-       do\r
-       {\r
-               /* rescan with NOP, to wait for the access to complete */\r
-               access = 0;\r
-               nr_w_buf = 0;\r
-               jtag_add_dr_scan(4, fields, -1);\r
-               jtag_execute_queue();\r
-       } while (buf_get_u32(&access, 0, 1) != 1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       DEBUG("addr: 0x%x value: %8.8x", address, *value);\r
-#endif\r
-       \r
-       arm_jtag_set_instr(jtag_info, 0xc, &arm926ejs_catch_broken_irscan);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_cp15_write(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);\r
-       scan_field_t fields[4];\r
-       u8 value_buf[4];\r
-       u8 address_buf[2];\r
-       u8 nr_w_buf = 1;\r
-       u8 access = 1;\r
-       \r
-       buf_set_u32(address_buf, 0, 14, address);\r
-       buf_set_u32(value_buf, 0, 32, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = value_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 1;\r
-       fields[1].out_value = &access;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = &access;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 14;\r
-       fields[2].out_value = address_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       fields[3].device = jtag_info->chain_pos;\r
-       fields[3].num_bits = 1;\r
-       fields[3].out_value = &nr_w_buf;\r
-       fields[3].out_mask = NULL;\r
-       fields[3].in_value = NULL;\r
-       fields[3].in_check_value = NULL;\r
-       fields[3].in_check_mask = NULL;\r
-       fields[3].in_handler = NULL;\r
-       fields[3].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(4, fields, -1);\r
-\r
-       do\r
-       {\r
-               /* rescan with NOP, to wait for the access to complete */\r
-               access = 0;\r
-               nr_w_buf = 0;\r
-               jtag_add_dr_scan(4, fields, -1);\r
-               jtag_execute_queue();\r
-       } while (buf_get_u32(&access, 0, 1) != 1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       DEBUG("addr: 0x%x value: %8.8x", address, value);\r
-#endif\r
-\r
-       arm_jtag_set_instr(jtag_info, 0xf, &arm926ejs_catch_broken_irscan);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_examine_debug_reason(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
-       int debug_reason;\r
-       int retval;\r
-\r
-       embeddedice_read_reg(dbg_stat);\r
-       if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-               return retval;\r
-       \r
-       debug_reason = buf_get_u32(dbg_stat->value, 6, 4);\r
-       \r
-       switch (debug_reason)\r
-       {\r
-               case 1:\r
-                       DEBUG("breakpoint from EICE unit 0");\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       break;\r
-               case 2:\r
-                       DEBUG("breakpoint from EICE unit 1");\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       break;\r
-               case 3:\r
-                       DEBUG("soft breakpoint (BKPT instruction)");\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       break;\r
-               case 4:\r
-                       DEBUG("vector catch breakpoint");\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       break;\r
-               case 5:\r
-                       DEBUG("external breakpoint");\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       break;\r
-               case 6:\r
-                       DEBUG("watchpoint from EICE unit 0");\r
-                       target->debug_reason = DBG_REASON_WATCHPOINT;\r
-                       break;\r
-               case 7:\r
-                       DEBUG("watchpoint from EICE unit 1");\r
-                       target->debug_reason = DBG_REASON_WATCHPOINT;\r
-                       break;\r
-               case 8:\r
-                       DEBUG("external watchpoint");\r
-                       target->debug_reason = DBG_REASON_WATCHPOINT;\r
-                       break;\r
-               case 9:\r
-                       DEBUG("internal debug request");\r
-                       target->debug_reason = DBG_REASON_DBGRQ;\r
-                       break;\r
-               case 10:\r
-                       DEBUG("external debug request");\r
-                       target->debug_reason = DBG_REASON_DBGRQ;\r
-                       break;\r
-               case 11:\r
-                       ERROR("BUG: debug re-entry from system speed access shouldn't be handled here");\r
-                       break;\r
-               default:\r
-                       ERROR("BUG: unknown debug reason: 0x%x", debug_reason);\r
-                       target->debug_reason = DBG_REASON_DBGRQ;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-u32 arm926ejs_get_ttb(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-       int retval;\r
-       u32 ttb = 0x0;\r
-\r
-       if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)\r
-               return retval;\r
-\r
-       return ttb;\r
-}\r
-\r
-void arm926ejs_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);\r
-       jtag_execute_queue();\r
-       \r
-       if (mmu)\r
-       {\r
-               /* invalidate TLB */\r
-               arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);\r
-               \r
-               cp15_control &= ~0x1U;\r
-       }\r
-       \r
-       if (d_u_cache)\r
-       {\r
-               u32 debug_override;\r
-               /* read-modify-write CP15 debug override register \r
-                * to enable "test and clean all" */\r
-               arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);\r
-               debug_override |= 0x80000;\r
-               arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);\r
-               \r
-               /* clean and invalidate DCache */\r
-               arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);\r
-\r
-               /* write CP15 debug override register \r
-                * to disable "test and clean all" */\r
-               debug_override &= ~0x80000;\r
-               arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);\r
-               \r
-               cp15_control &= ~0x4U;\r
-       }\r
-       \r
-       if (i_cache)\r
-       {\r
-               /* invalidate ICache */\r
-               arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);\r
-               \r
-               cp15_control &= ~0x1000U;\r
-       }\r
-       \r
-       arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);\r
-}\r
-\r
-void arm926ejs_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);\r
-       jtag_execute_queue();\r
-               \r
-       if (mmu)\r
-               cp15_control |= 0x1U;\r
-       \r
-       if (d_u_cache)\r
-               cp15_control |= 0x4U;\r
-       \r
-       if (i_cache)\r
-               cp15_control |= 0x1000U;\r
-       \r
-       arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);\r
-}\r
-\r
-void arm926ejs_post_debug_entry(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-\r
-       /* examine cp15 control reg */\r
-       arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);\r
-       jtag_execute_queue();\r
-       DEBUG("cp15_control_reg: %8.8x", arm926ejs->cp15_control_reg);\r
-\r
-       if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)\r
-       {\r
-               u32 cache_type_reg;\r
-               /* identify caches */\r
-               arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);\r
-               jtag_execute_queue();\r
-               armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);\r
-       }\r
-\r
-       arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;\r
-       arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;\r
-       arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;\r
-\r
-       /* save i/d fault status and address register */\r
-       arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);\r
-       arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);\r
-       arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);\r
-       \r
-       DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x",\r
-               arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);  \r
-\r
-\r
-       u32 cache_dbg_ctrl;\r
-       \r
-       /* read-modify-write CP15 cache debug control register \r
-        * to disable I/D-cache linefills and force WT */\r
-       arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);\r
-       cache_dbg_ctrl |= 0x7;\r
-       arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);\r
-}\r
-\r
-void arm926ejs_pre_restore_context(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-\r
-       /* restore i/d fault status and address register */\r
-       arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);\r
-       arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);\r
-       arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);\r
-       \r
-       u32 cache_dbg_ctrl;\r
-       \r
-       /* read-modify-write CP15 cache debug control register \r
-        * to reenable I/D-cache linefills and disable WT */\r
-       arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);\r
-       cache_dbg_ctrl &= ~0x7;\r
-       arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);\r
-}\r
-\r
-int arm926ejs_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm926ejs_common_t **arm926ejs_p)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm7_9 = armv4_5->arch_info;\r
-       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm9tdmi = arm7_9->arch_info;\r
-       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm926ejs = arm9tdmi->arch_info;\r
-       if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       *armv4_5_p = armv4_5;\r
-       *arm7_9_p = arm7_9;\r
-       *arm9tdmi_p = arm9tdmi;\r
-       *arm926ejs_p = arm926ejs;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_arch_state(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-       \r
-       char *state[] = \r
-       {\r
-               "disabled", "enabled"\r
-       };\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               ERROR("BUG: called for a non-ARMv4/5 target");\r
-               exit(-1);\r
-       }\r
-       \r
-       USER(\r
-                       "target halted in %s state due to %s, current mode: %s\n"\r
-                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"\r
-                       "MMU: %s, D-Cache: %s, I-Cache: %s",\r
-                        armv4_5_state_strings[armv4_5->core_state],\r
-                        target_debug_reason_strings[target->debug_reason],\r
-                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),\r
-                        state[arm926ejs->armv4_5_mmu.mmu_enabled],\r
-                        state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], \r
-                        state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_soft_reset_halt(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
-       \r
-       if (target->state == TARGET_RUNNING)\r
-       {\r
-               target->type->halt(target);\r
-       }\r
-       \r
-       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)\r
-       {\r
-               embeddedice_read_reg(dbg_stat);\r
-               jtag_execute_queue();\r
-       }\r
-       \r
-       target->state = TARGET_HALTED;\r
-       \r
-       /* SVC, ARM state, IRQ and FIQ disabled */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;\r
-       \r
-       /* start fetching from 0x0 */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);\r
-       armv4_5->core_cache->reg_list[15].dirty = 1;\r
-       armv4_5->core_cache->reg_list[15].valid = 1;\r
-       \r
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;\r
-       armv4_5->core_state = ARMV4_5_STATE_ARM;\r
-       \r
-       arm926ejs_disable_mmu_caches(target, 1, 1, 1);\r
-       arm926ejs->armv4_5_mmu.mmu_enabled = 0;\r
-       arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;\r
-       arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;\r
-\r
-       target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       int retval;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;\r
-       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;\r
-       \r
-       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)\r
-               return retval;\r
-\r
-       /* If ICache is enabled, we have to invalidate affected ICache lines\r
-        * the DCache is forced to write-through, so we don't have to clean it here\r
-        */\r
-       if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)\r
-       {\r
-               if (count <= 1)\r
-               {\r
-                       /* invalidate ICache single entry with MVA */\r
-                       arm926ejs->write_cp15(target, 0, 1, 7, 5, address);\r
-               }\r
-               else\r
-               {\r
-                       /* invalidate ICache */\r
-                       arm926ejs->write_cp15(target, 0, 0, 7, 5, address);\r
-               }\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       arm9tdmi_init_target(cmd_ctx, target);\r
-               \r
-       return ERROR_OK;\r
-       \r
-}\r
-\r
-int arm926ejs_quit()\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_init_arch_info(target_t *target, arm926ejs_common_t *arm926ejs, int chain_pos, char *variant)\r
-{\r
-       arm9tdmi_common_t *arm9tdmi = &arm926ejs->arm9tdmi_common;\r
-       arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;\r
-       \r
-       /* initialize arm9tdmi specific info (including arm7_9 and armv4_5)\r
-        */\r
-       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);\r
-\r
-       arm9tdmi->arch_info = arm926ejs;\r
-       arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;\r
-       \r
-       arm7_9->post_debug_entry = arm926ejs_post_debug_entry;\r
-       arm7_9->pre_restore_context = arm926ejs_pre_restore_context;\r
-       \r
-       arm926ejs->read_cp15 = arm926ejs_cp15_read;\r
-       arm926ejs->write_cp15 = arm926ejs_cp15_write;\r
-       arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;\r
-       arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;\r
-       arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;\r
-       arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;\r
-       arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;\r
-       arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;\r
-       arm926ejs->armv4_5_mmu.has_tiny_pages = 1;\r
-       arm926ejs->armv4_5_mmu.mmu_enabled = 0;\r
-       \r
-       arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;\r
-       \r
-       /* The ARM926EJ-S implements the ARMv5TE architecture which\r
-        * has the BKPT instruction, so we don't have to use a watchpoint comparator\r
-        */\r
-       arm7_9->arm_bkpt = ARMV5_BKPT(0x0);\r
-       arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;\r
-       \r
-       arm7_9->sw_bkpts_use_wp = 0;\r
-       arm7_9->sw_bkpts_enabled = 1;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));\r
-       \r
-       if (argc < 4)\r
-       {\r
-               ERROR("'target arm926ejs' requires at least one additional argument");\r
-               exit(-1);\r
-       }\r
-       \r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-       \r
-       if (argc >= 5)\r
-               variant = args[4];\r
-       \r
-       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);\r
-       \r
-       arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       command_t *arm926ejs_cmd;\r
-       \r
-               \r
-       retval = arm9tdmi_register_commands(cmd_ctx);\r
-       \r
-       arm926ejs_cmd = register_command(cmd_ctx, NULL, "arm926ejs", NULL, COMMAND_ANY, "arm926ejs specific commands");\r
-\r
-       register_command(cmd_ctx, arm926ejs_cmd, "cp15", arm926ejs_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode_1> <opcode_2> <CRn> <CRm> [value]");\r
-       \r
-       register_command(cmd_ctx, arm926ejs_cmd, "cache_info", arm926ejs_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");\r
-       register_command(cmd_ctx, arm926ejs_cmd, "virt2phys", arm926ejs_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");\r
-\r
-       register_command(cmd_ctx, arm926ejs_cmd, "mdw_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");\r
-       register_command(cmd_ctx, arm926ejs_cmd, "mdh_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");\r
-       register_command(cmd_ctx, arm926ejs_cmd, "mdb_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");\r
-\r
-       register_command(cmd_ctx, arm926ejs_cmd, "mww_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");\r
-       register_command(cmd_ctx, arm926ejs_cmd, "mwh_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");\r
-       register_command(cmd_ctx, arm926ejs_cmd, "mwb_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       int opcode_1;\r
-       int opcode_2;\r
-       int CRn;\r
-       int CRm;\r
-\r
-       if ((argc < 4) || (argc > 5))\r
-       {\r
-               command_print(cmd_ctx, "usage: arm926ejs cp15 <opcode_1> <opcode_2> <CRn> <CRm> [value]");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       opcode_1 = strtoul(args[0], NULL, 0);\r
-       opcode_2 = strtoul(args[1], NULL, 0);\r
-       CRn = strtoul(args[2], NULL, 0);\r
-       CRm = strtoul(args[3], NULL, 0);\r
-\r
-       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (argc == 4)\r
-       {\r
-               u32 value;\r
-               if ((retval = arm926ejs->read_cp15(target, opcode_1, opcode_2, CRn, CRm, &value)) != ERROR_OK)\r
-               {\r
-                       command_print(cmd_ctx, "couldn't access register");\r
-                       return ERROR_OK;\r
-               }\r
-               jtag_execute_queue();\r
-               \r
-               command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);\r
-       }\r
-       else\r
-       {\r
-               u32 value = strtoul(args[4], NULL, 0);\r
-               if ((retval = arm926ejs->write_cp15(target, opcode_1, opcode_2, CRn, CRm, value)) != ERROR_OK)\r
-               {\r
-                       command_print(cmd_ctx, "couldn't access register");\r
-                       return ERROR_OK;\r
-               }\r
-               command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       \r
-       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_handle_cache_info_command(cmd_ctx, &arm926ejs->armv4_5_mmu.armv4_5_cache);\r
-}\r
-\r
-int arm926ejs_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-               \r
-       return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);\r
-}\r
-\r
-int arm926ejs_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);\r
-}\r
-\r
-int arm926ejs_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{      \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);\r
-}\r
-static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical)\r
-{\r
-       int retval;\r
-       int type;\r
-       u32 cb;\r
-       int domain;\r
-       u32 ap;\r
-       \r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm926ejs_common_t *arm926ejs;\r
-       retval= arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs);\r
-       if (retval != ERROR_OK)\r
-       {\r
-               return retval;\r
-       }\r
-       u32 ret = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);\r
-       if (type == -1)\r
-       {\r
-               return ret;\r
-       }\r
-       *physical = ret;\r
-       return ERROR_OK;\r
-}\r
-\r
-static int arm926ejs_mmu(struct target_s *target, int *enabled)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm926ejs_common_t *arm926ejs = armv4_5->arch_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               ERROR("Target not halted");\r
-               return ERROR_TARGET_INVALID;\r
-       }\r
-       *enabled = arm926ejs->armv4_5_mmu.mmu_enabled;\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm926ejs.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 1
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm926ejs_register_commands(struct command_context_s *cmd_ctx);
+
+int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int arm926ejs_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm926ejs_quit();
+int arm926ejs_arch_state(struct target_s *target);
+int arm926ejs_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm926ejs_soft_reset_halt(struct target_s *target);
+static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
+static int arm926ejs_mmu(struct target_s *target, int *enabled);
+
+target_type_t arm926ejs_target =
+{
+       .name = "arm926ejs",
+
+       .poll = arm7_9_poll,
+       .arch_state = arm926ejs_arch_state,
+
+       .target_request_data = arm7_9_target_request_data,
+
+       .halt = arm7_9_halt,
+       .resume = arm7_9_resume,
+       .step = arm7_9_step,
+
+       .assert_reset = arm7_9_assert_reset,
+       .deassert_reset = arm7_9_deassert_reset,
+       .soft_reset_halt = arm926ejs_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
+       
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+       .read_memory = arm7_9_read_memory,
+       .write_memory = arm926ejs_write_memory,
+       .bulk_write_memory = arm7_9_bulk_write_memory,
+       .checksum_memory = arm7_9_checksum_memory,
+       
+       .run_algorithm = armv4_5_run_algorithm,
+
+       .add_breakpoint = arm7_9_add_breakpoint,
+       .remove_breakpoint = arm7_9_remove_breakpoint,
+       .add_watchpoint = arm7_9_add_watchpoint,
+       .remove_watchpoint = arm7_9_remove_watchpoint,
+
+       .register_commands = arm926ejs_register_commands,
+       .target_command = arm926ejs_target_command,
+       .init_target = arm926ejs_init_target,
+       .quit = arm926ejs_quit,
+       .virt2phys = arm926ejs_virt2phys,
+       .mmu = arm926ejs_mmu
+};
+
+
+int arm926ejs_catch_broken_irscan(u8 *captured, void *priv, scan_field_t *field)
+{
+       /* The ARM926EJ-S' instruction register is 4 bits wide */
+       u8 t = *captured & 0xf;
+       u8 t2 = *field->in_check_value & 0xf;
+       if (t == t2)
+       {
+               return ERROR_OK;
+       }
+       else if ((t == 0x0f) || (t == 0x00))
+       {
+               DEBUG("caught ARM926EJ-S invalid Capture-IR result after CP15 access");
+               return ERROR_OK;
+       }
+       return ERROR_JTAG_QUEUE_FAILED;;
+}
+
+#define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))
+
+int arm926ejs_cp15_read(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
+       scan_field_t fields[4];
+       u8 address_buf[2];
+       u8 nr_w_buf = 0;
+       u8 access = 1;
+       
+       buf_set_u32(address_buf, 0, 14, address);
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 1;
+       fields[1].out_value = &access;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = &access;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 14;
+       fields[2].out_value = address_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       fields[3].device = jtag_info->chain_pos;
+       fields[3].num_bits = 1;
+       fields[3].out_value = &nr_w_buf;
+       fields[3].out_mask = NULL;
+       fields[3].in_value = NULL;
+       fields[3].in_check_value = NULL;
+       fields[3].in_check_mask = NULL;
+       fields[3].in_handler = NULL;
+       fields[3].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(4, fields, -1);
+
+       fields[0].in_handler_priv = value;
+       fields[0].in_handler = arm_jtag_buf_to_u32;
+       
+       do
+       {
+               /* rescan with NOP, to wait for the access to complete */
+               access = 0;
+               nr_w_buf = 0;
+               jtag_add_dr_scan(4, fields, -1);
+               jtag_execute_queue();
+       } while (buf_get_u32(&access, 0, 1) != 1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       DEBUG("addr: 0x%x value: %8.8x", address, *value);
+#endif
+       
+       arm_jtag_set_instr(jtag_info, 0xc, &arm926ejs_catch_broken_irscan);
+
+       return ERROR_OK;
+}
+
+int arm926ejs_cp15_write(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
+       scan_field_t fields[4];
+       u8 value_buf[4];
+       u8 address_buf[2];
+       u8 nr_w_buf = 1;
+       u8 access = 1;
+       
+       buf_set_u32(address_buf, 0, 14, address);
+       buf_set_u32(value_buf, 0, 32, value);
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = value_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 1;
+       fields[1].out_value = &access;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = &access;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 14;
+       fields[2].out_value = address_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       fields[3].device = jtag_info->chain_pos;
+       fields[3].num_bits = 1;
+       fields[3].out_value = &nr_w_buf;
+       fields[3].out_mask = NULL;
+       fields[3].in_value = NULL;
+       fields[3].in_check_value = NULL;
+       fields[3].in_check_mask = NULL;
+       fields[3].in_handler = NULL;
+       fields[3].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(4, fields, -1);
+
+       do
+       {
+               /* rescan with NOP, to wait for the access to complete */
+               access = 0;
+               nr_w_buf = 0;
+               jtag_add_dr_scan(4, fields, -1);
+               jtag_execute_queue();
+       } while (buf_get_u32(&access, 0, 1) != 1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       DEBUG("addr: 0x%x value: %8.8x", address, value);
+#endif
+
+       arm_jtag_set_instr(jtag_info, 0xf, &arm926ejs_catch_broken_irscan);
+
+       return ERROR_OK;
+}
+
+int arm926ejs_examine_debug_reason(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+       int debug_reason;
+       int retval;
+
+       embeddedice_read_reg(dbg_stat);
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+               return retval;
+       
+       debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
+       
+       switch (debug_reason)
+       {
+               case 1:
+                       DEBUG("breakpoint from EICE unit 0");
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       break;
+               case 2:
+                       DEBUG("breakpoint from EICE unit 1");
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       break;
+               case 3:
+                       DEBUG("soft breakpoint (BKPT instruction)");
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       break;
+               case 4:
+                       DEBUG("vector catch breakpoint");
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       break;
+               case 5:
+                       DEBUG("external breakpoint");
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       break;
+               case 6:
+                       DEBUG("watchpoint from EICE unit 0");
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+                       break;
+               case 7:
+                       DEBUG("watchpoint from EICE unit 1");
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+                       break;
+               case 8:
+                       DEBUG("external watchpoint");
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+                       break;
+               case 9:
+                       DEBUG("internal debug request");
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       break;
+               case 10:
+                       DEBUG("external debug request");
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       break;
+               case 11:
+                       ERROR("BUG: debug re-entry from system speed access shouldn't be handled here");
+                       break;
+               default:
+                       ERROR("BUG: unknown debug reason: 0x%x", debug_reason);
+                       target->debug_reason = DBG_REASON_DBGRQ;
+       }
+       
+       return ERROR_OK;
+}
+
+u32 arm926ejs_get_ttb(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+       int retval;
+       u32 ttb = 0x0;
+
+       if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)
+               return retval;
+
+       return ttb;
+}
+
+void arm926ejs_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
+       jtag_execute_queue();
+       
+       if (mmu)
+       {
+               /* invalidate TLB */
+               arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
+               
+               cp15_control &= ~0x1U;
+       }
+       
+       if (d_u_cache)
+       {
+               u32 debug_override;
+               /* read-modify-write CP15 debug override register 
+                * to enable "test and clean all" */
+               arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);
+               debug_override |= 0x80000;
+               arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
+               
+               /* clean and invalidate DCache */
+               arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
+
+               /* write CP15 debug override register 
+                * to disable "test and clean all" */
+               debug_override &= ~0x80000;
+               arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
+               
+               cp15_control &= ~0x4U;
+       }
+       
+       if (i_cache)
+       {
+               /* invalidate ICache */
+               arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
+               
+               cp15_control &= ~0x1000U;
+       }
+       
+       arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
+}
+
+void arm926ejs_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
+       jtag_execute_queue();
+               
+       if (mmu)
+               cp15_control |= 0x1U;
+       
+       if (d_u_cache)
+               cp15_control |= 0x4U;
+       
+       if (i_cache)
+               cp15_control |= 0x1000U;
+       
+       arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
+}
+
+void arm926ejs_post_debug_entry(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+
+       /* examine cp15 control reg */
+       arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);
+       jtag_execute_queue();
+       DEBUG("cp15_control_reg: %8.8x", arm926ejs->cp15_control_reg);
+
+       if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)
+       {
+               u32 cache_type_reg;
+               /* identify caches */
+               arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
+               jtag_execute_queue();
+               armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);
+       }
+
+       arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;
+       arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;
+       arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;
+
+       /* save i/d fault status and address register */
+       arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);
+       arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);
+       arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);
+       
+       DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x",
+               arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);  
+
+
+       u32 cache_dbg_ctrl;
+       
+       /* read-modify-write CP15 cache debug control register 
+        * to disable I/D-cache linefills and force WT */
+       arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
+       cache_dbg_ctrl |= 0x7;
+       arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
+}
+
+void arm926ejs_pre_restore_context(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+
+       /* restore i/d fault status and address register */
+       arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);
+       arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);
+       arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);
+       
+       u32 cache_dbg_ctrl;
+       
+       /* read-modify-write CP15 cache debug control register 
+        * to reenable I/D-cache linefills and disable WT */
+       arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
+       cache_dbg_ctrl &= ~0x7;
+       arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
+}
+
+int arm926ejs_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm926ejs_common_t **arm926ejs_p)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm7_9 = armv4_5->arch_info;
+       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm9tdmi = arm7_9->arch_info;
+       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm926ejs = arm9tdmi->arch_info;
+       if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       *armv4_5_p = armv4_5;
+       *arm7_9_p = arm7_9;
+       *arm9tdmi_p = arm9tdmi;
+       *arm926ejs_p = arm926ejs;
+       
+       return ERROR_OK;
+}
+
+int arm926ejs_arch_state(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+       
+       char *state[] = 
+       {
+               "disabled", "enabled"
+       };
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               ERROR("BUG: called for a non-ARMv4/5 target");
+               exit(-1);
+       }
+       
+       USER(
+                       "target halted in %s state due to %s, current mode: %s\n"
+                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"
+                       "MMU: %s, D-Cache: %s, I-Cache: %s",
+                        armv4_5_state_strings[armv4_5->core_state],
+                        target_debug_reason_strings[target->debug_reason],
+                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
+                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
+                        state[arm926ejs->armv4_5_mmu.mmu_enabled],
+                        state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], 
+                        state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
+       
+       return ERROR_OK;
+}
+
+int arm926ejs_soft_reset_halt(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+       
+       if (target->state == TARGET_RUNNING)
+       {
+               target->type->halt(target);
+       }
+       
+       while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
+       {
+               embeddedice_read_reg(dbg_stat);
+               jtag_execute_queue();
+       }
+       
+       target->state = TARGET_HALTED;
+       
+       /* SVC, ARM state, IRQ and FIQ disabled */
+       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+       
+       /* start fetching from 0x0 */
+       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+       armv4_5->core_cache->reg_list[15].dirty = 1;
+       armv4_5->core_cache->reg_list[15].valid = 1;
+       
+       armv4_5->core_mode = ARMV4_5_MODE_SVC;
+       armv4_5->core_state = ARMV4_5_STATE_ARM;
+       
+       arm926ejs_disable_mmu_caches(target, 1, 1, 1);
+       arm926ejs->armv4_5_mmu.mmu_enabled = 0;
+       arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+       arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+       
+       return ERROR_OK;
+}
+
+int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       int retval;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+       arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+       
+       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+               return retval;
+
+       /* If ICache is enabled, we have to invalidate affected ICache lines
+        * the DCache is forced to write-through, so we don't have to clean it here
+        */
+       if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+       {
+               if (count <= 1)
+               {
+                       /* invalidate ICache single entry with MVA */
+                       arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
+               }
+               else
+               {
+                       /* invalidate ICache */
+                       arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
+               }
+       }
+
+       return retval;
+}
+
+int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       arm9tdmi_init_target(cmd_ctx, target);
+               
+       return ERROR_OK;
+       
+}
+
+int arm926ejs_quit()
+{
+       
+       return ERROR_OK;
+}
+
+int arm926ejs_init_arch_info(target_t *target, arm926ejs_common_t *arm926ejs, int chain_pos, char *variant)
+{
+       arm9tdmi_common_t *arm9tdmi = &arm926ejs->arm9tdmi_common;
+       arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
+       
+       /* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
+        */
+       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+       arm9tdmi->arch_info = arm926ejs;
+       arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;
+       
+       arm7_9->post_debug_entry = arm926ejs_post_debug_entry;
+       arm7_9->pre_restore_context = arm926ejs_pre_restore_context;
+       
+       arm926ejs->read_cp15 = arm926ejs_cp15_read;
+       arm926ejs->write_cp15 = arm926ejs_cp15_write;
+       arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;
+       arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;
+       arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;
+       arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;
+       arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
+       arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
+       arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
+       arm926ejs->armv4_5_mmu.mmu_enabled = 0;
+       
+       arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;
+       
+       /* The ARM926EJ-S implements the ARMv5TE architecture which
+        * has the BKPT instruction, so we don't have to use a watchpoint comparator
+        */
+       arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
+       arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
+       
+       arm7_9->sw_bkpts_use_wp = 0;
+       arm7_9->sw_bkpts_enabled = 1;
+       
+       return ERROR_OK;
+}
+
+int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));
+       
+       if (argc < 4)
+       {
+               ERROR("'target arm926ejs' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+       
+       arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);
+
+       return ERROR_OK;
+}
+
+int arm926ejs_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       command_t *arm926ejs_cmd;
+       
+               
+       retval = arm9tdmi_register_commands(cmd_ctx);
+       
+       arm926ejs_cmd = register_command(cmd_ctx, NULL, "arm926ejs", NULL, COMMAND_ANY, "arm926ejs specific commands");
+
+       register_command(cmd_ctx, arm926ejs_cmd, "cp15", arm926ejs_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode_1> <opcode_2> <CRn> <CRm> [value]");
+       
+       register_command(cmd_ctx, arm926ejs_cmd, "cache_info", arm926ejs_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");
+       register_command(cmd_ctx, arm926ejs_cmd, "virt2phys", arm926ejs_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
+
+       register_command(cmd_ctx, arm926ejs_cmd, "mdw_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
+       register_command(cmd_ctx, arm926ejs_cmd, "mdh_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
+       register_command(cmd_ctx, arm926ejs_cmd, "mdb_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
+
+       register_command(cmd_ctx, arm926ejs_cmd, "mww_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
+       register_command(cmd_ctx, arm926ejs_cmd, "mwh_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
+       register_command(cmd_ctx, arm926ejs_cmd, "mwb_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
+
+       return ERROR_OK;
+}
+
+int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       int opcode_1;
+       int opcode_2;
+       int CRn;
+       int CRm;
+
+       if ((argc < 4) || (argc > 5))
+       {
+               command_print(cmd_ctx, "usage: arm926ejs cp15 <opcode_1> <opcode_2> <CRn> <CRm> [value]");
+               return ERROR_OK;
+       }
+       
+       opcode_1 = strtoul(args[0], NULL, 0);
+       opcode_2 = strtoul(args[1], NULL, 0);
+       CRn = strtoul(args[2], NULL, 0);
+       CRm = strtoul(args[3], NULL, 0);
+
+       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+               return ERROR_OK;
+       }
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       if (argc == 4)
+       {
+               u32 value;
+               if ((retval = arm926ejs->read_cp15(target, opcode_1, opcode_2, CRn, CRm, &value)) != ERROR_OK)
+               {
+                       command_print(cmd_ctx, "couldn't access register");
+                       return ERROR_OK;
+               }
+               jtag_execute_queue();
+               
+               command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);
+       }
+       else
+       {
+               u32 value = strtoul(args[4], NULL, 0);
+               if ((retval = arm926ejs->write_cp15(target, opcode_1, opcode_2, CRn, CRm, value)) != ERROR_OK)
+               {
+                       command_print(cmd_ctx, "couldn't access register");
+                       return ERROR_OK;
+               }
+               command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);
+       }
+
+       return ERROR_OK;
+}
+
+int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       
+       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+               return ERROR_OK;
+       }
+       
+       return armv4_5_handle_cache_info_command(cmd_ctx, &arm926ejs->armv4_5_mmu.armv4_5_cache);
+}
+
+int arm926ejs_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       arm_jtag_t *jtag_info;
+
+       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+               
+       return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
+}
+
+int arm926ejs_handle_md_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       arm_jtag_t *jtag_info;
+
+       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       return armv4_5_mmu_handle_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
+}
+
+int arm926ejs_handle_mw_phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{      
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       arm_jtag_t *jtag_info;
+
+       if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       
+       return armv4_5_mmu_handle_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
+}
+static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+       int retval;
+       int type;
+       u32 cb;
+       int domain;
+       u32 ap;
+       
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm926ejs_common_t *arm926ejs;
+       retval= arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs);
+       if (retval != ERROR_OK)
+       {
+               return retval;
+       }
+       u32 ret = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
+       if (type == -1)
+       {
+               return ret;
+       }
+       *physical = ret;
+       return ERROR_OK;
+}
+
+static int arm926ejs_mmu(struct target_s *target, int *enabled)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm926ejs_common_t *arm926ejs = armv4_5->arch_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               ERROR("Target not halted");
+               return ERROR_TARGET_INVALID;
+       }
+       *enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
+       return ERROR_OK;
+}
index 1ea2ce77cc97ecca94bc6a2939ac228856f3391c..4ba5d8526334f887e23abb4d11207bb2e49dc511 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm966e.h"\r
-\r
-#include "arm7_9_common.h"\r
-#include "register.h"\r
-#include "target.h"\r
-#include "armv4_5.h"\r
-#include "embeddedice.h"\r
-#include "log.h"\r
-#include "jtag.h"\r
-#include "arm_jtag.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-/* cli handling */\r
-int arm966e_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-/* forward declarations */\r
-int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm966e_quit(void);\r
-\r
-target_type_t arm966e_target =\r
-{\r
-       .name = "arm966e",\r
-\r
-       .poll = arm7_9_poll,\r
-       .arch_state = armv4_5_arch_state,\r
-\r
-       .target_request_data = arm7_9_target_request_data,\r
-\r
-       .halt = arm7_9_halt,\r
-       .resume = arm7_9_resume,\r
-       .step = arm7_9_step,\r
-\r
-       .assert_reset = arm7_9_assert_reset,\r
-       .deassert_reset = arm7_9_deassert_reset,\r
-       .soft_reset_halt = arm7_9_soft_reset_halt,\r
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
-\r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-\r
-       .read_memory = arm7_9_read_memory,\r
-       .write_memory = arm7_9_write_memory,\r
-       .bulk_write_memory = arm7_9_bulk_write_memory,\r
-       .checksum_memory = arm7_9_checksum_memory,\r
-       \r
-       .run_algorithm = armv4_5_run_algorithm,\r
-       \r
-       .add_breakpoint = arm7_9_add_breakpoint,\r
-       .remove_breakpoint = arm7_9_remove_breakpoint,\r
-       .add_watchpoint = arm7_9_add_watchpoint,\r
-       .remove_watchpoint = arm7_9_remove_watchpoint,\r
-\r
-       .register_commands = arm966e_register_commands,\r
-       .target_command = arm966e_target_command,\r
-       .init_target = arm966e_init_target,\r
-       .quit = arm966e_quit,\r
-};\r
-\r
-int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       arm9tdmi_init_target(cmd_ctx, target);\r
-               \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_quit(void)\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chain_pos, char *variant)\r
-{\r
-       arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;\r
-       arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;\r
-       \r
-       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);\r
-\r
-       arm9tdmi->arch_info = arm966e;\r
-       arm966e->common_magic = ARM966E_COMMON_MAGIC;\r
-       \r
-       /* The ARM966E-S implements the ARMv5TE architecture which\r
-        * has the BKPT instruction, so we don't have to use a watchpoint comparator\r
-        */\r
-       arm7_9->arm_bkpt = ARMV5_BKPT(0x0);\r
-       arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;\r
-       \r
-       arm7_9->sw_bkpts_use_wp = 0;\r
-       arm7_9->sw_bkpts_enabled = 1;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       arm966e_common_t *arm966e = malloc(sizeof(arm966e_common_t));\r
-       \r
-       if (argc < 4)\r
-       {\r
-               ERROR("'target arm966e' requires at least one additional argument");\r
-               exit(-1);\r
-       }\r
-       \r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-       \r
-       if (argc >= 5)\r
-               variant = args[4];\r
-       \r
-       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);\r
-       \r
-       arm966e_init_arch_info(target, arm966e, chain_pos, variant);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm966e_common_t **arm966e_p)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm966e_common_t *arm966e;\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm7_9 = armv4_5->arch_info;\r
-       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm9tdmi = arm7_9->arch_info;\r
-       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm966e = arm9tdmi->arch_info;\r
-       if (arm966e->common_magic != ARM966E_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       *armv4_5_p = armv4_5;\r
-       *arm7_9_p = arm7_9;\r
-       *arm9tdmi_p = arm9tdmi;\r
-       *arm966e_p = arm966e;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       scan_field_t fields[3];\r
-       u8 reg_addr_buf = reg_addr & 0x3f;\r
-       u8 nr_w_buf = 0;\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 6;\r
-       fields[1].out_value = &reg_addr_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = &nr_w_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       fields[0].in_handler_priv = value;\r
-       fields[0].in_handler = arm_jtag_buf_to_u32;\r
-\r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       jtag_execute_queue();\r
-       DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       scan_field_t fields[3];\r
-       u8 reg_addr_buf = reg_addr & 0x3f;\r
-       u8 nr_w_buf = 1;\r
-       u8 value_buf[4];\r
-       \r
-       buf_set_u32(value_buf, 0, 32, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0xf);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = value_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 6;\r
-       fields[1].out_value = &reg_addr_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = &nr_w_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       arm966e_common_t *arm966e;\r
-       arm_jtag_t *jtag_info;\r
-\r
-       if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM966e target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_info = &arm7_9->jtag_info;\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       /* one or more argument, access a single register (write if second argument is given */\r
-       if (argc >= 1)\r
-       {\r
-               int address = strtoul(args[0], NULL, 0);\r
-\r
-               if (argc == 1)\r
-               {\r
-                       u32 value;\r
-                       if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't access reg %i", address);\r
-                               return ERROR_OK;\r
-                       }\r
-                       jtag_execute_queue();\r
-                       \r
-                       command_print(cmd_ctx, "%i: %8.8x", address, value);\r
-               }\r
-               else if (argc == 2)\r
-               {\r
-                       u32 value = strtoul(args[1], NULL, 0);\r
-                       if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)\r
-                       {\r
-                               command_print(cmd_ctx, "couldn't access reg %i", address);\r
-                               return ERROR_OK;\r
-                       }\r
-                       command_print(cmd_ctx, "%i: %8.8x", address, value);\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int arm966e_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       command_t *arm966e_cmd;\r
-       \r
-       retval = arm9tdmi_register_commands(cmd_ctx);\r
-       arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");\r
-       register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");\r
-       \r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm966e.h"
+
+#include "arm7_9_common.h"
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "embeddedice.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm966e_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm966e_quit(void);
+
+target_type_t arm966e_target =
+{
+       .name = "arm966e",
+
+       .poll = arm7_9_poll,
+       .arch_state = armv4_5_arch_state,
+
+       .target_request_data = arm7_9_target_request_data,
+
+       .halt = arm7_9_halt,
+       .resume = arm7_9_resume,
+       .step = arm7_9_step,
+
+       .assert_reset = arm7_9_assert_reset,
+       .deassert_reset = arm7_9_deassert_reset,
+       .soft_reset_halt = arm7_9_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
+
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+       .read_memory = arm7_9_read_memory,
+       .write_memory = arm7_9_write_memory,
+       .bulk_write_memory = arm7_9_bulk_write_memory,
+       .checksum_memory = arm7_9_checksum_memory,
+       
+       .run_algorithm = armv4_5_run_algorithm,
+       
+       .add_breakpoint = arm7_9_add_breakpoint,
+       .remove_breakpoint = arm7_9_remove_breakpoint,
+       .add_watchpoint = arm7_9_add_watchpoint,
+       .remove_watchpoint = arm7_9_remove_watchpoint,
+
+       .register_commands = arm966e_register_commands,
+       .target_command = arm966e_target_command,
+       .init_target = arm966e_init_target,
+       .quit = arm966e_quit,
+};
+
+int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       arm9tdmi_init_target(cmd_ctx, target);
+               
+       return ERROR_OK;
+}
+
+int arm966e_quit(void)
+{
+       
+       return ERROR_OK;
+}
+
+int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chain_pos, char *variant)
+{
+       arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
+       arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
+       
+       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+       arm9tdmi->arch_info = arm966e;
+       arm966e->common_magic = ARM966E_COMMON_MAGIC;
+       
+       /* The ARM966E-S implements the ARMv5TE architecture which
+        * has the BKPT instruction, so we don't have to use a watchpoint comparator
+        */
+       arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
+       arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
+       
+       arm7_9->sw_bkpts_use_wp = 0;
+       arm7_9->sw_bkpts_enabled = 1;
+       
+       return ERROR_OK;
+}
+
+int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       arm966e_common_t *arm966e = malloc(sizeof(arm966e_common_t));
+       
+       if (argc < 4)
+       {
+               ERROR("'target arm966e' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+       
+       arm966e_init_arch_info(target, arm966e, chain_pos, variant);
+
+       return ERROR_OK;
+}
+
+int arm966e_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm966e_common_t **arm966e_p)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm966e_common_t *arm966e;
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm7_9 = armv4_5->arch_info;
+       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm9tdmi = arm7_9->arch_info;
+       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm966e = arm9tdmi->arch_info;
+       if (arm966e->common_magic != ARM966E_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       *armv4_5_p = armv4_5;
+       *arm7_9_p = arm7_9;
+       *arm9tdmi_p = arm9tdmi;
+       *arm966e_p = arm966e;
+       
+       return ERROR_OK;
+}
+
+int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       scan_field_t fields[3];
+       u8 reg_addr_buf = reg_addr & 0x3f;
+       u8 nr_w_buf = 0;
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 6;
+       fields[1].out_value = &reg_addr_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = &nr_w_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+       fields[0].in_handler_priv = value;
+       fields[0].in_handler = arm_jtag_buf_to_u32;
+
+       jtag_add_dr_scan(3, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       jtag_execute_queue();
+       DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
+#endif
+
+       return ERROR_OK;
+}
+
+int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       scan_field_t fields[3];
+       u8 reg_addr_buf = reg_addr & 0x3f;
+       u8 nr_w_buf = 1;
+       u8 value_buf[4];
+       
+       buf_set_u32(value_buf, 0, 32, value);
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0xf);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = value_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 6;
+       fields[1].out_value = &reg_addr_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = &nr_w_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
+#endif
+
+       return ERROR_OK;
+}
+
+int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       arm966e_common_t *arm966e;
+       arm_jtag_t *jtag_info;
+
+       if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM966e target");
+               return ERROR_OK;
+       }
+       
+       jtag_info = &arm7_9->jtag_info;
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       /* one or more argument, access a single register (write if second argument is given */
+       if (argc >= 1)
+       {
+               int address = strtoul(args[0], NULL, 0);
+
+               if (argc == 1)
+               {
+                       u32 value;
+                       if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't access reg %i", address);
+                               return ERROR_OK;
+                       }
+                       jtag_execute_queue();
+                       
+                       command_print(cmd_ctx, "%i: %8.8x", address, value);
+               }
+               else if (argc == 2)
+               {
+                       u32 value = strtoul(args[1], NULL, 0);
+                       if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
+                       {
+                               command_print(cmd_ctx, "couldn't access reg %i", address);
+                               return ERROR_OK;
+                       }
+                       command_print(cmd_ctx, "%i: %8.8x", address, value);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int arm966e_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       command_t *arm966e_cmd;
+       
+       retval = arm9tdmi_register_commands(cmd_ctx);
+       arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");
+       register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
+       
+       return ERROR_OK;
+}
index 7170693dc4b99eafc24fbb81cd1ebc971abc4e61..595790bc9529a5c6e51b17c2fece24ea997df012 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm9tdmi.h"\r
-\r
-#include "arm7_9_common.h"\r
-#include "register.h"\r
-#include "target.h"\r
-#include "armv4_5.h"\r
-#include "embeddedice.h"\r
-#include "etm.h"\r
-#include "etb.h"\r
-#include "log.h"\r
-#include "jtag.h"\r
-#include "arm_jtag.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#if 0\r
-#define _DEBUG_INSTRUCTION_EXECUTION_\r
-#endif\r
-\r
-/* cli handling */\r
-int arm9tdmi_register_commands(struct command_context_s *cmd_ctx);\r
-int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-/* forward declarations */\r
-int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int arm9tdmi_quit();\r
-               \r
-target_type_t arm9tdmi_target =\r
-{\r
-       .name = "arm9tdmi",\r
-\r
-       .poll = arm7_9_poll,\r
-       .arch_state = armv4_5_arch_state,\r
-\r
-       .target_request_data = arm7_9_target_request_data,\r
-\r
-       .halt = arm7_9_halt,\r
-       .resume = arm7_9_resume,\r
-       .step = arm7_9_step,\r
-\r
-       .assert_reset = arm7_9_assert_reset,\r
-       .deassert_reset = arm7_9_deassert_reset,\r
-       .soft_reset_halt = arm7_9_soft_reset_halt,\r
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,\r
-\r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-\r
-       .read_memory = arm7_9_read_memory,\r
-       .write_memory = arm7_9_write_memory,\r
-       .bulk_write_memory = arm7_9_bulk_write_memory,\r
-       .checksum_memory = arm7_9_checksum_memory,\r
-       \r
-       .run_algorithm = armv4_5_run_algorithm,\r
-       \r
-       .add_breakpoint = arm7_9_add_breakpoint,\r
-       .remove_breakpoint = arm7_9_remove_breakpoint,\r
-       .add_watchpoint = arm7_9_add_watchpoint,\r
-       .remove_watchpoint = arm7_9_remove_watchpoint,\r
-\r
-       .register_commands = arm9tdmi_register_commands,\r
-       .target_command = arm9tdmi_target_command,\r
-       .init_target = arm9tdmi_init_target,\r
-       .quit = arm9tdmi_quit\r
-};\r
-\r
-arm9tdmi_vector_t arm9tdmi_vectors[] =\r
-{\r
-       {"reset", ARM9TDMI_RESET_VECTOR},\r
-       {"undef", ARM9TDMI_UNDEF_VECTOR},\r
-       {"swi", ARM9TDMI_SWI_VECTOR},\r
-       {"pabt", ARM9TDMI_PABT_VECTOR},\r
-       {"dabt", ARM9TDMI_DABT_VECTOR},\r
-       {"reserved", ARM9TDMI_RESERVED_VECTOR},\r
-       {"irq", ARM9TDMI_IRQ_VECTOR},\r
-       {"fiq", ARM9TDMI_FIQ_VECTOR},\r
-       {0, 0},\r
-};\r
-\r
-int arm9tdmi_examine_debug_reason(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       \r
-       /* only check the debug reason if we don't know it already */\r
-       if ((target->debug_reason != DBG_REASON_DBGRQ)\r
-                       && (target->debug_reason != DBG_REASON_SINGLESTEP))\r
-       {\r
-               scan_field_t fields[3];\r
-               u8 databus[4];\r
-               u8 instructionbus[4];\r
-               u8 debug_reason;\r
-\r
-               jtag_add_end_state(TAP_PD);\r
-\r
-               fields[0].device = arm7_9->jtag_info.chain_pos;\r
-               fields[0].num_bits = 32;\r
-               fields[0].out_value = NULL;\r
-               fields[0].out_mask = NULL;\r
-               fields[0].in_value = databus;\r
-               fields[0].in_check_value = NULL;\r
-               fields[0].in_check_mask = NULL;\r
-               fields[0].in_handler = NULL;\r
-               fields[0].in_handler_priv = NULL;\r
-               \r
-               fields[1].device = arm7_9->jtag_info.chain_pos;\r
-               fields[1].num_bits = 3;\r
-               fields[1].out_value = NULL;\r
-               fields[1].out_mask = NULL;\r
-               fields[1].in_value = &debug_reason;\r
-               fields[1].in_check_value = NULL;\r
-               fields[1].in_check_mask = NULL;\r
-               fields[1].in_handler = NULL;\r
-               fields[1].in_handler_priv = NULL;\r
-               \r
-               fields[2].device = arm7_9->jtag_info.chain_pos;\r
-               fields[2].num_bits = 32;\r
-               fields[2].out_value = NULL;\r
-               fields[2].out_mask = NULL;\r
-               fields[2].in_value = instructionbus;\r
-               fields[2].in_check_value = NULL;\r
-               fields[2].in_check_mask = NULL;\r
-               fields[2].in_handler = NULL;\r
-               fields[2].in_handler_priv = NULL;\r
-               \r
-               arm_jtag_scann(&arm7_9->jtag_info, 0x1);\r
-               arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);\r
-\r
-               jtag_add_dr_scan(3, fields, TAP_PD);\r
-               jtag_execute_queue();\r
-               \r
-               fields[0].in_value = NULL;\r
-               fields[0].out_value = databus;\r
-               fields[1].in_value = NULL;\r
-               fields[1].out_value = &debug_reason;\r
-               fields[2].in_value = NULL;\r
-               fields[2].out_value = instructionbus;\r
-               \r
-               jtag_add_dr_scan(3, fields, TAP_PD);\r
-\r
-               if (debug_reason & 0x4)\r
-                       if (debug_reason & 0x2)\r
-                               target->debug_reason = DBG_REASON_WPTANDBKPT;\r
-               else\r
-                       target->debug_reason = DBG_REASON_WATCHPOINT;\r
-               else\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* put an instruction in the ARM9TDMI pipeline or write the data bus, and optionally read data */\r
-int arm9tdmi_clock_out(arm_jtag_t *jtag_info, u32 instr, u32 out, u32 *in, int sysspeed)\r
-{\r
-       scan_field_t fields[3];\r
-       u8 out_buf[4];\r
-       u8 instr_buf[4];\r
-       u8 sysspeed_buf = 0x0;\r
-       \r
-       /* prepare buffer */\r
-       buf_set_u32(out_buf, 0, 32, out);\r
-       \r
-       buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));\r
-       \r
-       if (sysspeed)\r
-               buf_set_u32(&sysspeed_buf, 2, 1, 1);\r
-       \r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0x1);\r
-       \r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-               \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = out_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       if (in)\r
-       {\r
-               fields[0].in_handler = arm_jtag_buf_to_u32;\r
-               fields[0].in_handler_priv = in;\r
-       }\r
-       else\r
-       {\r
-               fields[0].in_handler = NULL;\r
-               fields[0].in_handler_priv = NULL;\r
-       }\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 3;\r
-       fields[1].out_value = &sysspeed_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-               \r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 32;\r
-       fields[2].out_value = instr_buf;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       jtag_add_runtest(0, -1);\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       {\r
-               jtag_execute_queue();\r
-               \r
-               if (in)\r
-               {\r
-                       DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);\r
-               }\r
-               else\r
-                       DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);\r
-       }\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* just read data (instruction and data-out = don't care) */\r
-int arm9tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)\r
-{\r
-       scan_field_t fields[3];\r
-\r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0x1);\r
-       \r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-               \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_handler = arm_jtag_buf_to_u32;\r
-       fields[0].in_handler_priv = in;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 3;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 32;\r
-       fields[2].out_value = NULL;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       jtag_add_runtest(0, -1);\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       {\r
-               jtag_execute_queue();\r
-                       \r
-               if (in)\r
-               {\r
-                       DEBUG("in: 0x%8.8x", *in);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: called with in == NULL");\r
-               }\r
-       }\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* clock the target, and read the databus\r
- * the *in pointer points to a buffer where elements of 'size' bytes\r
- * are stored in big (be==1) or little (be==0) endianness\r
- */\r
-int arm9tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)\r
-{\r
-       scan_field_t fields[3];\r
-       \r
-       jtag_add_end_state(TAP_PD);\r
-       arm_jtag_scann(jtag_info, 0x1);\r
-       \r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-               \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       switch (size)\r
-       {\r
-               case 4:\r
-                       fields[0].in_handler = (be) ? arm_jtag_buf_to_be32 : arm_jtag_buf_to_le32;\r
-                       break;\r
-               case 2:\r
-                       fields[0].in_handler = (be) ? arm_jtag_buf_to_be16 : arm_jtag_buf_to_le16;\r
-                       break;\r
-               case 1:\r
-                       fields[0].in_handler = arm_jtag_buf_to_8;\r
-                       break;\r
-       }\r
-       fields[0].in_handler_priv = in;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 3;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 32;\r
-       fields[2].out_value = NULL;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       jtag_add_runtest(0, -1);\r
-       \r
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_\r
-       {\r
-               jtag_execute_queue();\r
-                       \r
-               if (in)\r
-               {\r
-                       DEBUG("in: 0x%8.8x", *in);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: called with in == NULL");\r
-               }\r
-       }\r
-#endif\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void arm9tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* save r0 before using it and put system in ARM state \r
-        * to allow common handling of ARM and THUMB debugging */\r
-       \r
-       /* fetch STR r0, [r0] */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* STR r0, [r0] in Memory */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);\r
-\r
-       /* MOV r0, r15 fetched, STR in Decode */        \r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* nothing fetched, STR r0, [r0] in Memory */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);\r
-\r
-       /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);\r
-       /* LDR in Decode */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* LDR in Execute */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* LDR in Memory (to account for interlock) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-\r
-       /* fetch BX */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);\r
-       /* NOP fetched, BX in Decode, MOV in Execute */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* NOP fetched, BX in Execute (1) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       \r
-       jtag_execute_queue();\r
-       \r
-       /* fix program counter:\r
-        * MOV r0, r15 was the 5th instruction (+8)\r
-        * reading PC in Thumb state gives address of instruction + 4\r
-        */\r
-       *pc -= 0xc;\r
-}\r
-\r
-void arm9tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])\r
-{\r
-       int i;\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       /* STMIA r0-15, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);\r
-\r
-       /* fetch NOP, STM in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, STM in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-       for (i = 0; i <= 15; i++)\r
-       {\r
-               if (mask & (1 << i))\r
-                       /* nothing fetched, STM in MEMORY (i'th cycle) */\r
-                       arm9tdmi_clock_data_in(jtag_info, core_regs[i]);\r
-       }\r
-\r
-}\r
-\r
-void arm9tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)\r
-{\r
-       int i;\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;\r
-       u32 *buf_u32 = buffer;\r
-       u16 *buf_u16 = buffer;\r
-       u8 *buf_u8 = buffer;\r
-       \r
-       /* STMIA r0-15, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);\r
-\r
-       /* fetch NOP, STM in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, STM in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-       for (i = 0; i <= 15; i++)\r
-       {\r
-               if (mask & (1 << i))\r
-                       /* nothing fetched, STM in MEMORY (i'th cycle) */\r
-                       switch (size)\r
-                       {\r
-                               case 4:\r
-                                       arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);\r
-                                       break;\r
-                               case 2:\r
-                                       arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);\r
-                                       break;\r
-                               case 1:\r
-                                       arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);\r
-                                       break;\r
-                       }\r
-       }\r
-\r
-}\r
-\r
-void arm9tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       /* MRS r0, cpsr */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-       /* STR r0, [r15] */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);\r
-       /* fetch NOP, STR in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, STR in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, STR in MEMORY */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);\r
-\r
-}\r
-\r
-void arm9tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);\r
-\r
-       /* MSR1 fetched */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);\r
-       /* MSR2 fetched, MSR1 in DECODE */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);\r
-       /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);\r
-       /* nothing fetched, MSR1 in EXECUTE (2) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, MSR1 in EXECUTE (3) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);\r
-       /* nothing fetched, MSR2 in EXECUTE (2) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, MSR2 in EXECUTE (3) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, MSR3 in EXECUTE (2) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, MSR3 in EXECUTE (3) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* NOP fetched, MSR4 in EXECUTE (1) */\r
-       /* last MSR writes flags, which takes only one cycle */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-}\r
-\r
-void arm9tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);\r
-       \r
-       /* MSR fetched */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);\r
-       /* NOP fetched, MSR in DECODE */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* NOP fetched, MSR in EXECUTE (1) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       \r
-       /* rot == 4 writes flags, which takes only one cycle */\r
-       if (rot != 4)\r
-       {\r
-               /* nothing fetched, MSR in EXECUTE (2) */\r
-               arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-               /* nothing fetched, MSR in EXECUTE (3) */\r
-               arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       }\r
-}\r
-\r
-void arm9tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])\r
-{\r
-       int i;\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-               \r
-       /* LDMIA r0-15, [r0] at debug speed\r
-       * register values will start to appear on 4th DCLK\r
-       */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);\r
-\r
-       /* fetch NOP, LDM in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-       for (i = 0; i <= 15; i++)\r
-       {\r
-               if (mask & (1 << i))\r
-                       /* nothing fetched, LDM still in EXECUTE (1+i cycle) */\r
-                       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);\r
-       }\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       \r
-}\r
-\r
-void arm9tdmi_load_word_regs(target_t *target, u32 mask)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed load-multiple into the pipeline */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-\r
-}\r
-\r
-void arm9tdmi_load_hword_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* put system-speed load half-word into the pipeline */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-}\r
-\r
-void arm9tdmi_load_byte_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed load byte into the pipeline */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-\r
-}\r
-\r
-void arm9tdmi_store_word_regs(target_t *target, u32 mask)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed store-multiple into the pipeline */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-\r
-}\r
-\r
-void arm9tdmi_store_hword_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed store half-word into the pipeline */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-\r
-}\r
-\r
-void arm9tdmi_store_byte_reg(target_t *target, int num)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       /* put system-speed store byte into the pipeline */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-\r
-}\r
-\r
-void arm9tdmi_write_pc(target_t *target, u32 pc)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       /* LDMIA r0-15, [r0] at debug speed\r
-        * register values will start to appear on 4th DCLK\r
-        */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);\r
-\r
-       /* fetch NOP, LDM in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (4th cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (5th cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-}\r
-\r
-void arm9tdmi_branch_resume(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       \r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);\r
-\r
-}\r
-\r
-void arm9tdmi_branch_resume_thumb(target_t *target)\r
-{\r
-       DEBUG("-");\r
-       \r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];\r
-\r
-       /* LDMIA r0-15, [r0] at debug speed\r
-       * register values will start to appear on 4th DCLK\r
-       */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);\r
-\r
-       /* fetch NOP, LDM in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);\r
-       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-       /* Branch and eXchange */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);\r
-       \r
-       embeddedice_read_reg(dbg_stat);\r
-       \r
-       /* fetch NOP, BX in DECODE stage */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-       \r
-       embeddedice_read_reg(dbg_stat);\r
-       \r
-       /* fetch NOP, BX in EXECUTE stage (1st cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);\r
-\r
-       /* target is now in Thumb state */\r
-       embeddedice_read_reg(dbg_stat);\r
-\r
-       /* load r0 value, MOV_IM in Decode*/\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);\r
-       /* fetch NOP, LDR in Decode, MOV_IM in Execute */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* fetch NOP, LDR in Execute */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);\r
-       /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       \r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-\r
-       embeddedice_read_reg(dbg_stat);\r
-       \r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);\r
-       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);\r
-\r
-}\r
-\r
-void arm9tdmi_enable_single_step(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       \r
-       if (arm7_9->has_single_step)\r
-       {\r
-               buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);\r
-               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);\r
-       }\r
-       else\r
-       {\r
-               arm7_9_enable_eice_step(target);\r
-       }\r
-}\r
-\r
-void arm9tdmi_disable_single_step(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       \r
-       if (arm7_9->has_single_step)\r
-       {\r
-               buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);\r
-               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);\r
-       }\r
-       else\r
-       {\r
-               arm7_9_disable_eice_step(target);\r
-       }\r
-}\r
-\r
-void arm9tdmi_build_reg_cache(target_t *target)\r
-{\r
-       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-\r
-       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);\r
-       armv4_5->core_cache = (*cache_p);\r
-       \r
-       /* one extra register (vector catch) */\r
-       (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);\r
-       arm7_9->eice_cache = (*cache_p)->next;\r
-\r
-       if (arm7_9->etm_ctx)\r
-       {\r
-               (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);\r
-               arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;\r
-       }\r
-}\r
-\r
-int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       \r
-       arm9tdmi_build_reg_cache(target);\r
-       \r
-       return ERROR_OK;\r
-       \r
-}\r
-\r
-int arm9tdmi_quit()\r
-{\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int chain_pos, char *variant)\r
-{\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       \r
-       arm7_9 = &arm9tdmi->arm7_9_common;\r
-       armv4_5 = &arm7_9->armv4_5_common;\r
-       \r
-       /* prepare JTAG information for the new target */\r
-       arm7_9->jtag_info.chain_pos = chain_pos;\r
-       arm7_9->jtag_info.scann_size = 5;\r
-       \r
-       /* register arch-specific functions */\r
-       arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;\r
-       arm7_9->change_to_arm = arm9tdmi_change_to_arm;\r
-       arm7_9->read_core_regs = arm9tdmi_read_core_regs;\r
-       arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;\r
-       arm7_9->read_xpsr = arm9tdmi_read_xpsr;\r
-       \r
-       arm7_9->write_xpsr = arm9tdmi_write_xpsr;\r
-       arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;\r
-       arm7_9->write_core_regs = arm9tdmi_write_core_regs;\r
-       \r
-       arm7_9->load_word_regs = arm9tdmi_load_word_regs;\r
-       arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;\r
-       arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;\r
-       \r
-       arm7_9->store_word_regs = arm9tdmi_store_word_regs;\r
-       arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;\r
-       arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;\r
-       \r
-       arm7_9->write_pc = arm9tdmi_write_pc;\r
-       arm7_9->branch_resume = arm9tdmi_branch_resume;\r
-       arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;\r
-\r
-       arm7_9->enable_single_step = arm9tdmi_enable_single_step;\r
-       arm7_9->disable_single_step = arm9tdmi_disable_single_step;\r
-       \r
-       arm7_9->pre_debug_entry = NULL;\r
-       arm7_9->post_debug_entry = NULL;\r
-       \r
-       arm7_9->pre_restore_context = NULL;\r
-       arm7_9->post_restore_context = NULL;\r
-\r
-       /* initialize arch-specific breakpoint handling */\r
-       arm7_9->arm_bkpt = 0xdeeedeee;\r
-       arm7_9->thumb_bkpt = 0xdeee;\r
-       \r
-       arm7_9->sw_bkpts_use_wp = 1;\r
-       arm7_9->sw_bkpts_enabled = 0;\r
-       arm7_9->dbgreq_adjust_pc = 3;\r
-       arm7_9->arch_info = arm9tdmi;\r
-       \r
-       arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC;\r
-       arm9tdmi->arch_info = NULL;\r
-\r
-       if (variant)\r
-       {\r
-               arm9tdmi->variant = strdup(variant);\r
-       }\r
-       else\r
-       {\r
-               arm9tdmi->variant = strdup("");\r
-       }\r
-       \r
-       arm7_9_init_arch_info(target, arm7_9);\r
-\r
-       /* override use of DBGRQ, this is safe on ARM9TDMI */\r
-       arm7_9->use_dbgrq = 1;\r
-\r
-       /* all ARM9s have the vector catch register */\r
-       arm7_9->has_vector_catch = 1;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm9tdmi_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       \r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm7_9 = armv4_5->arch_info;\r
-       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       arm9tdmi = arm7_9->arch_info;\r
-       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       *armv4_5_p = armv4_5;\r
-       *arm7_9_p = arm7_9;\r
-       *arm9tdmi_p = arm9tdmi;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-/* target arm9tdmi <endianess> <startup_mode> <chain_pos> <variant>*/\r
-int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       arm9tdmi_common_t *arm9tdmi = malloc(sizeof(arm9tdmi_common_t));\r
-\r
-       if (argc < 4)\r
-       {\r
-               ERROR("'target arm9tdmi' requires at least one additional argument");\r
-               exit(-1);\r
-       }\r
-       \r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-       \r
-       if (argc >= 5)\r
-               variant = args[4];\r
-       \r
-       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm9tdmi_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       \r
-       command_t *arm9tdmi_cmd;\r
-       \r
-               \r
-       retval = arm7_9_register_commands(cmd_ctx);\r
-       \r
-       arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9tdmi", NULL, COMMAND_ANY, "arm9tdmi specific commands");\r
-\r
-       register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch", handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC, "catch arm920t vectors ['all'|'none'|'<vec1 vec2 ...>']");\r
-       \r
-       \r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       arm9tdmi_common_t *arm9tdmi;\r
-       reg_t *vector_catch;\r
-       u32 vector_catch_value;\r
-       int i, j;\r
-       \r
-       if (arm9tdmi_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM9TDMI based target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];\r
-       \r
-       /* read the vector catch register if necessary */\r
-       if (!vector_catch->valid)\r
-               embeddedice_read_reg(vector_catch);\r
-       \r
-       /* get the current setting */\r
-       vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);\r
-       \r
-       if (argc > 0)\r
-       {\r
-               vector_catch_value = 0x0;\r
-               if (strcmp(args[0], "all") == 0)\r
-               {\r
-                       vector_catch_value = 0xdf;\r
-               }\r
-               else if (strcmp(args[0], "none") == 0)\r
-               {\r
-                       /* do nothing */\r
-               }\r
-               else\r
-               {\r
-                       for (i = 0; i < argc; i++)\r
-                       {\r
-                               /* go through list of vectors */\r
-                               for(j = 0; arm9tdmi_vectors[j].name; j++)\r
-                               {\r
-                                       if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)\r
-                                       {\r
-                                               vector_catch_value |= arm9tdmi_vectors[j].value;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               \r
-                               /* complain if vector wasn't found */\r
-                               if (!arm9tdmi_vectors[j].name)\r
-                               {\r
-                                       command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);\r
-                                       \r
-                                       /* reread current setting */\r
-                                       vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);\r
-                                       \r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               /* store new settings */\r
-               buf_set_u32(vector_catch->value, 0, 32, vector_catch_value);\r
-               embeddedice_store_reg(vector_catch);\r
-       }\r
-               \r
-       /* output current settings (skip RESERVED vector) */\r
-       for (i = 0; i < 8; i++)\r
-       {\r
-               if (i != 5)\r
-               {\r
-                       command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,\r
-                               (vector_catch_value & (1 << i)) ? "catch" : "don't catch");\r
-               }  \r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm9tdmi.h"
+
+#include "arm7_9_common.h"
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "embeddedice.h"
+#include "etm.h"
+#include "etb.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm9tdmi_register_commands(struct command_context_s *cmd_ctx);
+int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm9tdmi_quit();
+               
+target_type_t arm9tdmi_target =
+{
+       .name = "arm9tdmi",
+
+       .poll = arm7_9_poll,
+       .arch_state = armv4_5_arch_state,
+
+       .target_request_data = arm7_9_target_request_data,
+
+       .halt = arm7_9_halt,
+       .resume = arm7_9_resume,
+       .step = arm7_9_step,
+
+       .assert_reset = arm7_9_assert_reset,
+       .deassert_reset = arm7_9_deassert_reset,
+       .soft_reset_halt = arm7_9_soft_reset_halt,
+       .prepare_reset_halt = arm7_9_prepare_reset_halt,
+
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+       .read_memory = arm7_9_read_memory,
+       .write_memory = arm7_9_write_memory,
+       .bulk_write_memory = arm7_9_bulk_write_memory,
+       .checksum_memory = arm7_9_checksum_memory,
+       
+       .run_algorithm = armv4_5_run_algorithm,
+       
+       .add_breakpoint = arm7_9_add_breakpoint,
+       .remove_breakpoint = arm7_9_remove_breakpoint,
+       .add_watchpoint = arm7_9_add_watchpoint,
+       .remove_watchpoint = arm7_9_remove_watchpoint,
+
+       .register_commands = arm9tdmi_register_commands,
+       .target_command = arm9tdmi_target_command,
+       .init_target = arm9tdmi_init_target,
+       .quit = arm9tdmi_quit
+};
+
+arm9tdmi_vector_t arm9tdmi_vectors[] =
+{
+       {"reset", ARM9TDMI_RESET_VECTOR},
+       {"undef", ARM9TDMI_UNDEF_VECTOR},
+       {"swi", ARM9TDMI_SWI_VECTOR},
+       {"pabt", ARM9TDMI_PABT_VECTOR},
+       {"dabt", ARM9TDMI_DABT_VECTOR},
+       {"reserved", ARM9TDMI_RESERVED_VECTOR},
+       {"irq", ARM9TDMI_IRQ_VECTOR},
+       {"fiq", ARM9TDMI_FIQ_VECTOR},
+       {0, 0},
+};
+
+int arm9tdmi_examine_debug_reason(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       
+       /* only check the debug reason if we don't know it already */
+       if ((target->debug_reason != DBG_REASON_DBGRQ)
+                       && (target->debug_reason != DBG_REASON_SINGLESTEP))
+       {
+               scan_field_t fields[3];
+               u8 databus[4];
+               u8 instructionbus[4];
+               u8 debug_reason;
+
+               jtag_add_end_state(TAP_PD);
+
+               fields[0].device = arm7_9->jtag_info.chain_pos;
+               fields[0].num_bits = 32;
+               fields[0].out_value = NULL;
+               fields[0].out_mask = NULL;
+               fields[0].in_value = databus;
+               fields[0].in_check_value = NULL;
+               fields[0].in_check_mask = NULL;
+               fields[0].in_handler = NULL;
+               fields[0].in_handler_priv = NULL;
+               
+               fields[1].device = arm7_9->jtag_info.chain_pos;
+               fields[1].num_bits = 3;
+               fields[1].out_value = NULL;
+               fields[1].out_mask = NULL;
+               fields[1].in_value = &debug_reason;
+               fields[1].in_check_value = NULL;
+               fields[1].in_check_mask = NULL;
+               fields[1].in_handler = NULL;
+               fields[1].in_handler_priv = NULL;
+               
+               fields[2].device = arm7_9->jtag_info.chain_pos;
+               fields[2].num_bits = 32;
+               fields[2].out_value = NULL;
+               fields[2].out_mask = NULL;
+               fields[2].in_value = instructionbus;
+               fields[2].in_check_value = NULL;
+               fields[2].in_check_mask = NULL;
+               fields[2].in_handler = NULL;
+               fields[2].in_handler_priv = NULL;
+               
+               arm_jtag_scann(&arm7_9->jtag_info, 0x1);
+               arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
+
+               jtag_add_dr_scan(3, fields, TAP_PD);
+               jtag_execute_queue();
+               
+               fields[0].in_value = NULL;
+               fields[0].out_value = databus;
+               fields[1].in_value = NULL;
+               fields[1].out_value = &debug_reason;
+               fields[2].in_value = NULL;
+               fields[2].out_value = instructionbus;
+               
+               jtag_add_dr_scan(3, fields, TAP_PD);
+
+               if (debug_reason & 0x4)
+                       if (debug_reason & 0x2)
+                               target->debug_reason = DBG_REASON_WPTANDBKPT;
+               else
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+               else
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+       }
+
+       return ERROR_OK;
+}
+
+/* put an instruction in the ARM9TDMI pipeline or write the data bus, and optionally read data */
+int arm9tdmi_clock_out(arm_jtag_t *jtag_info, u32 instr, u32 out, u32 *in, int sysspeed)
+{
+       scan_field_t fields[3];
+       u8 out_buf[4];
+       u8 instr_buf[4];
+       u8 sysspeed_buf = 0x0;
+       
+       /* prepare buffer */
+       buf_set_u32(out_buf, 0, 32, out);
+       
+       buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
+       
+       if (sysspeed)
+               buf_set_u32(&sysspeed_buf, 2, 1, 1);
+       
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+               
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = out_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       if (in)
+       {
+               fields[0].in_handler = arm_jtag_buf_to_u32;
+               fields[0].in_handler_priv = in;
+       }
+       else
+       {
+               fields[0].in_handler = NULL;
+               fields[0].in_handler_priv = NULL;
+       }
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 3;
+       fields[1].out_value = &sysspeed_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+               
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 32;
+       fields[2].out_value = instr_buf;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       jtag_add_dr_scan(3, fields, -1);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       {
+               jtag_execute_queue();
+               
+               if (in)
+               {
+                       DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
+               }
+               else
+                       DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
+       }
+#endif
+
+       return ERROR_OK;
+}
+
+/* just read data (instruction and data-out = don't care) */
+int arm9tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
+{
+       scan_field_t fields[3];
+
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+               
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_handler = arm_jtag_buf_to_u32;
+       fields[0].in_handler_priv = in;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 3;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 32;
+       fields[2].out_value = NULL;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       {
+               jtag_execute_queue();
+                       
+               if (in)
+               {
+                       DEBUG("in: 0x%8.8x", *in);
+               }
+               else
+               {
+                       ERROR("BUG: called with in == NULL");
+               }
+       }
+#endif
+
+       return ERROR_OK;
+}
+
+/* clock the target, and read the databus
+ * the *in pointer points to a buffer where elements of 'size' bytes
+ * are stored in big (be==1) or little (be==0) endianness
+ */
+int arm9tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
+{
+       scan_field_t fields[3];
+       
+       jtag_add_end_state(TAP_PD);
+       arm_jtag_scann(jtag_info, 0x1);
+       
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+               
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       switch (size)
+       {
+               case 4:
+                       fields[0].in_handler = (be) ? arm_jtag_buf_to_be32 : arm_jtag_buf_to_le32;
+                       break;
+               case 2:
+                       fields[0].in_handler = (be) ? arm_jtag_buf_to_be16 : arm_jtag_buf_to_le16;
+                       break;
+               case 1:
+                       fields[0].in_handler = arm_jtag_buf_to_8;
+                       break;
+       }
+       fields[0].in_handler_priv = in;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 3;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 32;
+       fields[2].out_value = NULL;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+       jtag_add_runtest(0, -1);
+       
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+       {
+               jtag_execute_queue();
+                       
+               if (in)
+               {
+                       DEBUG("in: 0x%8.8x", *in);
+               }
+               else
+               {
+                       ERROR("BUG: called with in == NULL");
+               }
+       }
+#endif
+
+       return ERROR_OK;
+}
+
+void arm9tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       /* save r0 before using it and put system in ARM state 
+        * to allow common handling of ARM and THUMB debugging */
+       
+       /* fetch STR r0, [r0] */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* STR r0, [r0] in Memory */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
+
+       /* MOV r0, r15 fetched, STR in Decode */        
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* nothing fetched, STR r0, [r0] in Memory */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
+
+       /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
+       /* LDR in Decode */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* LDR in Execute */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* LDR in Memory (to account for interlock) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+
+       /* fetch BX */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
+       /* NOP fetched, BX in Decode, MOV in Execute */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* NOP fetched, BX in Execute (1) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       
+       jtag_execute_queue();
+       
+       /* fix program counter:
+        * MOV r0, r15 was the 5th instruction (+8)
+        * reading PC in Thumb state gives address of instruction + 4
+        */
+       *pc -= 0xc;
+}
+
+void arm9tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       /* STMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
+
+       /* fetch NOP, STM in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, STM in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               if (mask & (1 << i))
+                       /* nothing fetched, STM in MEMORY (i'th cycle) */
+                       arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
+       }
+
+}
+
+void arm9tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
+       u32 *buf_u32 = buffer;
+       u16 *buf_u16 = buffer;
+       u8 *buf_u8 = buffer;
+       
+       /* STMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
+
+       /* fetch NOP, STM in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, STM in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               if (mask & (1 << i))
+                       /* nothing fetched, STM in MEMORY (i'th cycle) */
+                       switch (size)
+                       {
+                               case 4:
+                                       arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+                                       break;
+                               case 2:
+                                       arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+                                       break;
+                               case 1:
+                                       arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+                                       break;
+                       }
+       }
+
+}
+
+void arm9tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       /* MRS r0, cpsr */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       /* STR r0, [r15] */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
+       /* fetch NOP, STR in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, STR in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, STR in MEMORY */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
+
+}
+
+void arm9tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
+
+       /* MSR1 fetched */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
+       /* MSR2 fetched, MSR1 in DECODE */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
+       /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
+       /* nothing fetched, MSR1 in EXECUTE (2) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, MSR1 in EXECUTE (3) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
+       /* nothing fetched, MSR2 in EXECUTE (2) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, MSR2 in EXECUTE (3) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, MSR3 in EXECUTE (2) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, MSR3 in EXECUTE (3) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* NOP fetched, MSR4 in EXECUTE (1) */
+       /* last MSR writes flags, which takes only one cycle */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+}
+
+void arm9tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
+       
+       /* MSR fetched */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
+       /* NOP fetched, MSR in DECODE */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* NOP fetched, MSR in EXECUTE (1) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       
+       /* rot == 4 writes flags, which takes only one cycle */
+       if (rot != 4)
+       {
+               /* nothing fetched, MSR in EXECUTE (2) */
+               arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+               /* nothing fetched, MSR in EXECUTE (3) */
+               arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       }
+}
+
+void arm9tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
+{
+       int i;
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+               
+       /* LDMIA r0-15, [r0] at debug speed
+       * register values will start to appear on 4th DCLK
+       */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
+
+       /* fetch NOP, LDM in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       for (i = 0; i <= 15; i++)
+       {
+               if (mask & (1 << i))
+                       /* nothing fetched, LDM still in EXECUTE (1+i cycle) */
+                       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
+       }
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       
+}
+
+void arm9tdmi_load_word_regs(target_t *target, u32 mask)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed load-multiple into the pipeline */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_load_hword_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       /* put system-speed load half-word into the pipeline */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+}
+
+void arm9tdmi_load_byte_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed load byte into the pipeline */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_store_word_regs(target_t *target, u32 mask)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed store-multiple into the pipeline */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_store_hword_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed store half-word into the pipeline */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_store_byte_reg(target_t *target, int num)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       /* put system-speed store byte into the pipeline */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_write_pc(target_t *target, u32 pc)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       /* LDMIA r0-15, [r0] at debug speed
+        * register values will start to appear on 4th DCLK
+        */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
+
+       /* fetch NOP, LDM in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+}
+
+void arm9tdmi_branch_resume(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_branch_resume_thumb(target_t *target)
+{
+       DEBUG("-");
+       
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+
+       /* LDMIA r0-15, [r0] at debug speed
+       * register values will start to appear on 4th DCLK
+       */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
+
+       /* fetch NOP, LDM in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
+       /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       /* Branch and eXchange */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
+       
+       embeddedice_read_reg(dbg_stat);
+       
+       /* fetch NOP, BX in DECODE stage */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+       
+       embeddedice_read_reg(dbg_stat);
+       
+       /* fetch NOP, BX in EXECUTE stage (1st cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+       /* target is now in Thumb state */
+       embeddedice_read_reg(dbg_stat);
+
+       /* load r0 value, MOV_IM in Decode*/
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
+       /* fetch NOP, LDR in Decode, MOV_IM in Execute */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* fetch NOP, LDR in Execute */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
+       /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+
+       embeddedice_read_reg(dbg_stat);
+       
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
+       arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+
+}
+
+void arm9tdmi_enable_single_step(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       
+       if (arm7_9->has_single_step)
+       {
+               buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
+               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
+       }
+       else
+       {
+               arm7_9_enable_eice_step(target);
+       }
+}
+
+void arm9tdmi_disable_single_step(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       
+       if (arm7_9->has_single_step)
+       {
+               buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
+               embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
+       }
+       else
+       {
+               arm7_9_disable_eice_step(target);
+       }
+}
+
+void arm9tdmi_build_reg_cache(target_t *target)
+{
+       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+       armv4_5->core_cache = (*cache_p);
+       
+       /* one extra register (vector catch) */
+       (*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
+       arm7_9->eice_cache = (*cache_p)->next;
+
+       if (arm7_9->etm_ctx)
+       {
+               (*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
+               arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
+       }
+}
+
+int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       
+       arm9tdmi_build_reg_cache(target);
+       
+       return ERROR_OK;
+       
+}
+
+int arm9tdmi_quit()
+{
+       
+       return ERROR_OK;
+}
+
+int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int chain_pos, char *variant)
+{
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       
+       arm7_9 = &arm9tdmi->arm7_9_common;
+       armv4_5 = &arm7_9->armv4_5_common;
+       
+       /* prepare JTAG information for the new target */
+       arm7_9->jtag_info.chain_pos = chain_pos;
+       arm7_9->jtag_info.scann_size = 5;
+       
+       /* register arch-specific functions */
+       arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
+       arm7_9->change_to_arm = arm9tdmi_change_to_arm;
+       arm7_9->read_core_regs = arm9tdmi_read_core_regs;
+       arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
+       arm7_9->read_xpsr = arm9tdmi_read_xpsr;
+       
+       arm7_9->write_xpsr = arm9tdmi_write_xpsr;
+       arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
+       arm7_9->write_core_regs = arm9tdmi_write_core_regs;
+       
+       arm7_9->load_word_regs = arm9tdmi_load_word_regs;
+       arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
+       arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
+       
+       arm7_9->store_word_regs = arm9tdmi_store_word_regs;
+       arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
+       arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
+       
+       arm7_9->write_pc = arm9tdmi_write_pc;
+       arm7_9->branch_resume = arm9tdmi_branch_resume;
+       arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
+
+       arm7_9->enable_single_step = arm9tdmi_enable_single_step;
+       arm7_9->disable_single_step = arm9tdmi_disable_single_step;
+       
+       arm7_9->pre_debug_entry = NULL;
+       arm7_9->post_debug_entry = NULL;
+       
+       arm7_9->pre_restore_context = NULL;
+       arm7_9->post_restore_context = NULL;
+
+       /* initialize arch-specific breakpoint handling */
+       arm7_9->arm_bkpt = 0xdeeedeee;
+       arm7_9->thumb_bkpt = 0xdeee;
+       
+       arm7_9->sw_bkpts_use_wp = 1;
+       arm7_9->sw_bkpts_enabled = 0;
+       arm7_9->dbgreq_adjust_pc = 3;
+       arm7_9->arch_info = arm9tdmi;
+       
+       arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC;
+       arm9tdmi->arch_info = NULL;
+
+       if (variant)
+       {
+               arm9tdmi->variant = strdup(variant);
+       }
+       else
+       {
+               arm9tdmi->variant = strdup("");
+       }
+       
+       arm7_9_init_arch_info(target, arm7_9);
+
+       /* override use of DBGRQ, this is safe on ARM9TDMI */
+       arm7_9->use_dbgrq = 1;
+
+       /* all ARM9s have the vector catch register */
+       arm7_9->has_vector_catch = 1;
+       
+       return ERROR_OK;
+}
+
+int arm9tdmi_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm7_9 = armv4_5->arch_info;
+       if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       arm9tdmi = arm7_9->arch_info;
+       if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+       {
+               return -1;
+       }
+       
+       *armv4_5_p = armv4_5;
+       *arm7_9_p = arm7_9;
+       *arm9tdmi_p = arm9tdmi;
+       
+       return ERROR_OK;
+}
+
+
+/* target arm9tdmi <endianess> <startup_mode> <chain_pos> <variant>*/
+int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       arm9tdmi_common_t *arm9tdmi = malloc(sizeof(arm9tdmi_common_t));
+
+       if (argc < 4)
+       {
+               ERROR("'target arm9tdmi' requires at least one additional argument");
+               exit(-1);
+       }
+       
+       chain_pos = strtoul(args[3], NULL, 0);
+       
+       if (argc >= 5)
+               variant = args[4];
+       
+       arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+       
+       return ERROR_OK;
+}
+
+int arm9tdmi_register_commands(struct command_context_s *cmd_ctx)
+{
+       int retval;
+       
+       command_t *arm9tdmi_cmd;
+       
+               
+       retval = arm7_9_register_commands(cmd_ctx);
+       
+       arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9tdmi", NULL, COMMAND_ANY, "arm9tdmi specific commands");
+
+       register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch", handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC, "catch arm920t vectors ['all'|'none'|'<vec1 vec2 ...>']");
+       
+       
+       return ERROR_OK;
+
+}
+
+int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       arm9tdmi_common_t *arm9tdmi;
+       reg_t *vector_catch;
+       u32 vector_catch_value;
+       int i, j;
+       
+       if (arm9tdmi_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM9TDMI based target");
+               return ERROR_OK;
+       }
+       
+       vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
+       
+       /* read the vector catch register if necessary */
+       if (!vector_catch->valid)
+               embeddedice_read_reg(vector_catch);
+       
+       /* get the current setting */
+       vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);
+       
+       if (argc > 0)
+       {
+               vector_catch_value = 0x0;
+               if (strcmp(args[0], "all") == 0)
+               {
+                       vector_catch_value = 0xdf;
+               }
+               else if (strcmp(args[0], "none") == 0)
+               {
+                       /* do nothing */
+               }
+               else
+               {
+                       for (i = 0; i < argc; i++)
+                       {
+                               /* go through list of vectors */
+                               for(j = 0; arm9tdmi_vectors[j].name; j++)
+                               {
+                                       if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)
+                                       {
+                                               vector_catch_value |= arm9tdmi_vectors[j].value;
+                                               break;
+                                       }
+                               }
+                               
+                               /* complain if vector wasn't found */
+                               if (!arm9tdmi_vectors[j].name)
+                               {
+                                       command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);
+                                       
+                                       /* reread current setting */
+                                       vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);
+                                       
+                                       break;
+                               }
+                       }
+               }
+               
+               /* store new settings */
+               buf_set_u32(vector_catch->value, 0, 32, vector_catch_value);
+               embeddedice_store_reg(vector_catch);
+       }
+               
+       /* output current settings (skip RESERVED vector) */
+       for (i = 0; i < 8; i++)
+       {
+               if (i != 5)
+               {
+                       command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,
+                               (vector_catch_value & (1 << i)) ? "catch" : "don't catch");
+               }  
+       }
+
+       return ERROR_OK;
+}
index 08cf3462dcdaab060db23864ff79de3a4357fdd0..7a9e8786f730a0085c94267788f191c665c6668a 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "arm_jtag.h"\r
-\r
-#include "binarybuffer.h"\r
-#include "log.h"\r
-#include "jtag.h"\r
-\r
-#include <stdlib.h>\r
-\r
-#if 0\r
-#define _ARM_JTAG_SCAN_N_CHECK_\r
-#endif\r
-\r
-int arm_jtag_set_instr(arm_jtag_t *jtag_info, u32 new_instr,  in_handler_t handler)\r
-{\r
-       jtag_device_t *device = jtag_get_device(jtag_info->chain_pos);\r
-       \r
-       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
-       {\r
-               scan_field_t field;\r
-       \r
-               field.device = jtag_info->chain_pos;\r
-               field.num_bits = device->ir_length;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = handler;\r
-               field.in_handler_priv = NULL;\r
-               jtag_add_ir_scan(1, &field, -1);\r
-               \r
-               \r
-               free(field.out_value);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm_jtag_scann(arm_jtag_t *jtag_info, u32 new_scan_chain)\r
-{\r
-       if(jtag_info->cur_scan_chain != new_scan_chain)\r
-       {\r
-#ifdef _ARM_JTAG_SCAN_N_CHECK_\r
-               u8 scan_n_check_value = 1 << (jtag_info->scann_size - 1);\r
-#endif\r
-               scan_field_t field;\r
-               \r
-               field.device = jtag_info->chain_pos;\r
-               field.num_bits = jtag_info->scann_size;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-#ifdef _ARM_JTAG_SCAN_N_CHECK_\r
-               jtag_set_check_value(&field, &scan_n_check_value, NULL, NULL, NULL);\r
-#else\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-#endif \r
-               \r
-               \r
-               arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL);\r
-               jtag_add_dr_scan(1, &field, -1);\r
-               \r
-               jtag_info->cur_scan_chain = new_scan_chain;\r
-               \r
-               free(field.out_value);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm_jtag_reset_callback(enum jtag_event event, void *priv)\r
-{\r
-       arm_jtag_t *jtag_info = priv;\r
-       \r
-       if (event == JTAG_TRST_ASSERTED)\r
-       {\r
-               jtag_info->cur_scan_chain = 0;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int arm_jtag_setup_connection(arm_jtag_t *jtag_info)\r
-{\r
-       jtag_info->scann_instr = 0x2;\r
-       jtag_info->cur_scan_chain = 0;\r
-       jtag_info->intest_instr = 0xc;\r
-\r
-       jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into host-endian u32, flipping bit-order */\r
-int arm_jtag_buf_to_u32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       u32 *dest = priv;\r
-       *dest = flip_u32(le_to_h_u32(in_buf), 32);\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into little-endian u32, flipping bit-order */\r
-int arm_jtag_buf_to_le32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u32_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into little-endian u16, flipping bit-order */\r
-int arm_jtag_buf_to_le16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u16_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into big-endian u32, flipping bit-order */\r
-int arm_jtag_buf_to_be32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u32_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into big-endian u16, flipping bit-order */\r
-int arm_jtag_buf_to_be16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u16_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into u8, flipping bit-order */\r
-int arm_jtag_buf_to_8_flip(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       u8 *dest = priv;\r
-       *dest = flip_u32(le_to_h_u32(in_buf), 32) & 0xff;\r
-       return ERROR_OK;\r
-}\r
-\r
-/* not-flipping variants */\r
-/* read JTAG buffer into host-endian u32 */\r
-int arm_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       u32 *dest = priv;\r
-       *dest = le_to_h_u32(in_buf);\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into little-endian u32 */\r
-int arm_jtag_buf_to_le32(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u32_to_le(((u8*)priv), le_to_h_u32(in_buf));\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into little-endian u16 */\r
-int arm_jtag_buf_to_le16(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u16_to_le(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into big-endian u32 */\r
-int arm_jtag_buf_to_be32(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u32_to_be(((u8*)priv), le_to_h_u32(in_buf));\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into big-endian u16 */\r
-int arm_jtag_buf_to_be16(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       h_u16_to_be(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);\r
-       return ERROR_OK;\r
-}\r
-\r
-/* read JTAG buffer into u8 */\r
-int arm_jtag_buf_to_8(u8 *in_buf, void *priv, struct scan_field_s *field)\r
-{\r
-       u8 *dest = priv;\r
-       *dest = le_to_h_u32(in_buf) & 0xff;\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "arm_jtag.h"
+
+#include "binarybuffer.h"
+#include "log.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+#if 0
+#define _ARM_JTAG_SCAN_N_CHECK_
+#endif
+
+int arm_jtag_set_instr(arm_jtag_t *jtag_info, u32 new_instr,  in_handler_t handler)
+{
+       jtag_device_t *device = jtag_get_device(jtag_info->chain_pos);
+       
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+       
+               field.device = jtag_info->chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = handler;
+               field.in_handler_priv = NULL;
+               jtag_add_ir_scan(1, &field, -1);
+               
+               
+               free(field.out_value);
+       }
+       
+       return ERROR_OK;
+}
+
+int arm_jtag_scann(arm_jtag_t *jtag_info, u32 new_scan_chain)
+{
+       if(jtag_info->cur_scan_chain != new_scan_chain)
+       {
+#ifdef _ARM_JTAG_SCAN_N_CHECK_
+               u8 scan_n_check_value = 1 << (jtag_info->scann_size - 1);
+#endif
+               scan_field_t field;
+               
+               field.device = jtag_info->chain_pos;
+               field.num_bits = jtag_info->scann_size;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+#ifdef _ARM_JTAG_SCAN_N_CHECK_
+               jtag_set_check_value(&field, &scan_n_check_value, NULL, NULL, NULL);
+#else
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+#endif 
+               
+               
+               arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL);
+               jtag_add_dr_scan(1, &field, -1);
+               
+               jtag_info->cur_scan_chain = new_scan_chain;
+               
+               free(field.out_value);
+       }
+       
+       return ERROR_OK;
+}
+
+int arm_jtag_reset_callback(enum jtag_event event, void *priv)
+{
+       arm_jtag_t *jtag_info = priv;
+       
+       if (event == JTAG_TRST_ASSERTED)
+       {
+               jtag_info->cur_scan_chain = 0;
+       }
+       
+       return ERROR_OK;
+}
+
+int arm_jtag_setup_connection(arm_jtag_t *jtag_info)
+{
+       jtag_info->scann_instr = 0x2;
+       jtag_info->cur_scan_chain = 0;
+       jtag_info->intest_instr = 0xc;
+
+       jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);
+       
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into host-endian u32, flipping bit-order */
+int arm_jtag_buf_to_u32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       u32 *dest = priv;
+       *dest = flip_u32(le_to_h_u32(in_buf), 32);
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u32, flipping bit-order */
+int arm_jtag_buf_to_le32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u32_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u16, flipping bit-order */
+int arm_jtag_buf_to_le16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u16_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u32, flipping bit-order */
+int arm_jtag_buf_to_be32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u32_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u16, flipping bit-order */
+int arm_jtag_buf_to_be16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u16_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into u8, flipping bit-order */
+int arm_jtag_buf_to_8_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       u8 *dest = priv;
+       *dest = flip_u32(le_to_h_u32(in_buf), 32) & 0xff;
+       return ERROR_OK;
+}
+
+/* not-flipping variants */
+/* read JTAG buffer into host-endian u32 */
+int arm_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       u32 *dest = priv;
+       *dest = le_to_h_u32(in_buf);
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u32 */
+int arm_jtag_buf_to_le32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u32_to_le(((u8*)priv), le_to_h_u32(in_buf));
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u16 */
+int arm_jtag_buf_to_le16(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u16_to_le(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u32 */
+int arm_jtag_buf_to_be32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u32_to_be(((u8*)priv), le_to_h_u32(in_buf));
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u16 */
+int arm_jtag_buf_to_be16(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       h_u16_to_be(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
+       return ERROR_OK;
+}
+
+/* read JTAG buffer into u8 */
+int arm_jtag_buf_to_8(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+       u8 *dest = priv;
+       *dest = le_to_h_u32(in_buf) & 0xff;
+       return ERROR_OK;
+}
index 88b641e3e35c4219cd1ef71f68750fdbe8f935e0..160f4c53f5e81b7d918cf570719c82f6de0ebed9 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2006 by Magnus Lundin                                   *\r
- *   lundin@mlu.mine.nu                                                    *\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
- *                                                                         *\r
- * CoreSight (Light?) SerialWireJtagDebugPort                              *\r
- *                                                                         *\r
- * CoreSightâ„¢ DAP-Lite TRM, ARM DDI 0316A                                  *\r
- * Cortex-M3â„¢ TRM, ARM DDI 0337C                                            *\r
- *                                                                         *\r
-***************************************************************************/\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include "replacements.h"\r
-\r
-#include "cortex_m3.h"\r
-#include "cortex_swjdp.h"\r
-#include "jtag.h"\r
-#include "log.h"\r
-#include <stdlib.h>\r
-\r
-/*\r
-\r
-Transaction Mode:\r
-swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-Uses Overrun checking mode and does not do actual JTAG send/receive or transaction \r
-result checking until swjdp_end_transaction()\r
-This must be done before using or deallocating any return variables.\r
-\r
-swjdp->trans_mode == TRANS_MODE_ATOMIC\r
-All reads and writes to the AHB bus are checked for valid completion, and return values\r
-are immediatley available.\r
-\r
-*/\r
-\r
-/***************************************************************************\r
- *                                                                         *\r
- * DPACC and APACC scanchain access through JTAG-DR                        *\r
- *                                                                         *\r
-***************************************************************************/\r
-\r
-/* Scan out and in from target ordered u8 buffers */\r
-int swjdp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)\r
-{\r
-       scan_field_t fields[2];\r
-       u8 out_addr_buf;\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_set_instr(jtag_info, instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 3;\r
-       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));\r
-       fields[0].out_value = &out_addr_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = ack;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = outvalue;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = invalue;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* Scan out and in from host ordered u32 variables */\r
-int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)\r
-{\r
-       scan_field_t fields[2];\r
-       u8 out_value_buf[4];\r
-       u8 out_addr_buf;\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_set_instr(jtag_info, instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 3;\r
-       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));\r
-       fields[0].out_value = &out_addr_buf;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = ack;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 32;\r
-       buf_set_u32(out_value_buf, 0, 32, outvalue);\r
-       fields[1].out_value = out_value_buf;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       if (invalue)\r
-       {\r
-               fields[1].in_handler = arm_jtag_buf_to_u32;\r
-               fields[1].in_handler_priv = invalue;\r
-       }\r
-       else\r
-       {\r
-               fields[1].in_handler = NULL;\r
-               fields[1].in_handler_priv = NULL;\r
-       }\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ \r
-int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)\r
-{\r
-       swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);\r
-       if ((RnW == DPAP_READ) && (invalue != NULL))\r
-       {\r
-               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);\r
-       }\r
-       \r
-       /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */\r
-       if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))\r
-       {\r
-               return swjdp_transaction_endcheck(swjdp);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)\r
-{\r
-\r
-       swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);\r
-       if ((RnW==DPAP_READ) && (invalue != NULL))\r
-       {\r
-               swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);\r
-       }\r
-       \r
-       /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */\r
-       if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))\r
-       {\r
-               return swjdp_transaction_endcheck(swjdp);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int swjdp_transaction_endcheck(swjdp_common_t *swjdp)\r
-{\r
-       int waitcount = 0;\r
-       u32 ctrlstat;\r
-\r
-       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
-       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
-       jtag_execute_queue();\r
-       \r
-       swjdp->ack = swjdp->ack & 0x7;\r
-       \r
-       while (swjdp->ack != 2)\r
-       {\r
-               if (swjdp->ack == 1)\r
-               {\r
-                       waitcount++;\r
-                       if (waitcount > 100)\r
-                       {\r
-                               WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");\r
-\r
-                               return ERROR_JTAG_DEVICE_ERROR;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       WARNING("Invalid ACK in SWJDP transaction");\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-\r
-               scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
-               jtag_execute_queue();\r
-               swjdp->ack = swjdp->ack & 0x7;\r
-       }\r
-\r
-       /* Check for STICKYERR and STICKYORUN */\r
-       if (ctrlstat & (SSTICKYORUN | SSTICKYERR))\r
-       {\r
-               DEBUG("swjdp: CTRL/STAT error 0x%x", ctrlstat);\r
-               /* Check power to debug regions */\r
-               if ((ctrlstat & 0xf0000000) != 0xf0000000)\r
-               {\r
-                        ahbap_debugport_init(swjdp);\r
-               }\r
-               else\r
-               {\r
-                       u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr;\r
-                       \r
-                       if (ctrlstat & SSTICKYORUN)\r
-                               ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed");\r
-                       \r
-                       if (ctrlstat & SSTICKYERR)\r
-                               ERROR("SWJ-DP STICKY ERROR");\r
-                       \r
-                       /* Clear Sticky Error Bits */\r
-                       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);\r
-                       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);\r
-                       jtag_execute_queue();\r
-\r
-                       DEBUG("swjdp: status 0x%x", ctrlstat);\r
-                       \r
-                       /* Can we find out the reason for the error ?? */                       \r
-                       ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);\r
-                       ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr);\r
-                       ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr);\r
-                       ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar);\r
-                       ERROR("dcb_dhcsr 0x%x, nvic_shcsr 0x%x, nvic_cfsr 0x%x, nvic_bfar 0x%x", dcb_dhcsr, nvic_shcsr, nvic_cfsr, nvic_bfar);\r
-               }\r
-               jtag_execute_queue();\r
-               return ERROR_JTAG_DEVICE_ERROR;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/***************************************************************************\r
- *                                                                         *\r
- * DP and AHB-AP  register access  through APACC and DPACC                 *\r
- *                                                                         *\r
-***************************************************************************/\r
-\r
-int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)\r
-{\r
-       u8 out_value_buf[4];\r
-       \r
-       buf_set_u32(out_value_buf, 0, 32, value);\r
-       return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);\r
-}\r
-\r
-int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)\r
-{\r
-       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);\r
-\r
-    return ERROR_OK;\r
-}\r
-\r
-int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)\r
-{\r
-       u32 select;\r
-       select = (reg_addr & 0xFF0000F0);\r
-\r
-       if (select != swjdp->dp_select_value)\r
-       {\r
-               swjdp_write_dpacc(swjdp, select, DP_SELECT);\r
-               swjdp->dp_select_value = select;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)\r
-{\r
-       swjdp_bankselect_apacc(swjdp, reg_addr);\r
-       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)\r
-{\r
-       swjdp_bankselect_apacc(swjdp, reg_addr);\r
-       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);\r
-\r
-       return ERROR_OK;\r
-}\r
-int ahbap_write_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 value)\r
-{\r
-       u8 out_value_buf[4];\r
-       \r
-       buf_set_u32(out_value_buf, 0, 32, value);\r
-       swjdp_bankselect_apacc(swjdp, reg_addr);\r
-       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)\r
-{\r
-       swjdp_bankselect_apacc(swjdp, reg_addr);\r
-       scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/***************************************************************************\r
- *                                                                         *\r
- * AHB-AP access to memory and system registers on AHB bus                 *\r
- *                                                                         *\r
-***************************************************************************/\r
-\r
-int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)\r
-{\r
-       csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;\r
-       if (csw != swjdp->ap_csw_value)\r
-       {\r
-               //DEBUG("swjdp : Set CSW %x",csw);\r
-               ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); \r
-               swjdp->ap_csw_value = csw;\r
-       }\r
-       if (tar != swjdp->ap_tar_value)\r
-       {\r
-               //DEBUG("swjdp : Set TAR %x",tar);\r
-               ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar );\r
-               swjdp->ap_tar_value = tar;\r
-       }\r
-       if (csw & CSW_ADDRINC_MASK)\r
-       {       \r
-               /* Do not cache TAR value when autoincrementing */      \r
-               swjdp->ap_tar_value = -1;\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-/*****************************************************************************\r
-*                                                                            *\r
-* ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)      *\r
-*                                                                            *\r
-* Read a u32 value from memory or system register                            *\r
-* Functionally equivalent to target_read_u32(target, address, u32 *value),   *\r
-* but with less overhead                                                     *\r
-*****************************************************************************/\r
-int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)\r
-{\r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-\r
-       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);\r
-       ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value)\r
-{\r
-       ahbap_read_system_u32(swjdp, address, value);\r
-       \r
-       return swjdp_transaction_endcheck(swjdp);\r
-}\r
-\r
-/*****************************************************************************\r
-*                                                                            *\r
-* ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)      *\r
-*                                                                            *\r
-* Write a u32 value to memory or system register                             *\r
-*                                                                            *\r
-*****************************************************************************/\r
-int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)\r
-{\r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-\r
-       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);\r
-       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)\r
-{\r
-       ahbap_write_system_u32(swjdp, address, value);\r
-       \r
-       return swjdp_transaction_endcheck(swjdp);\r
-}\r
-\r
-/*****************************************************************************\r
-*                                                                            *\r
-* ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) *\r
-*                                                                            *\r
-* Write a buffer in target order (little endian)                             *\r
-*                                                                            *\r
-*****************************************************************************/\r
-int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
-{\r
-       u32 outvalue;\r
-       int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;\r
-\r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-\r
-       while ((address & 0x3) && (count > 0))\r
-       {\r
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
-               outvalue = (*buffer++) << 8 * (address & 0x3);\r
-               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );\r
-               swjdp_transaction_endcheck(swjdp);\r
-               count--;\r
-               address++;\r
-       }\r
-       wcount = count >> 2;\r
-       count = count - 4 * wcount;\r
-       while (wcount > 0)\r
-       {\r
-               /* Adjust to write blocks within 4K aligned boundaries */\r
-               blocksize = (0x1000 - (0xFFF & address)) >> 2;\r
-               if (wcount < blocksize)\r
-                       blocksize = wcount;\r
-               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);\r
-               for (writecount=0; writecount<blocksize; writecount++)\r
-               {\r
-                       ahbap_write_reg(swjdp, AHBAP_DRW, buffer + 4 * writecount );\r
-               }\r
-               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)\r
-               {\r
-                       wcount = wcount - blocksize;\r
-                       address = address + 4 * blocksize;\r
-                       buffer = buffer + 4 * blocksize;\r
-               }\r
-               else\r
-               {\r
-                       errorcount++;\r
-               }\r
-               if (errorcount > 1)\r
-               {\r
-                       WARNING("Block write error address 0x%x, wcount 0x%x", address, wcount);\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-       }\r
-       \r
-       while (count > 0)\r
-       {\r
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
-               outvalue = (*buffer++) << 8 * (address & 0x3);\r
-               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );\r
-               retval = swjdp_transaction_endcheck(swjdp);\r
-               count--;\r
-               address++;\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
-{\r
-       u32 outvalue;\r
-       int retval = ERROR_OK;\r
-       \r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-       \r
-       while (count > 0)\r
-       {\r
-               ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);\r
-               outvalue = *((u16*)buffer) << 8 * (address & 0x3);\r
-               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );\r
-               retval = swjdp_transaction_endcheck(swjdp);\r
-               count -= 2;\r
-               address += 2;\r
-               buffer += 2;\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-/*****************************************************************************\r
-*                                                                            *\r
-* ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *\r
-*                                                                            *\r
-* Read block fast in target order (little endian) into a buffer       *\r
-*                                                                            *\r
-*****************************************************************************/\r
-int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
-{\r
-       u32 invalue;\r
-       int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;\r
-\r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-\r
-       while ((address & 0x3) && (count > 0))\r
-       {\r
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
-               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue);\r
-               swjdp_transaction_endcheck(swjdp);\r
-               *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;\r
-               count--;\r
-               address++;\r
-       }\r
-       wcount = count >> 2;\r
-       count = count - 4 * wcount;\r
-       while (wcount > 0)\r
-       {\r
-               /* Adjust to read within 4K block boundaries */\r
-               blocksize = (0x1000 - (0xFFF & address)) >> 2;\r
-               if (wcount < blocksize)\r
-                       blocksize = wcount;\r
-               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);\r
-               /* Scan out first read */\r
-               swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);\r
-               for (readcount = 0; readcount < blocksize - 1; readcount++)\r
-               {\r
-                       /* Scan out read instruction and scan in previous value */\r
-                       swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);\r
-               }\r
-               /* Scan in last value */\r
-               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);\r
-               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)\r
-               {\r
-                       wcount = wcount - blocksize;\r
-                       address += 4 * blocksize;\r
-                       buffer += 4 * blocksize; \r
-               }\r
-               else\r
-               {\r
-                       errorcount++;\r
-               }\r
-               if (errorcount > 1)\r
-               {\r
-                       WARNING("Block read error address 0x%x, count 0x%x", address, count);\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-       }\r
-\r
-       while (count > 0)\r
-       {\r
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);\r
-               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );\r
-               retval = swjdp_transaction_endcheck(swjdp);\r
-               *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;\r
-               count--;\r
-               address++;\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)\r
-{\r
-       u32 invalue;\r
-       int retval = ERROR_OK;\r
-       \r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-       \r
-       while (count > 0)\r
-       {\r
-               ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);\r
-               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );\r
-               retval = swjdp_transaction_endcheck(swjdp);\r
-               *((u16*)buffer) = (invalue >> 8 * (address & 0x3));\r
-               count -= 2;\r
-               address += 2;\r
-               buffer += 2;\r
-       }\r
-\r
-       return retval;\r
-}\r
-\r
-int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)\r
-{\r
-       int readcount, errorcount = 0;\r
-       u32 blocksize;\r
-       \r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-       \r
-       while (count > 0)\r
-       {\r
-               /* Adjust to read within 4K block boundaries */\r
-               blocksize = (0x1000 - (0xFFF & address)) >> 2;\r
-               if (count < blocksize)\r
-                       blocksize = count;\r
-               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);\r
-               for (readcount = 0; readcount < blocksize; readcount++)\r
-               {\r
-                       ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer + readcount );\r
-               }\r
-               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)\r
-               {\r
-                       count = count - blocksize;\r
-                       address = address + 4 * blocksize;\r
-                       buffer = buffer + blocksize;\r
-               }\r
-               else\r
-               {\r
-                       errorcount++;\r
-               }\r
-               if (errorcount > 1)\r
-               {\r
-                       WARNING("Block read error address 0x%x, count 0x%x", address, count);\r
-                       return ERROR_JTAG_DEVICE_ERROR;\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)\r
-{\r
-       int retval;\r
-       u32 dcrdr;\r
-       \r
-       ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);\r
-       \r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-\r
-       /* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */\r
-       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);\r
-       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum );\r
-\r
-       /* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */\r
-       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);\r
-       ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );\r
-       \r
-       retval = swjdp_transaction_endcheck(swjdp);\r
-       ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);\r
-       return retval;\r
-}\r
-\r
-int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)\r
-{\r
-       int retval;\r
-       u32 dcrdr;\r
-       \r
-       ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);\r
-       \r
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;\r
-       \r
-       /* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */\r
-       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);\r
-       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );\r
-\r
-       /* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR       ); */\r
-       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);\r
-       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR );\r
-       \r
-       retval = swjdp_transaction_endcheck(swjdp);\r
-       ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);\r
-       return retval;\r
-}\r
-\r
-int ahbap_debugport_init(swjdp_common_t *swjdp)\r
-{\r
-       u32 idreg, romaddr, dummy;\r
-       u32 ctrlstat;\r
-       int cnt = 0;\r
-       \r
-       DEBUG(" ");\r
-       \r
-       swjdp->ap_csw_value = -1;\r
-       swjdp->ap_tar_value = -1;\r
-       swjdp->trans_mode = TRANS_MODE_ATOMIC;\r
-       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
-       swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT);\r
-       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
-       \r
-       swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;\r
-\r
-       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);\r
-       swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);\r
-       jtag_execute_queue();\r
-\r
-       /* Check that we have debug power domains activated */\r
-       while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))\r
-       {\r
-               DEBUG("swjdp: wait CDBGPWRUPACK");\r
-               swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);\r
-               jtag_execute_queue();\r
-               usleep(10000);\r
-       }\r
-\r
-       while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))\r
-       {\r
-               DEBUG("swjdp: wait CSYSPWRUPACK");\r
-               swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);\r
-               jtag_execute_queue();\r
-               usleep(10000);\r
-       }\r
-\r
-       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
-       /* With debug power on we can activate OVERRUN checking */\r
-       swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;\r
-       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);\r
-       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);\r
-       \r
-       ahbap_read_reg_u32(swjdp, 0xFC, &idreg);\r
-       ahbap_read_reg_u32(swjdp, 0xF8, &romaddr);\r
-       \r
-       DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);       \r
-       \r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+/***************************************************************************
+ *                                                                         *
+ * CoreSight (Light?) SerialWireJtagDebugPort                              *
+ *                                                                         *
+ * CoreSightâ„¢ DAP-Lite TRM, ARM DDI 0316A                                  *
+ * Cortex-M3â„¢ TRM, ARM DDI 0337C                                            *
+ *                                                                         *
+***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "cortex_m3.h"
+#include "cortex_swjdp.h"
+#include "jtag.h"
+#include "log.h"
+#include <stdlib.h>
+
+/*
+
+Transaction Mode:
+swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+Uses Overrun checking mode and does not do actual JTAG send/receive or transaction 
+result checking until swjdp_end_transaction()
+This must be done before using or deallocating any return variables.
+
+swjdp->trans_mode == TRANS_MODE_ATOMIC
+All reads and writes to the AHB bus are checked for valid completion, and return values
+are immediatley available.
+
+*/
+
+/***************************************************************************
+ *                                                                         *
+ * DPACC and APACC scanchain access through JTAG-DR                        *
+ *                                                                         *
+***************************************************************************/
+
+/* Scan out and in from target ordered u8 buffers */
+int swjdp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)
+{
+       scan_field_t fields[2];
+       u8 out_addr_buf;
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_set_instr(jtag_info, instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 3;
+       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
+       fields[0].out_value = &out_addr_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = ack;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = outvalue;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = invalue;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       return ERROR_OK;
+}
+
+/* Scan out and in from host ordered u32 variables */
+int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)
+{
+       scan_field_t fields[2];
+       u8 out_value_buf[4];
+       u8 out_addr_buf;
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_set_instr(jtag_info, instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 3;
+       buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
+       fields[0].out_value = &out_addr_buf;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = ack;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 32;
+       buf_set_u32(out_value_buf, 0, 32, outvalue);
+       fields[1].out_value = out_value_buf;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       if (invalue)
+       {
+               fields[1].in_handler = arm_jtag_buf_to_u32;
+               fields[1].in_handler_priv = invalue;
+       }
+       else
+       {
+               fields[1].in_handler = NULL;
+               fields[1].in_handler_priv = NULL;
+       }
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       return ERROR_OK;
+}
+
+/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ 
+int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)
+{
+       swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
+       if ((RnW == DPAP_READ) && (invalue != NULL))
+       {
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+       }
+       
+       /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
+       if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
+       {
+               return swjdp_transaction_endcheck(swjdp);
+       }
+
+       return ERROR_OK;
+}
+
+int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)
+{
+
+       swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
+       if ((RnW==DPAP_READ) && (invalue != NULL))
+       {
+               swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+       }
+       
+       /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */
+       if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
+       {
+               return swjdp_transaction_endcheck(swjdp);
+       }
+
+       return ERROR_OK;
+}
+
+int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
+{
+       int waitcount = 0;
+       u32 ctrlstat;
+
+       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+       jtag_execute_queue();
+       
+       swjdp->ack = swjdp->ack & 0x7;
+       
+       while (swjdp->ack != 2)
+       {
+               if (swjdp->ack == 1)
+               {
+                       waitcount++;
+                       if (waitcount > 100)
+                       {
+                               WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");
+
+                               return ERROR_JTAG_DEVICE_ERROR;
+                       }
+               }
+               else
+               {
+                       WARNING("Invalid ACK in SWJDP transaction");
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+
+               scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+               jtag_execute_queue();
+               swjdp->ack = swjdp->ack & 0x7;
+       }
+
+       /* Check for STICKYERR and STICKYORUN */
+       if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
+       {
+               DEBUG("swjdp: CTRL/STAT error 0x%x", ctrlstat);
+               /* Check power to debug regions */
+               if ((ctrlstat & 0xf0000000) != 0xf0000000)
+               {
+                        ahbap_debugport_init(swjdp);
+               }
+               else
+               {
+                       u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr;
+                       
+                       if (ctrlstat & SSTICKYORUN)
+                               ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed");
+                       
+                       if (ctrlstat & SSTICKYERR)
+                               ERROR("SWJ-DP STICKY ERROR");
+                       
+                       /* Clear Sticky Error Bits */
+                       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);
+                       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+                       jtag_execute_queue();
+
+                       DEBUG("swjdp: status 0x%x", ctrlstat);
+                       
+                       /* Can we find out the reason for the error ?? */                       
+                       ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr);
+                       ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar);
+                       ERROR("dcb_dhcsr 0x%x, nvic_shcsr 0x%x, nvic_cfsr 0x%x, nvic_bfar 0x%x", dcb_dhcsr, nvic_shcsr, nvic_cfsr, nvic_bfar);
+               }
+               jtag_execute_queue();
+               return ERROR_JTAG_DEVICE_ERROR;
+       }
+
+       return ERROR_OK;
+}
+
+/***************************************************************************
+ *                                                                         *
+ * DP and AHB-AP  register access  through APACC and DPACC                 *
+ *                                                                         *
+***************************************************************************/
+
+int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)
+{
+       u8 out_value_buf[4];
+       
+       buf_set_u32(out_value_buf, 0, 32, value);
+       return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+}
+
+int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)
+{
+       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
+
+    return ERROR_OK;
+}
+
+int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)
+{
+       u32 select;
+       select = (reg_addr & 0xFF0000F0);
+
+       if (select != swjdp->dp_select_value)
+       {
+               swjdp_write_dpacc(swjdp, select, DP_SELECT);
+               swjdp->dp_select_value = select;
+       }
+
+       return ERROR_OK;
+}
+
+int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)
+{
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+       return ERROR_OK;
+}
+
+int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)
+{
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);
+
+       return ERROR_OK;
+}
+int ahbap_write_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 value)
+{
+       u8 out_value_buf[4];
+       
+       buf_set_u32(out_value_buf, 0, 32, value);
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+       return ERROR_OK;
+}
+
+int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)
+{
+       swjdp_bankselect_apacc(swjdp, reg_addr);
+       scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);
+
+       return ERROR_OK;
+}
+
+/***************************************************************************
+ *                                                                         *
+ * AHB-AP access to memory and system registers on AHB bus                 *
+ *                                                                         *
+***************************************************************************/
+
+int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)
+{
+       csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
+       if (csw != swjdp->ap_csw_value)
+       {
+               //DEBUG("swjdp : Set CSW %x",csw);
+               ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); 
+               swjdp->ap_csw_value = csw;
+       }
+       if (tar != swjdp->ap_tar_value)
+       {
+               //DEBUG("swjdp : Set TAR %x",tar);
+               ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar );
+               swjdp->ap_tar_value = tar;
+       }
+       if (csw & CSW_ADDRINC_MASK)
+       {       
+               /* Do not cache TAR value when autoincrementing */      
+               swjdp->ap_tar_value = -1;
+       }
+       return ERROR_OK;
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)      *
+*                                                                            *
+* Read a u32 value from memory or system register                            *
+* Functionally equivalent to target_read_u32(target, address, u32 *value),   *
+* but with less overhead                                                     *
+*****************************************************************************/
+int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
+{
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
+       ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );
+       
+       return ERROR_OK;
+}
+
+int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
+{
+       ahbap_read_system_u32(swjdp, address, value);
+       
+       return swjdp_transaction_endcheck(swjdp);
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)      *
+*                                                                            *
+* Write a u32 value to memory or system register                             *
+*                                                                            *
+*****************************************************************************/
+int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)
+{
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );
+
+       return ERROR_OK;
+}
+
+int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)
+{
+       ahbap_write_system_u32(swjdp, address, value);
+       
+       return swjdp_transaction_endcheck(swjdp);
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) *
+*                                                                            *
+* Write a buffer in target order (little endian)                             *
+*                                                                            *
+*****************************************************************************/
+int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 outvalue;
+       int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
+
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       while ((address & 0x3) && (count > 0))
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               outvalue = (*buffer++) << 8 * (address & 0x3);
+               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+               swjdp_transaction_endcheck(swjdp);
+               count--;
+               address++;
+       }
+       wcount = count >> 2;
+       count = count - 4 * wcount;
+       while (wcount > 0)
+       {
+               /* Adjust to write blocks within 4K aligned boundaries */
+               blocksize = (0x1000 - (0xFFF & address)) >> 2;
+               if (wcount < blocksize)
+                       blocksize = wcount;
+               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               for (writecount=0; writecount<blocksize; writecount++)
+               {
+                       ahbap_write_reg(swjdp, AHBAP_DRW, buffer + 4 * writecount );
+               }
+               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
+               {
+                       wcount = wcount - blocksize;
+                       address = address + 4 * blocksize;
+                       buffer = buffer + 4 * blocksize;
+               }
+               else
+               {
+                       errorcount++;
+               }
+               if (errorcount > 1)
+               {
+                       WARNING("Block write error address 0x%x, wcount 0x%x", address, wcount);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+       
+       while (count > 0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               outvalue = (*buffer++) << 8 * (address & 0x3);
+               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               count--;
+               address++;
+       }
+
+       return retval;
+}
+
+int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 outvalue;
+       int retval = ERROR_OK;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       while (count > 0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
+               outvalue = *((u16*)buffer) << 8 * (address & 0x3);
+               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               count -= 2;
+               address += 2;
+               buffer += 2;
+       }
+
+       return retval;
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *
+*                                                                            *
+* Read block fast in target order (little endian) into a buffer       *
+*                                                                            *
+*****************************************************************************/
+int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 invalue;
+       int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
+
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       while ((address & 0x3) && (count > 0))
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue);
+               swjdp_transaction_endcheck(swjdp);
+               *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
+               count--;
+               address++;
+       }
+       wcount = count >> 2;
+       count = count - 4 * wcount;
+       while (wcount > 0)
+       {
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000 - (0xFFF & address)) >> 2;
+               if (wcount < blocksize)
+                       blocksize = wcount;
+               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               /* Scan out first read */
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);
+               for (readcount = 0; readcount < blocksize - 1; readcount++)
+               {
+                       /* Scan out read instruction and scan in previous value */
+                       swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+               }
+               /* Scan in last value */
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
+               {
+                       wcount = wcount - blocksize;
+                       address += 4 * blocksize;
+                       buffer += 4 * blocksize; 
+               }
+               else
+               {
+                       errorcount++;
+               }
+               if (errorcount > 1)
+               {
+                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+
+       while (count > 0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
+               count--;
+               address++;
+       }
+
+       return retval;
+}
+
+int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 invalue;
+       int retval = ERROR_OK;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       while (count > 0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
+               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               *((u16*)buffer) = (invalue >> 8 * (address & 0x3));
+               count -= 2;
+               address += 2;
+               buffer += 2;
+       }
+
+       return retval;
+}
+
+int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)
+{
+       int readcount, errorcount = 0;
+       u32 blocksize;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       while (count > 0)
+       {
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000 - (0xFFF & address)) >> 2;
+               if (count < blocksize)
+                       blocksize = count;
+               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               for (readcount = 0; readcount < blocksize; readcount++)
+               {
+                       ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer + readcount );
+               }
+               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
+               {
+                       count = count - blocksize;
+                       address = address + 4 * blocksize;
+                       buffer = buffer + blocksize;
+               }
+               else
+               {
+                       errorcount++;
+               }
+               if (errorcount > 1)
+               {
+                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)
+{
+       int retval;
+       u32 dcrdr;
+       
+       ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+       /* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum );
+
+       /* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
+       ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );
+       
+       retval = swjdp_transaction_endcheck(swjdp);
+       ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);
+       return retval;
+}
+
+int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)
+{
+       int retval;
+       u32 dcrdr;
+       
+       ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       /* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );
+
+       /* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR       ); */
+       ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
+       ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR );
+       
+       retval = swjdp_transaction_endcheck(swjdp);
+       ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);
+       return retval;
+}
+
+int ahbap_debugport_init(swjdp_common_t *swjdp)
+{
+       u32 idreg, romaddr, dummy;
+       u32 ctrlstat;
+       int cnt = 0;
+       
+       DEBUG(" ");
+       
+       swjdp->ap_csw_value = -1;
+       swjdp->ap_tar_value = -1;
+       swjdp->trans_mode = TRANS_MODE_ATOMIC;
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT);
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       
+       swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
+
+       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);
+       swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+       jtag_execute_queue();
+
+       /* Check that we have debug power domains activated */
+       while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))
+       {
+               DEBUG("swjdp: wait CDBGPWRUPACK");
+               swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+               jtag_execute_queue();
+               usleep(10000);
+       }
+
+       while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))
+       {
+               DEBUG("swjdp: wait CSYSPWRUPACK");
+               swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+               jtag_execute_queue();
+               usleep(10000);
+       }
+
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       /* With debug power on we can activate OVERRUN checking */
+       swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
+       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);
+       swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+       
+       ahbap_read_reg_u32(swjdp, 0xFC, &idreg);
+       ahbap_read_reg_u32(swjdp, 0xF8, &romaddr);
+       
+       DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);       
+       
+       return ERROR_OK;
+}
index 07b965b07ecfa2d3317955e863030cf00d30207d..333c1c46ca679802aaf0dae7ea8ab7933e6032c1 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "embeddedice.h"\r
-\r
-#include "armv4_5.h"\r
-#include "arm7_9_common.h"\r
-\r
-#include "log.h"\r
-#include "arm_jtag.h"\r
-#include "types.h"\r
-#include "binarybuffer.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "jtag.h"\r
-\r
-#include <stdlib.h>\r
-\r
-bitfield_desc_t embeddedice_comms_ctrl_bitfield_desc[] = \r
-{\r
-       {"R", 1},\r
-       {"W", 1},\r
-       {"reserved", 26},\r
-       {"version", 4}\r
-};\r
-\r
-int embeddedice_reg_arch_info[] =\r
-{\r
-       0x0, 0x1, 0x4, 0x5,\r
-       0x8, 0x9, 0xa, 0xb, 0xc, 0xd,\r
-       0x10, 0x11, 0x12, 0x13, 0x14, 0x15,\r
-       0x2\r
-};\r
-\r
-char* embeddedice_reg_list[] =\r
-{\r
-       "debug_ctrl",\r
-       "debug_status",\r
-       \r
-       "comms_ctrl",\r
-       "comms_data",\r
-       \r
-       "watch 0 addr value",\r
-       "watch 0 addr mask",\r
-       "watch 0 data value",\r
-       "watch 0 data mask",\r
-       "watch 0 control value",\r
-       "watch 0 control mask",\r
-       \r
-       "watch 1 addr value",\r
-       "watch 1 addr mask",\r
-       "watch 1 data value",\r
-       "watch 1 data mask",\r
-       "watch 1 control value",\r
-       "watch 1 control mask",\r
-       \r
-       "vector catch"\r
-};\r
-\r
-int embeddedice_reg_arch_type = -1;\r
-\r
-int embeddedice_get_reg(reg_t *reg);\r
-int embeddedice_set_reg(reg_t *reg, u32 value);\r
-int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf);\r
-\r
-int embeddedice_write_reg(reg_t *reg, u32 value);\r
-int embeddedice_read_reg(reg_t *reg);\r
-\r
-reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9)\r
-{\r
-       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));\r
-       reg_t *reg_list = NULL;\r
-       embeddedice_reg_t *arch_info = NULL;\r
-       arm_jtag_t *jtag_info = &arm7_9->jtag_info;\r
-       int num_regs;\r
-       int i;\r
-       int eice_version = 0;\r
-       \r
-       /* register a register arch-type for EmbeddedICE registers only once */\r
-       if (embeddedice_reg_arch_type == -1)\r
-               embeddedice_reg_arch_type = register_reg_arch_type(embeddedice_get_reg, embeddedice_set_reg_w_exec);\r
-       \r
-       if (arm7_9->has_vector_catch)\r
-               num_regs = 17;\r
-       else\r
-               num_regs = 16;\r
-               \r
-       /* the actual registers are kept in two arrays */\r
-       reg_list = calloc(num_regs, sizeof(reg_t));\r
-       arch_info = calloc(num_regs, sizeof(embeddedice_reg_t));\r
-       \r
-       /* fill in values for the reg cache */\r
-       reg_cache->name = "EmbeddedICE registers";\r
-       reg_cache->next = NULL;\r
-       reg_cache->reg_list = reg_list;\r
-       reg_cache->num_regs = num_regs;\r
-       \r
-       /* set up registers */\r
-       for (i = 0; i < num_regs; i++)\r
-       {\r
-               reg_list[i].name = embeddedice_reg_list[i];\r
-               reg_list[i].size = 32;\r
-               reg_list[i].dirty = 0;\r
-               reg_list[i].valid = 0;\r
-               reg_list[i].bitfield_desc = NULL;\r
-               reg_list[i].num_bitfields = 0;\r
-               reg_list[i].value = calloc(1, 4);\r
-               reg_list[i].arch_info = &arch_info[i];\r
-               reg_list[i].arch_type = embeddedice_reg_arch_type;\r
-               arch_info[i].addr = embeddedice_reg_arch_info[i];\r
-               arch_info[i].jtag_info = jtag_info;\r
-       }\r
-       \r
-       /* identify EmbeddedICE version by reading DCC control register */\r
-       embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);\r
-       jtag_execute_queue();\r
-       \r
-       eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);\r
-       \r
-       switch (eice_version)\r
-       {\r
-               case 1:\r
-                       reg_list[EICE_DBG_CTRL].size = 3;\r
-                       reg_list[EICE_DBG_STAT].size = 5;\r
-                       break;\r
-               case 2:\r
-                       reg_list[EICE_DBG_CTRL].size = 4;\r
-                       reg_list[EICE_DBG_STAT].size = 5;\r
-                       arm7_9->has_single_step = 1;\r
-                       break;\r
-               case 3:\r
-                       ERROR("EmbeddedICE version 3 detected, EmbeddedICE handling might be broken"); \r
-                       reg_list[EICE_DBG_CTRL].size = 6;\r
-                       reg_list[EICE_DBG_STAT].size = 5;\r
-                       arm7_9->has_single_step = 1;\r
-                       arm7_9->has_monitor_mode = 1;\r
-                       break;\r
-               case 4:\r
-                       reg_list[EICE_DBG_CTRL].size = 6;\r
-                       reg_list[EICE_DBG_STAT].size = 5;\r
-                       arm7_9->has_monitor_mode = 1;\r
-                       break;\r
-               case 5:\r
-                       reg_list[EICE_DBG_CTRL].size = 6;\r
-                       reg_list[EICE_DBG_STAT].size = 5;\r
-                       arm7_9->has_single_step = 1;\r
-                       arm7_9->has_monitor_mode = 1;\r
-                       break;\r
-               case 6:\r
-                       reg_list[EICE_DBG_CTRL].size = 6;\r
-                       reg_list[EICE_DBG_STAT].size = 10;\r
-                       arm7_9->has_monitor_mode = 1;\r
-                       break;\r
-               case 7:\r
-                       WARNING("EmbeddedICE version 7 detected, EmbeddedICE handling might be broken");\r
-                       reg_list[EICE_DBG_CTRL].size = 6;\r
-                       reg_list[EICE_DBG_STAT].size = 5;\r
-                       arm7_9->has_monitor_mode = 1;\r
-                       break;\r
-               default:\r
-                       ERROR("unknown EmbeddedICE version (comms ctrl: 0x%8.8x)", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));\r
-       }\r
-       \r
-       /* explicitly disable monitor mode */\r
-       if (arm7_9->has_monitor_mode)\r
-       {\r
-               embeddedice_read_reg(&reg_list[EICE_DBG_CTRL]);\r
-               jtag_execute_queue();\r
-               buf_set_u32(reg_list[EICE_DBG_CTRL].value, 4, 1, 0);\r
-               embeddedice_set_reg_w_exec(&reg_list[EICE_DBG_CTRL], reg_list[EICE_DBG_CTRL].value);\r
-       }\r
-       \r
-       return reg_cache;\r
-}\r
-\r
-int embeddedice_get_reg(reg_t *reg)\r
-{\r
-       if (embeddedice_read_reg(reg) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling EmbeddedICE register read");\r
-               exit(-1);\r
-       }\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register read failed");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)\r
-{\r
-       embeddedice_reg_t *ice_reg = reg->arch_info;\r
-       u8 reg_addr = ice_reg->addr & 0x1f;\r
-       scan_field_t fields[3];\r
-       u8 field1_out[1];\r
-       u8 field2_out[1];\r
-\r
-       DEBUG("%i", ice_reg->addr);\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(ice_reg->jtag_info, 0x2);\r
-       \r
-       arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = ice_reg->jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = reg->value;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = ice_reg->jtag_info->chain_pos;\r
-       fields[1].num_bits = 5;\r
-       fields[1].out_value = field1_out;\r
-       buf_set_u32(fields[1].out_value, 0, 5, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = ice_reg->jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = field2_out;\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       fields[0].in_value = reg->value;\r
-       jtag_set_check_value(fields+0, check_value, check_mask, NULL);\r
-       \r
-       /* when reading the DCC data register, leaving the address field set to\r
-        * EICE_COMMS_DATA would read the register twice\r
-        * reading the control register is safe\r
-        */\r
-       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* receive <size> words of 32 bit from the DCC\r
- * we pretend the target is always going to be fast enough\r
- * (relative to the JTAG clock), so we don't need to handshake\r
- */\r
-int embeddedice_receive(arm_jtag_t *jtag_info, u32 *data, u32 size)\r
-{\r
-       scan_field_t fields[3];\r
-       u8 field1_out[1];\r
-       u8 field2_out[1];\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0x2);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 5;\r
-       fields[1].out_value = field1_out;\r
-       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = field2_out;\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       while (size > 0)\r
-       {\r
-               /* when reading the last item, set the register address to the DCC control reg,\r
-                * to avoid reading additional data from the DCC data reg\r
-                */\r
-               if (size == 1)\r
-                       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);\r
-               \r
-               fields[0].in_handler = arm_jtag_buf_to_u32;\r
-               fields[0].in_handler_priv = data;\r
-               jtag_add_dr_scan(3, fields, -1);\r
-               \r
-               data++;\r
-               size--;\r
-       }\r
-       \r
-       return jtag_execute_queue();\r
-}\r
-\r
-int embeddedice_read_reg(reg_t *reg)\r
-{\r
-       return embeddedice_read_reg_w_check(reg, NULL, NULL);   \r
-}\r
-\r
-int embeddedice_set_reg(reg_t *reg, u32 value)\r
-{\r
-       if (embeddedice_write_reg(reg, value) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling EmbeddedICE register write");\r
-               exit(-1);\r
-       }\r
-       \r
-       buf_set_u32(reg->value, 0, reg->size, value);\r
-       reg->valid = 1;\r
-       reg->dirty = 0;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf)\r
-{\r
-       embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register write failed");\r
-               exit(-1);\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-int embeddedice_write_reg(reg_t *reg, u32 value)\r
-{\r
-       embeddedice_reg_t *ice_reg = reg->arch_info;\r
-       u8 reg_addr = ice_reg->addr & 0x1f;\r
-       scan_field_t fields[3];\r
-       u8 field0_out[4];\r
-       u8 field1_out[1];\r
-       u8 field2_out[1];\r
-\r
-       DEBUG("%i: 0x%8.8x", ice_reg->addr, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(ice_reg->jtag_info, 0x2);\r
-       \r
-       arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = ice_reg->jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = field0_out;\r
-       buf_set_u32(fields[0].out_value, 0, 32, value);\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = ice_reg->jtag_info->chain_pos;\r
-       fields[1].num_bits = 5;\r
-       fields[1].out_value = field1_out;\r
-       buf_set_u32(fields[1].out_value, 0, 5, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = ice_reg->jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = field2_out;\r
-       buf_set_u32(fields[2].out_value, 0, 1, 1);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int embeddedice_store_reg(reg_t *reg)\r
-{\r
-       return embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));\r
-}\r
-\r
-/* send <size> words of 32 bit to the DCC\r
- * we pretend the target is always going to be fast enough\r
- * (relative to the JTAG clock), so we don't need to handshake\r
- */\r
-int embeddedice_send(arm_jtag_t *jtag_info, u32 *data, u32 size)\r
-{\r
-       scan_field_t fields[3];\r
-       u8 field0_out[4];\r
-       u8 field1_out[1];\r
-       u8 field2_out[1];\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0x2);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = field0_out;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 5;\r
-       fields[1].out_value = field1_out;\r
-       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = field2_out;\r
-       buf_set_u32(fields[2].out_value, 0, 1, 1);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       while (size > 0)\r
-       {\r
-               buf_set_u32(fields[0].out_value, 0, 32, *data);\r
-               jtag_add_dr_scan(3, fields, -1);\r
-\r
-               data++;\r
-               size--;\r
-       }\r
-\r
-       /* call to jtag_execute_queue() intentionally omitted */\r
-       return ERROR_OK;\r
-}\r
-\r
-/* wait for DCC control register R/W handshake bit to become active\r
- */\r
-int embeddedice_handshake(arm_jtag_t *jtag_info, int hsbit, u32 timeout)\r
-{\r
-       scan_field_t fields[3];\r
-       u8 field0_in[4];\r
-       u8 field1_out[1];\r
-       u8 field2_out[1];\r
-       int retval;\r
-       int hsact;\r
-       struct timeval lap;\r
-       struct timeval now;\r
-\r
-       if (hsbit == EICE_COMM_CTRL_WBIT)\r
-               hsact = 1;\r
-       else if (hsbit == EICE_COMM_CTRL_RBIT)\r
-               hsact = 0;\r
-       else\r
-               return ERROR_INVALID_ARGUMENTS;\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(jtag_info, 0x2);\r
-       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);\r
-\r
-       fields[0].device = jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = field0_in;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = jtag_info->chain_pos;\r
-       fields[1].num_bits = 5;\r
-       fields[1].out_value = field1_out;\r
-       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = field2_out;\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-\r
-       jtag_add_dr_scan(3, fields, -1);\r
-       gettimeofday(&lap, NULL);\r
-       do\r
-       {\r
-               jtag_add_dr_scan(3, fields, -1);\r
-               if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-                       return retval;\r
-\r
-               if (buf_get_u32(field0_in, hsbit, 1) == hsact)\r
-                       return ERROR_OK;\r
-\r
-               gettimeofday(&now, NULL);\r
-       }\r
-       while ((now.tv_sec-lap.tv_sec)*1000 + (now.tv_usec-lap.tv_usec)/1000 <= timeout);\r
-\r
-       return ERROR_TARGET_TIMEOUT;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "embeddedice.h"
+
+#include "armv4_5.h"
+#include "arm7_9_common.h"
+
+#include "log.h"
+#include "arm_jtag.h"
+#include "types.h"
+#include "binarybuffer.h"
+#include "target.h"
+#include "register.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+bitfield_desc_t embeddedice_comms_ctrl_bitfield_desc[] = 
+{
+       {"R", 1},
+       {"W", 1},
+       {"reserved", 26},
+       {"version", 4}
+};
+
+int embeddedice_reg_arch_info[] =
+{
+       0x0, 0x1, 0x4, 0x5,
+       0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+       0x2
+};
+
+char* embeddedice_reg_list[] =
+{
+       "debug_ctrl",
+       "debug_status",
+       
+       "comms_ctrl",
+       "comms_data",
+       
+       "watch 0 addr value",
+       "watch 0 addr mask",
+       "watch 0 data value",
+       "watch 0 data mask",
+       "watch 0 control value",
+       "watch 0 control mask",
+       
+       "watch 1 addr value",
+       "watch 1 addr mask",
+       "watch 1 data value",
+       "watch 1 data mask",
+       "watch 1 control value",
+       "watch 1 control mask",
+       
+       "vector catch"
+};
+
+int embeddedice_reg_arch_type = -1;
+
+int embeddedice_get_reg(reg_t *reg);
+int embeddedice_set_reg(reg_t *reg, u32 value);
+int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int embeddedice_write_reg(reg_t *reg, u32 value);
+int embeddedice_read_reg(reg_t *reg);
+
+reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9)
+{
+       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
+       reg_t *reg_list = NULL;
+       embeddedice_reg_t *arch_info = NULL;
+       arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+       int num_regs;
+       int i;
+       int eice_version = 0;
+       
+       /* register a register arch-type for EmbeddedICE registers only once */
+       if (embeddedice_reg_arch_type == -1)
+               embeddedice_reg_arch_type = register_reg_arch_type(embeddedice_get_reg, embeddedice_set_reg_w_exec);
+       
+       if (arm7_9->has_vector_catch)
+               num_regs = 17;
+       else
+               num_regs = 16;
+               
+       /* the actual registers are kept in two arrays */
+       reg_list = calloc(num_regs, sizeof(reg_t));
+       arch_info = calloc(num_regs, sizeof(embeddedice_reg_t));
+       
+       /* fill in values for the reg cache */
+       reg_cache->name = "EmbeddedICE registers";
+       reg_cache->next = NULL;
+       reg_cache->reg_list = reg_list;
+       reg_cache->num_regs = num_regs;
+       
+       /* set up registers */
+       for (i = 0; i < num_regs; i++)
+       {
+               reg_list[i].name = embeddedice_reg_list[i];
+               reg_list[i].size = 32;
+               reg_list[i].dirty = 0;
+               reg_list[i].valid = 0;
+               reg_list[i].bitfield_desc = NULL;
+               reg_list[i].num_bitfields = 0;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].arch_info = &arch_info[i];
+               reg_list[i].arch_type = embeddedice_reg_arch_type;
+               arch_info[i].addr = embeddedice_reg_arch_info[i];
+               arch_info[i].jtag_info = jtag_info;
+       }
+       
+       /* identify EmbeddedICE version by reading DCC control register */
+       embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
+       jtag_execute_queue();
+       
+       eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
+       
+       switch (eice_version)
+       {
+               case 1:
+                       reg_list[EICE_DBG_CTRL].size = 3;
+                       reg_list[EICE_DBG_STAT].size = 5;
+                       break;
+               case 2:
+                       reg_list[EICE_DBG_CTRL].size = 4;
+                       reg_list[EICE_DBG_STAT].size = 5;
+                       arm7_9->has_single_step = 1;
+                       break;
+               case 3:
+                       ERROR("EmbeddedICE version 3 detected, EmbeddedICE handling might be broken"); 
+                       reg_list[EICE_DBG_CTRL].size = 6;
+                       reg_list[EICE_DBG_STAT].size = 5;
+                       arm7_9->has_single_step = 1;
+                       arm7_9->has_monitor_mode = 1;
+                       break;
+               case 4:
+                       reg_list[EICE_DBG_CTRL].size = 6;
+                       reg_list[EICE_DBG_STAT].size = 5;
+                       arm7_9->has_monitor_mode = 1;
+                       break;
+               case 5:
+                       reg_list[EICE_DBG_CTRL].size = 6;
+                       reg_list[EICE_DBG_STAT].size = 5;
+                       arm7_9->has_single_step = 1;
+                       arm7_9->has_monitor_mode = 1;
+                       break;
+               case 6:
+                       reg_list[EICE_DBG_CTRL].size = 6;
+                       reg_list[EICE_DBG_STAT].size = 10;
+                       arm7_9->has_monitor_mode = 1;
+                       break;
+               case 7:
+                       WARNING("EmbeddedICE version 7 detected, EmbeddedICE handling might be broken");
+                       reg_list[EICE_DBG_CTRL].size = 6;
+                       reg_list[EICE_DBG_STAT].size = 5;
+                       arm7_9->has_monitor_mode = 1;
+                       break;
+               default:
+                       ERROR("unknown EmbeddedICE version (comms ctrl: 0x%8.8x)", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
+       }
+       
+       /* explicitly disable monitor mode */
+       if (arm7_9->has_monitor_mode)
+       {
+               embeddedice_read_reg(&reg_list[EICE_DBG_CTRL]);
+               jtag_execute_queue();
+               buf_set_u32(reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
+               embeddedice_set_reg_w_exec(&reg_list[EICE_DBG_CTRL], reg_list[EICE_DBG_CTRL].value);
+       }
+       
+       return reg_cache;
+}
+
+int embeddedice_get_reg(reg_t *reg)
+{
+       if (embeddedice_read_reg(reg) != ERROR_OK)
+       {
+               ERROR("BUG: error scheduling EmbeddedICE register read");
+               exit(-1);
+       }
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("register read failed");
+       }
+       
+       return ERROR_OK;
+}
+
+int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
+{
+       embeddedice_reg_t *ice_reg = reg->arch_info;
+       u8 reg_addr = ice_reg->addr & 0x1f;
+       scan_field_t fields[3];
+       u8 field1_out[1];
+       u8 field2_out[1];
+
+       DEBUG("%i", ice_reg->addr);
+
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(ice_reg->jtag_info, 0x2);
+       
+       arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
+       
+       fields[0].device = ice_reg->jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = reg->value;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = ice_reg->jtag_info->chain_pos;
+       fields[1].num_bits = 5;
+       fields[1].out_value = field1_out;
+       buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = ice_reg->jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = field2_out;
+       buf_set_u32(fields[2].out_value, 0, 1, 0);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       fields[0].in_value = reg->value;
+       jtag_set_check_value(fields+0, check_value, check_mask, NULL);
+       
+       /* when reading the DCC data register, leaving the address field set to
+        * EICE_COMMS_DATA would read the register twice
+        * reading the control register is safe
+        */
+       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+       return ERROR_OK;
+}
+
+/* receive <size> words of 32 bit from the DCC
+ * we pretend the target is always going to be fast enough
+ * (relative to the JTAG clock), so we don't need to handshake
+ */
+int embeddedice_receive(arm_jtag_t *jtag_info, u32 *data, u32 size)
+{
+       scan_field_t fields[3];
+       u8 field1_out[1];
+       u8 field2_out[1];
+
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0x2);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+       
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 5;
+       fields[1].out_value = field1_out;
+       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = field2_out;
+       buf_set_u32(fields[2].out_value, 0, 1, 0);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       while (size > 0)
+       {
+               /* when reading the last item, set the register address to the DCC control reg,
+                * to avoid reading additional data from the DCC data reg
+                */
+               if (size == 1)
+                       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+               
+               fields[0].in_handler = arm_jtag_buf_to_u32;
+               fields[0].in_handler_priv = data;
+               jtag_add_dr_scan(3, fields, -1);
+               
+               data++;
+               size--;
+       }
+       
+       return jtag_execute_queue();
+}
+
+int embeddedice_read_reg(reg_t *reg)
+{
+       return embeddedice_read_reg_w_check(reg, NULL, NULL);   
+}
+
+int embeddedice_set_reg(reg_t *reg, u32 value)
+{
+       if (embeddedice_write_reg(reg, value) != ERROR_OK)
+       {
+               ERROR("BUG: error scheduling EmbeddedICE register write");
+               exit(-1);
+       }
+       
+       buf_set_u32(reg->value, 0, reg->size, value);
+       reg->valid = 1;
+       reg->dirty = 0;
+       
+       return ERROR_OK;
+}
+
+int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf)
+{
+       embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("register write failed");
+               exit(-1);
+       }
+       return ERROR_OK;
+}
+
+int embeddedice_write_reg(reg_t *reg, u32 value)
+{
+       embeddedice_reg_t *ice_reg = reg->arch_info;
+       u8 reg_addr = ice_reg->addr & 0x1f;
+       scan_field_t fields[3];
+       u8 field0_out[4];
+       u8 field1_out[1];
+       u8 field2_out[1];
+
+       DEBUG("%i: 0x%8.8x", ice_reg->addr, value);
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(ice_reg->jtag_info, 0x2);
+       
+       arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
+       
+       fields[0].device = ice_reg->jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = field0_out;
+       buf_set_u32(fields[0].out_value, 0, 32, value);
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = ice_reg->jtag_info->chain_pos;
+       fields[1].num_bits = 5;
+       fields[1].out_value = field1_out;
+       buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = ice_reg->jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = field2_out;
+       buf_set_u32(fields[2].out_value, 0, 1, 1);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       return ERROR_OK;
+}
+
+int embeddedice_store_reg(reg_t *reg)
+{
+       return embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
+/* send <size> words of 32 bit to the DCC
+ * we pretend the target is always going to be fast enough
+ * (relative to the JTAG clock), so we don't need to handshake
+ */
+int embeddedice_send(arm_jtag_t *jtag_info, u32 *data, u32 size)
+{
+       scan_field_t fields[3];
+       u8 field0_out[4];
+       u8 field1_out[1];
+       u8 field2_out[1];
+
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0x2);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = field0_out;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 5;
+       fields[1].out_value = field1_out;
+       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = field2_out;
+       buf_set_u32(fields[2].out_value, 0, 1, 1);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       while (size > 0)
+       {
+               buf_set_u32(fields[0].out_value, 0, 32, *data);
+               jtag_add_dr_scan(3, fields, -1);
+
+               data++;
+               size--;
+       }
+
+       /* call to jtag_execute_queue() intentionally omitted */
+       return ERROR_OK;
+}
+
+/* wait for DCC control register R/W handshake bit to become active
+ */
+int embeddedice_handshake(arm_jtag_t *jtag_info, int hsbit, u32 timeout)
+{
+       scan_field_t fields[3];
+       u8 field0_in[4];
+       u8 field1_out[1];
+       u8 field2_out[1];
+       int retval;
+       int hsact;
+       struct timeval lap;
+       struct timeval now;
+
+       if (hsbit == EICE_COMM_CTRL_WBIT)
+               hsact = 1;
+       else if (hsbit == EICE_COMM_CTRL_RBIT)
+               hsact = 0;
+       else
+               return ERROR_INVALID_ARGUMENTS;
+
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(jtag_info, 0x2);
+       arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+       fields[0].device = jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = field0_in;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = jtag_info->chain_pos;
+       fields[1].num_bits = 5;
+       fields[1].out_value = field1_out;
+       buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = field2_out;
+       buf_set_u32(fields[2].out_value, 0, 1, 0);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+
+       jtag_add_dr_scan(3, fields, -1);
+       gettimeofday(&lap, NULL);
+       do
+       {
+               jtag_add_dr_scan(3, fields, -1);
+               if ((retval = jtag_execute_queue()) != ERROR_OK)
+                       return retval;
+
+               if (buf_get_u32(field0_in, hsbit, 1) == hsact)
+                       return ERROR_OK;
+
+               gettimeofday(&now, NULL);
+       }
+       while ((now.tv_sec-lap.tv_sec)*1000 + (now.tv_usec-lap.tv_usec)/1000 <= timeout);
+
+       return ERROR_TARGET_TIMEOUT;
+}
index 6c9d3a0c139f5f5dbb842634ce5b2ec898200cfa..ff4113e5c1e568b1550464c55566803bf420fff6 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 <string.h>\r
-\r
-#include "arm7_9_common.h"\r
-#include "etb.h"\r
-#include "etm.h"\r
-\r
-#include "log.h"\r
-#include "types.h"\r
-#include "binarybuffer.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "jtag.h"\r
-\r
-#include <stdlib.h>\r
-\r
-char* etb_reg_list[] =\r
-{\r
-       "ETB_identification",\r
-       "ETB_ram_depth",\r
-       "ETB_ram_width",\r
-       "ETB_status",\r
-       "ETB_ram_data",\r
-       "ETB_ram_read_pointer",\r
-       "ETB_ram_write_pointer",\r
-       "ETB_trigger_counter",\r
-       "ETB_control",\r
-};\r
-\r
-int etb_reg_arch_type = -1;\r
-\r
-int etb_get_reg(reg_t *reg);\r
-int etb_set_reg(reg_t *reg, u32 value);\r
-int etb_set_reg_w_exec(reg_t *reg, u8 *buf);\r
-\r
-int etb_write_reg(reg_t *reg, u32 value);\r
-int etb_read_reg(reg_t *reg);\r
-\r
-int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int etb_set_instr(etb_t *etb, u32 new_instr)\r
-{\r
-       jtag_device_t *device = jtag_get_device(etb->chain_pos);\r
-       \r
-       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
-       {\r
-               scan_field_t field;\r
-       \r
-               field.device = etb->chain_pos;\r
-               field.num_bits = device->ir_length;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-                               \r
-               jtag_add_ir_scan(1, &field, -1);\r
-               \r
-               free(field.out_value);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_scann(etb_t *etb, u32 new_scan_chain)\r
-{\r
-       if(etb->cur_scan_chain != new_scan_chain)\r
-       {\r
-               scan_field_t field;\r
-               \r
-               field.device = etb->chain_pos;\r
-               field.num_bits = 5;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               field.in_check_value = NULL;\r
-               field.in_check_mask = NULL;\r
-               field.in_handler = NULL;\r
-               field.in_handler_priv = NULL;\r
-               \r
-               /* select INTEST instruction */\r
-               etb_set_instr(etb, 0x2);\r
-               jtag_add_dr_scan(1, &field, -1);\r
-               \r
-               etb->cur_scan_chain = new_scan_chain;\r
-               \r
-               free(field.out_value);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-reg_cache_t* etb_build_reg_cache(etb_t *etb)\r
-{\r
-       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));\r
-       reg_t *reg_list = NULL;\r
-       etb_reg_t *arch_info = NULL;\r
-       int num_regs = 9;\r
-       int i;\r
-       \r
-       /* register a register arch-type for etm registers only once */\r
-       if (etb_reg_arch_type == -1)\r
-               etb_reg_arch_type = register_reg_arch_type(etb_get_reg, etb_set_reg_w_exec);\r
-       \r
-       /* the actual registers are kept in two arrays */\r
-       reg_list = calloc(num_regs, sizeof(reg_t));\r
-       arch_info = calloc(num_regs, sizeof(etb_reg_t));\r
-       \r
-       /* fill in values for the reg cache */\r
-       reg_cache->name = "etb registers";\r
-       reg_cache->next = NULL;\r
-       reg_cache->reg_list = reg_list;\r
-       reg_cache->num_regs = num_regs;\r
-       \r
-       /* set up registers */\r
-       for (i = 0; i < num_regs; i++)\r
-       {\r
-               reg_list[i].name = etb_reg_list[i];\r
-               reg_list[i].size = 32;\r
-               reg_list[i].dirty = 0;\r
-               reg_list[i].valid = 0;\r
-               reg_list[i].bitfield_desc = NULL;\r
-               reg_list[i].num_bitfields = 0;\r
-               reg_list[i].value = calloc(1, 4);\r
-               reg_list[i].arch_info = &arch_info[i];\r
-               reg_list[i].arch_type = etb_reg_arch_type;\r
-               reg_list[i].size = 32;\r
-               arch_info[i].addr = i;\r
-               arch_info[i].etb = etb;\r
-       }\r
-       \r
-       return reg_cache;\r
-}\r
-\r
-int etb_get_reg(reg_t *reg)\r
-{\r
-       if (etb_read_reg(reg) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling etm register read");\r
-               exit(-1);\r
-       }\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register read failed");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_read_ram(etb_t *etb, u32 *data, int num_frames)\r
-{\r
-       scan_field_t fields[3];\r
-       int i;\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       etb_scann(etb, 0x0);\r
-       etb_set_instr(etb, 0xc);\r
-       \r
-       fields[0].device = etb->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etb->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, 4);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etb->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       fields[0].in_handler = buf_to_u32_handler;\r
-       \r
-       for (i = 0; i < num_frames; i++)\r
-       {\r
-               /* ensure nR/W reamins set to read */\r
-               buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-               \r
-               /* address remains set to 0x4 (RAM data) until we read the last frame */\r
-               if (i < num_frames - 1)\r
-                       buf_set_u32(fields[1].out_value, 0, 7, 4);\r
-               else\r
-                       buf_set_u32(fields[1].out_value, 0, 7, 0);\r
-               \r
-               fields[0].in_handler_priv = &data[i];\r
-               jtag_add_dr_scan(3, fields, -1);\r
-       }\r
-       \r
-       jtag_execute_queue();\r
-       \r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)\r
-{\r
-       etb_reg_t *etb_reg = reg->arch_info;\r
-       u8 reg_addr = etb_reg->addr & 0x7f;\r
-       scan_field_t fields[3];\r
-       \r
-       DEBUG("%i", etb_reg->addr);\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       etb_scann(etb_reg->etb, 0x0);\r
-       etb_set_instr(etb_reg->etb, 0xc);\r
-       \r
-       fields[0].device = etb_reg->etb->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = reg->value;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etb_reg->etb->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etb_reg->etb->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       /* read the identification register in the second run, to make sure we\r
-        * don't read the ETB data register twice, skipping every second entry\r
-        */\r
-       buf_set_u32(fields[1].out_value, 0, 7, 0x0);\r
-       fields[0].in_value = reg->value;\r
-       \r
-       jtag_set_check_value(fields+0, check_value, check_mask, NULL);\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_read_reg(reg_t *reg)\r
-{\r
-       return etb_read_reg_w_check(reg, NULL, NULL);   \r
-}\r
-\r
-int etb_set_reg(reg_t *reg, u32 value)\r
-{\r
-       if (etb_write_reg(reg, value) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling etm register write");\r
-               exit(-1);\r
-       }\r
-       \r
-       buf_set_u32(reg->value, 0, reg->size, value);\r
-       reg->valid = 1;\r
-       reg->dirty = 0;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_set_reg_w_exec(reg_t *reg, u8 *buf)\r
-{\r
-       etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register write failed");\r
-               exit(-1);\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_write_reg(reg_t *reg, u32 value)\r
-{\r
-       etb_reg_t *etb_reg = reg->arch_info;\r
-       u8 reg_addr = etb_reg->addr & 0x7f;\r
-       scan_field_t fields[3];\r
-       \r
-       DEBUG("%i: 0x%8.8x", etb_reg->addr, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       etb_scann(etb_reg->etb, 0x0);\r
-       etb_set_instr(etb_reg->etb, 0xc);\r
-       \r
-       fields[0].device = etb_reg->etb->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = malloc(4);\r
-       buf_set_u32(fields[0].out_value, 0, 32, value);\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etb_reg->etb->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etb_reg->etb->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 1);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       free(fields[0].out_value);\r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_store_reg(reg_t *reg)\r
-{\r
-       return etb_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));\r
-}\r
-\r
-int etb_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       command_t *etb_cmd;\r
-       \r
-       etb_cmd = register_command(cmd_ctx, NULL, "etb", NULL, COMMAND_ANY, "Embedded Trace Buffer");\r
-       \r
-       register_command(cmd_ctx, etb_cmd, "config", handle_etb_config_command, COMMAND_CONFIG, NULL);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       jtag_device_t *jtag_device;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       \r
-       if (argc != 2)\r
-       {\r
-               ERROR("incomplete 'etb config <target> <chain_pos>' command");\r
-               exit(-1);\r
-       }\r
-       \r
-       target = get_target_by_num(strtoul(args[0], NULL, 0));\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("target number '%s' not defined", args[0]);\r
-               exit(-1);\r
-       }\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       jtag_device = jtag_get_device(strtoul(args[1], NULL, 0));\r
-       \r
-       if (!jtag_device)\r
-       {\r
-               ERROR("jtag device number '%s' not defined", args[1]);\r
-               exit(-1);\r
-       }\r
-       \r
-       if (arm7_9->etm_ctx)\r
-       {\r
-               etb_t *etb = malloc(sizeof(etb_t));\r
-               \r
-               arm7_9->etm_ctx->capture_driver_priv = etb;\r
-               \r
-               etb->chain_pos = strtoul(args[1], NULL, 0);\r
-               etb->cur_scan_chain = -1;\r
-               etb->reg_cache = NULL;\r
-               etb->ram_width = 0;\r
-               etb->ram_depth = 0;\r
-       }\r
-       else\r
-       {\r
-               ERROR("target has no ETM defined, ETB left unconfigured");\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_init(etm_context_t *etm_ctx)\r
-{\r
-       etb_t *etb = etm_ctx->capture_driver_priv;\r
-       \r
-       etb->etm_ctx = etm_ctx;\r
-       \r
-       /* identify ETB RAM depth and width */\r
-       etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_DEPTH]);\r
-       etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WIDTH]);\r
-       jtag_execute_queue();\r
-\r
-       etb->ram_depth = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32);\r
-       etb->ram_width = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-trace_status_t etb_status(etm_context_t *etm_ctx)\r
-{\r
-       etb_t *etb = etm_ctx->capture_driver_priv;\r
-       \r
-       etb->etm_ctx = etm_ctx;\r
-       \r
-       /* if tracing is currently idle, return this information */\r
-       if (etm_ctx->capture_status == TRACE_IDLE)\r
-       {\r
-               return etm_ctx->capture_status;\r
-       }\r
-       else if (etm_ctx->capture_status & TRACE_RUNNING)\r
-       {\r
-               reg_t *etb_status_reg = &etb->reg_cache->reg_list[ETB_STATUS];\r
-               int etb_timeout = 100;\r
-               \r
-               /* trace is running, check the ETB status flags */\r
-               etb_get_reg(etb_status_reg);\r
-       \r
-               /* check Full bit to identify an overflow */\r
-               if (buf_get_u32(etb_status_reg->value, 0, 1) == 1)\r
-                       etm_ctx->capture_status |= TRACE_OVERFLOWED;\r
-\r
-               /* check Triggered bit to identify trigger condition */\r
-               if (buf_get_u32(etb_status_reg->value, 1, 1) == 1)\r
-                       etm_ctx->capture_status |= TRACE_TRIGGERED;\r
-\r
-               /* check AcqComp to identify trace completion */\r
-               if (buf_get_u32(etb_status_reg->value, 2, 1) == 1)\r
-               {\r
-                       while (etb_timeout-- && (buf_get_u32(etb_status_reg->value, 3, 1) == 0))\r
-                       {\r
-                               /* wait for data formatter idle */\r
-                               etb_get_reg(etb_status_reg);\r
-                       }\r
-                       \r
-                       if (etb_timeout == 0)\r
-                       {\r
-                               ERROR("AcqComp set but DFEmpty won't go high, ETB status: 0x%x",\r
-                                       buf_get_u32(etb_status_reg->value, 0, etb_status_reg->size));\r
-                       }\r
-                       \r
-                       if (!(etm_ctx->capture_status && TRACE_TRIGGERED))\r
-                       {\r
-                               ERROR("trace completed, but no trigger condition detected");\r
-                       }\r
-                       \r
-                       etm_ctx->capture_status &= ~TRACE_RUNNING;\r
-                       etm_ctx->capture_status |= TRACE_COMPLETED;\r
-               }\r
-       }\r
-       \r
-       return etm_ctx->capture_status;\r
-}\r
-\r
-int etb_read_trace(etm_context_t *etm_ctx)\r
-{\r
-       etb_t *etb = etm_ctx->capture_driver_priv;\r
-       int first_frame = 0;\r
-       int num_frames = etb->ram_depth;\r
-       u32 *trace_data = NULL;\r
-       int i, j;\r
-       \r
-       etb_read_reg(&etb->reg_cache->reg_list[ETB_STATUS]);\r
-       etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]);\r
-       jtag_execute_queue();\r
-       \r
-       /* check if we overflowed, and adjust first frame of the trace accordingly\r
-        * if we didn't overflow, read only up to the frame that would be written next,\r
-        * i.e. don't read invalid entries\r
-        */\r
-       if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))\r
-       {\r
-               first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);\r
-       }\r
-       else\r
-       {\r
-               num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);\r
-       }\r
-       \r
-       etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);\r
-\r
-       /* read data into temporary array for unpacking */      \r
-       trace_data = malloc(sizeof(u32) * num_frames);\r
-       etb_read_ram(etb, trace_data, num_frames);\r
-\r
-       if (etm_ctx->trace_depth > 0)\r
-       {\r
-               free(etm_ctx->trace_data);\r
-       }\r
-       \r
-       if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)\r
-               etm_ctx->trace_depth = num_frames * 3;\r
-       else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)\r
-               etm_ctx->trace_depth = num_frames * 2;\r
-       else\r
-               etm_ctx->trace_depth = num_frames;\r
-\r
-       etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);\r
-       \r
-       for (i = 0, j = 0; i < num_frames; i++)\r
-       {\r
-               if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)\r
-               {\r
-                       /* trace word j */\r
-                       etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;\r
-                       etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;\r
-                       etm_ctx->trace_data[j].flags = 0;\r
-                       if ((trace_data[i] & 0x80) >> 7)\r
-                       {\r
-                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;\r
-                       }\r
-                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)\r
-                       {\r
-                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;\r
-                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;\r
-                       }\r
-                       \r
-                       /* trace word j+1 */\r
-                       etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x100) >> 8;\r
-                       etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7800) >> 11;\r
-                       etm_ctx->trace_data[j+1].flags = 0;\r
-                       if ((trace_data[i] & 0x8000) >> 15)\r
-                       {\r
-                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;\r
-                       }\r
-                       if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)\r
-                       {\r
-                               etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;\r
-                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;\r
-                       }\r
-                       \r
-                       /* trace word j+2 */\r
-                       etm_ctx->trace_data[j+2].pipestat = (trace_data[i] & 0x10000) >> 16;\r
-                       etm_ctx->trace_data[j+2].packet = (trace_data[i] & 0x780000) >> 19;\r
-                       etm_ctx->trace_data[j+2].flags = 0;\r
-                       if ((trace_data[i] & 0x800000) >> 23)\r
-                       {\r
-                               etm_ctx->trace_data[j+2].flags |= ETMV1_TRACESYNC_CYCLE;\r
-                       }\r
-                       if (etm_ctx->trace_data[j+2].pipestat == STAT_TR)\r
-                       {\r
-                               etm_ctx->trace_data[j+2].pipestat = etm_ctx->trace_data[j+2].packet & 0x7;\r
-                               etm_ctx->trace_data[j+2].flags |= ETMV1_TRIGGER_CYCLE;\r
-                       }\r
-                       \r
-                       j += 3;\r
-               }\r
-               else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)\r
-               {\r
-                       /* trace word j */\r
-                       etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;\r
-                       etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;\r
-                       etm_ctx->trace_data[j].flags = 0;\r
-                       if ((trace_data[i] & 0x800) >> 11)\r
-                       {\r
-                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;\r
-                       }\r
-                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)\r
-                       {\r
-                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;\r
-                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;\r
-                       }\r
-\r
-                       /* trace word j+1 */\r
-                       etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x7000) >> 12;\r
-                       etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7f8000) >> 15;\r
-                       etm_ctx->trace_data[j+1].flags = 0;\r
-                       if ((trace_data[i] & 0x800000) >> 23)\r
-                       {\r
-                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;\r
-                       }\r
-                       if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)\r
-                       {\r
-                               etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;\r
-                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;\r
-                       }\r
-                       \r
-                       j += 2;\r
-               }\r
-               else\r
-               {\r
-                       /* trace word j */\r
-                       etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;\r
-                       etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;\r
-                       etm_ctx->trace_data[j].flags = 0;\r
-                       if ((trace_data[i] & 0x80000) >> 19)\r
-                       {\r
-                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;\r
-                       }\r
-                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)\r
-                       {\r
-                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;\r
-                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;\r
-                       }\r
-                       \r
-                       j += 1;\r
-               }\r
-       }\r
-       \r
-       free(trace_data);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etb_start_capture(etm_context_t *etm_ctx)\r
-{\r
-       etb_t *etb = etm_ctx->capture_driver_priv;\r
-       u32 etb_ctrl_value = 0x1;\r
-       u32 trigger_count;\r
-\r
-       if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED)\r
-       {\r
-               if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT)\r
-               {\r
-                       ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");\r
-                       return ERROR_ETM_PORTMODE_NOT_SUPPORTED;\r
-               }\r
-               etb_ctrl_value |= 0x2;\r
-       }\r
-       \r
-       if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_MUXED)\r
-               return ERROR_ETM_PORTMODE_NOT_SUPPORTED;\r
-       \r
-       trigger_count = (etb->ram_depth * etm_ctx->trigger_percent) / 100;\r
-       \r
-       etb_write_reg(&etb->reg_cache->reg_list[ETB_TRIGGER_COUNTER], trigger_count);\r
-       etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER], 0x0);\r
-       etb_write_reg(&etb->reg_cache->reg_list[ETB_CTRL], etb_ctrl_value);\r
-       jtag_execute_queue();\r
-       \r
-       /* we're starting a new trace, initialize capture status */\r
-       etm_ctx->capture_status = TRACE_RUNNING;\r
-       \r
-       return ERROR_OK; \r
-}\r
-\r
-int etb_stop_capture(etm_context_t *etm_ctx)\r
-{\r
-       etb_t *etb = etm_ctx->capture_driver_priv;\r
-       reg_t *etb_ctrl_reg = &etb->reg_cache->reg_list[ETB_CTRL];\r
-\r
-       etb_write_reg(etb_ctrl_reg, 0x0);\r
-       jtag_execute_queue();\r
-       \r
-       /* trace stopped, just clear running flag, but preserve others */ \r
-       etm_ctx->capture_status &= ~TRACE_RUNNING;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-etm_capture_driver_t etb_capture_driver =\r
-{\r
-       .name = "etb",\r
-       .register_commands = etb_register_commands,\r
-       .init = etb_init,\r
-       .status = etb_status,\r
-       .start_capture = etb_start_capture,\r
-       .stop_capture = etb_stop_capture,\r
-       .read_trace = etb_read_trace,\r
-};\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 <string.h>
+
+#include "arm7_9_common.h"
+#include "etb.h"
+#include "etm.h"
+
+#include "log.h"
+#include "types.h"
+#include "binarybuffer.h"
+#include "target.h"
+#include "register.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+char* etb_reg_list[] =
+{
+       "ETB_identification",
+       "ETB_ram_depth",
+       "ETB_ram_width",
+       "ETB_status",
+       "ETB_ram_data",
+       "ETB_ram_read_pointer",
+       "ETB_ram_write_pointer",
+       "ETB_trigger_counter",
+       "ETB_control",
+};
+
+int etb_reg_arch_type = -1;
+
+int etb_get_reg(reg_t *reg);
+int etb_set_reg(reg_t *reg, u32 value);
+int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int etb_write_reg(reg_t *reg, u32 value);
+int etb_read_reg(reg_t *reg);
+
+int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int etb_set_instr(etb_t *etb, u32 new_instr)
+{
+       jtag_device_t *device = jtag_get_device(etb->chain_pos);
+       
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+       
+               field.device = etb->chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+                               
+               jtag_add_ir_scan(1, &field, -1);
+               
+               free(field.out_value);
+       }
+       
+       return ERROR_OK;
+}
+
+int etb_scann(etb_t *etb, u32 new_scan_chain)
+{
+       if(etb->cur_scan_chain != new_scan_chain)
+       {
+               scan_field_t field;
+               
+               field.device = etb->chain_pos;
+               field.num_bits = 5;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               /* select INTEST instruction */
+               etb_set_instr(etb, 0x2);
+               jtag_add_dr_scan(1, &field, -1);
+               
+               etb->cur_scan_chain = new_scan_chain;
+               
+               free(field.out_value);
+       }
+
+       return ERROR_OK;
+}
+
+reg_cache_t* etb_build_reg_cache(etb_t *etb)
+{
+       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
+       reg_t *reg_list = NULL;
+       etb_reg_t *arch_info = NULL;
+       int num_regs = 9;
+       int i;
+       
+       /* register a register arch-type for etm registers only once */
+       if (etb_reg_arch_type == -1)
+               etb_reg_arch_type = register_reg_arch_type(etb_get_reg, etb_set_reg_w_exec);
+       
+       /* the actual registers are kept in two arrays */
+       reg_list = calloc(num_regs, sizeof(reg_t));
+       arch_info = calloc(num_regs, sizeof(etb_reg_t));
+       
+       /* fill in values for the reg cache */
+       reg_cache->name = "etb registers";
+       reg_cache->next = NULL;
+       reg_cache->reg_list = reg_list;
+       reg_cache->num_regs = num_regs;
+       
+       /* set up registers */
+       for (i = 0; i < num_regs; i++)
+       {
+               reg_list[i].name = etb_reg_list[i];
+               reg_list[i].size = 32;
+               reg_list[i].dirty = 0;
+               reg_list[i].valid = 0;
+               reg_list[i].bitfield_desc = NULL;
+               reg_list[i].num_bitfields = 0;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].arch_info = &arch_info[i];
+               reg_list[i].arch_type = etb_reg_arch_type;
+               reg_list[i].size = 32;
+               arch_info[i].addr = i;
+               arch_info[i].etb = etb;
+       }
+       
+       return reg_cache;
+}
+
+int etb_get_reg(reg_t *reg)
+{
+       if (etb_read_reg(reg) != ERROR_OK)
+       {
+               ERROR("BUG: error scheduling etm register read");
+               exit(-1);
+       }
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("register read failed");
+       }
+       
+       return ERROR_OK;
+}
+
+int etb_read_ram(etb_t *etb, u32 *data, int num_frames)
+{
+       scan_field_t fields[3];
+       int i;
+       
+       jtag_add_end_state(TAP_RTI);
+       etb_scann(etb, 0x0);
+       etb_set_instr(etb, 0xc);
+       
+       fields[0].device = etb->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = etb->chain_pos;
+       fields[1].num_bits = 7;
+       fields[1].out_value = malloc(1);
+       buf_set_u32(fields[1].out_value, 0, 7, 4);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = etb->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = malloc(1);
+       buf_set_u32(fields[2].out_value, 0, 1, 0);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+       fields[0].in_handler = buf_to_u32_handler;
+       
+       for (i = 0; i < num_frames; i++)
+       {
+               /* ensure nR/W reamins set to read */
+               buf_set_u32(fields[2].out_value, 0, 1, 0);
+               
+               /* address remains set to 0x4 (RAM data) until we read the last frame */
+               if (i < num_frames - 1)
+                       buf_set_u32(fields[1].out_value, 0, 7, 4);
+               else
+                       buf_set_u32(fields[1].out_value, 0, 7, 0);
+               
+               fields[0].in_handler_priv = &data[i];
+               jtag_add_dr_scan(3, fields, -1);
+       }
+       
+       jtag_execute_queue();
+       
+       free(fields[1].out_value);
+       free(fields[2].out_value);
+       
+       return ERROR_OK;
+}
+
+int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
+{
+       etb_reg_t *etb_reg = reg->arch_info;
+       u8 reg_addr = etb_reg->addr & 0x7f;
+       scan_field_t fields[3];
+       
+       DEBUG("%i", etb_reg->addr);
+
+       jtag_add_end_state(TAP_RTI);
+       etb_scann(etb_reg->etb, 0x0);
+       etb_set_instr(etb_reg->etb, 0xc);
+       
+       fields[0].device = etb_reg->etb->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = reg->value;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = etb_reg->etb->chain_pos;
+       fields[1].num_bits = 7;
+       fields[1].out_value = malloc(1);
+       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = etb_reg->etb->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = malloc(1);
+       buf_set_u32(fields[2].out_value, 0, 1, 0);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       /* read the identification register in the second run, to make sure we
+        * don't read the ETB data register twice, skipping every second entry
+        */
+       buf_set_u32(fields[1].out_value, 0, 7, 0x0);
+       fields[0].in_value = reg->value;
+       
+       jtag_set_check_value(fields+0, check_value, check_mask, NULL);
+       
+       jtag_add_dr_scan(3, fields, -1);
+
+       free(fields[1].out_value);
+       free(fields[2].out_value);
+       
+       return ERROR_OK;
+}
+
+int etb_read_reg(reg_t *reg)
+{
+       return etb_read_reg_w_check(reg, NULL, NULL);   
+}
+
+int etb_set_reg(reg_t *reg, u32 value)
+{
+       if (etb_write_reg(reg, value) != ERROR_OK)
+       {
+               ERROR("BUG: error scheduling etm register write");
+               exit(-1);
+       }
+       
+       buf_set_u32(reg->value, 0, reg->size, value);
+       reg->valid = 1;
+       reg->dirty = 0;
+       
+       return ERROR_OK;
+}
+
+int etb_set_reg_w_exec(reg_t *reg, u8 *buf)
+{
+       etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("register write failed");
+               exit(-1);
+       }
+       return ERROR_OK;
+}
+
+int etb_write_reg(reg_t *reg, u32 value)
+{
+       etb_reg_t *etb_reg = reg->arch_info;
+       u8 reg_addr = etb_reg->addr & 0x7f;
+       scan_field_t fields[3];
+       
+       DEBUG("%i: 0x%8.8x", etb_reg->addr, value);
+       
+       jtag_add_end_state(TAP_RTI);
+       etb_scann(etb_reg->etb, 0x0);
+       etb_set_instr(etb_reg->etb, 0xc);
+       
+       fields[0].device = etb_reg->etb->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = malloc(4);
+       buf_set_u32(fields[0].out_value, 0, 32, value);
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = etb_reg->etb->chain_pos;
+       fields[1].num_bits = 7;
+       fields[1].out_value = malloc(1);
+       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = etb_reg->etb->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = malloc(1);
+       buf_set_u32(fields[2].out_value, 0, 1, 1);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       free(fields[0].out_value);
+       free(fields[1].out_value);
+       free(fields[2].out_value);
+       
+       return ERROR_OK;
+}
+
+int etb_store_reg(reg_t *reg)
+{
+       return etb_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
+int etb_register_commands(struct command_context_s *cmd_ctx)
+{
+       command_t *etb_cmd;
+       
+       etb_cmd = register_command(cmd_ctx, NULL, "etb", NULL, COMMAND_ANY, "Embedded Trace Buffer");
+       
+       register_command(cmd_ctx, etb_cmd, "config", handle_etb_config_command, COMMAND_CONFIG, NULL);
+
+       return ERROR_OK;
+}
+
+int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       jtag_device_t *jtag_device;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       
+       if (argc != 2)
+       {
+               ERROR("incomplete 'etb config <target> <chain_pos>' command");
+               exit(-1);
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       jtag_device = jtag_get_device(strtoul(args[1], NULL, 0));
+       
+       if (!jtag_device)
+       {
+               ERROR("jtag device number '%s' not defined", args[1]);
+               exit(-1);
+       }
+       
+       if (arm7_9->etm_ctx)
+       {
+               etb_t *etb = malloc(sizeof(etb_t));
+               
+               arm7_9->etm_ctx->capture_driver_priv = etb;
+               
+               etb->chain_pos = strtoul(args[1], NULL, 0);
+               etb->cur_scan_chain = -1;
+               etb->reg_cache = NULL;
+               etb->ram_width = 0;
+               etb->ram_depth = 0;
+       }
+       else
+       {
+               ERROR("target has no ETM defined, ETB left unconfigured");
+       }
+
+       return ERROR_OK;
+}
+
+int etb_init(etm_context_t *etm_ctx)
+{
+       etb_t *etb = etm_ctx->capture_driver_priv;
+       
+       etb->etm_ctx = etm_ctx;
+       
+       /* identify ETB RAM depth and width */
+       etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_DEPTH]);
+       etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WIDTH]);
+       jtag_execute_queue();
+
+       etb->ram_depth = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32);
+       etb->ram_width = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);
+       
+       return ERROR_OK;
+}
+
+trace_status_t etb_status(etm_context_t *etm_ctx)
+{
+       etb_t *etb = etm_ctx->capture_driver_priv;
+       
+       etb->etm_ctx = etm_ctx;
+       
+       /* if tracing is currently idle, return this information */
+       if (etm_ctx->capture_status == TRACE_IDLE)
+       {
+               return etm_ctx->capture_status;
+       }
+       else if (etm_ctx->capture_status & TRACE_RUNNING)
+       {
+               reg_t *etb_status_reg = &etb->reg_cache->reg_list[ETB_STATUS];
+               int etb_timeout = 100;
+               
+               /* trace is running, check the ETB status flags */
+               etb_get_reg(etb_status_reg);
+       
+               /* check Full bit to identify an overflow */
+               if (buf_get_u32(etb_status_reg->value, 0, 1) == 1)
+                       etm_ctx->capture_status |= TRACE_OVERFLOWED;
+
+               /* check Triggered bit to identify trigger condition */
+               if (buf_get_u32(etb_status_reg->value, 1, 1) == 1)
+                       etm_ctx->capture_status |= TRACE_TRIGGERED;
+
+               /* check AcqComp to identify trace completion */
+               if (buf_get_u32(etb_status_reg->value, 2, 1) == 1)
+               {
+                       while (etb_timeout-- && (buf_get_u32(etb_status_reg->value, 3, 1) == 0))
+                       {
+                               /* wait for data formatter idle */
+                               etb_get_reg(etb_status_reg);
+                       }
+                       
+                       if (etb_timeout == 0)
+                       {
+                               ERROR("AcqComp set but DFEmpty won't go high, ETB status: 0x%x",
+                                       buf_get_u32(etb_status_reg->value, 0, etb_status_reg->size));
+                       }
+                       
+                       if (!(etm_ctx->capture_status && TRACE_TRIGGERED))
+                       {
+                               ERROR("trace completed, but no trigger condition detected");
+                       }
+                       
+                       etm_ctx->capture_status &= ~TRACE_RUNNING;
+                       etm_ctx->capture_status |= TRACE_COMPLETED;
+               }
+       }
+       
+       return etm_ctx->capture_status;
+}
+
+int etb_read_trace(etm_context_t *etm_ctx)
+{
+       etb_t *etb = etm_ctx->capture_driver_priv;
+       int first_frame = 0;
+       int num_frames = etb->ram_depth;
+       u32 *trace_data = NULL;
+       int i, j;
+       
+       etb_read_reg(&etb->reg_cache->reg_list[ETB_STATUS]);
+       etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]);
+       jtag_execute_queue();
+       
+       /* check if we overflowed, and adjust first frame of the trace accordingly
+        * if we didn't overflow, read only up to the frame that would be written next,
+        * i.e. don't read invalid entries
+        */
+       if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))
+       {
+               first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
+       }
+       else
+       {
+               num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
+       }
+       
+       etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
+
+       /* read data into temporary array for unpacking */      
+       trace_data = malloc(sizeof(u32) * num_frames);
+       etb_read_ram(etb, trace_data, num_frames);
+
+       if (etm_ctx->trace_depth > 0)
+       {
+               free(etm_ctx->trace_data);
+       }
+       
+       if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
+               etm_ctx->trace_depth = num_frames * 3;
+       else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+               etm_ctx->trace_depth = num_frames * 2;
+       else
+               etm_ctx->trace_depth = num_frames;
+
+       etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
+       
+       for (i = 0, j = 0; i < num_frames; i++)
+       {
+               if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
+               {
+                       /* trace word j */
+                       etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
+                       etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;
+                       etm_ctx->trace_data[j].flags = 0;
+                       if ((trace_data[i] & 0x80) >> 7)
+                       {
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
+                       
+                       /* trace word j+1 */
+                       etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x100) >> 8;
+                       etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7800) >> 11;
+                       etm_ctx->trace_data[j+1].flags = 0;
+                       if ((trace_data[i] & 0x8000) >> 15)
+                       {
+                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
+                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
+                       
+                       /* trace word j+2 */
+                       etm_ctx->trace_data[j+2].pipestat = (trace_data[i] & 0x10000) >> 16;
+                       etm_ctx->trace_data[j+2].packet = (trace_data[i] & 0x780000) >> 19;
+                       etm_ctx->trace_data[j+2].flags = 0;
+                       if ((trace_data[i] & 0x800000) >> 23)
+                       {
+                               etm_ctx->trace_data[j+2].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j+2].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j+2].pipestat = etm_ctx->trace_data[j+2].packet & 0x7;
+                               etm_ctx->trace_data[j+2].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
+                       
+                       j += 3;
+               }
+               else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+               {
+                       /* trace word j */
+                       etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
+                       etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
+                       etm_ctx->trace_data[j].flags = 0;
+                       if ((trace_data[i] & 0x800) >> 11)
+                       {
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
+
+                       /* trace word j+1 */
+                       etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x7000) >> 12;
+                       etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7f8000) >> 15;
+                       etm_ctx->trace_data[j+1].flags = 0;
+                       if ((trace_data[i] & 0x800000) >> 23)
+                       {
+                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
+                               etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
+                       
+                       j += 2;
+               }
+               else
+               {
+                       /* trace word j */
+                       etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
+                       etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
+                       etm_ctx->trace_data[j].flags = 0;
+                       if ((trace_data[i] & 0x80000) >> 19)
+                       {
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+                       }
+                       if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+                       {
+                               etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+                               etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+                       }
+                       
+                       j += 1;
+               }
+       }
+       
+       free(trace_data);
+       
+       return ERROR_OK;
+}
+
+int etb_start_capture(etm_context_t *etm_ctx)
+{
+       etb_t *etb = etm_ctx->capture_driver_priv;
+       u32 etb_ctrl_value = 0x1;
+       u32 trigger_count;
+
+       if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED)
+       {
+               if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT)
+               {
+                       ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");
+                       return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
+               }
+               etb_ctrl_value |= 0x2;
+       }
+       
+       if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_MUXED)
+               return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
+       
+       trigger_count = (etb->ram_depth * etm_ctx->trigger_percent) / 100;
+       
+       etb_write_reg(&etb->reg_cache->reg_list[ETB_TRIGGER_COUNTER], trigger_count);
+       etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER], 0x0);
+       etb_write_reg(&etb->reg_cache->reg_list[ETB_CTRL], etb_ctrl_value);
+       jtag_execute_queue();
+       
+       /* we're starting a new trace, initialize capture status */
+       etm_ctx->capture_status = TRACE_RUNNING;
+       
+       return ERROR_OK; 
+}
+
+int etb_stop_capture(etm_context_t *etm_ctx)
+{
+       etb_t *etb = etm_ctx->capture_driver_priv;
+       reg_t *etb_ctrl_reg = &etb->reg_cache->reg_list[ETB_CTRL];
+
+       etb_write_reg(etb_ctrl_reg, 0x0);
+       jtag_execute_queue();
+       
+       /* trace stopped, just clear running flag, but preserve others */ 
+       etm_ctx->capture_status &= ~TRACE_RUNNING;
+       
+       return ERROR_OK;
+}
+
+etm_capture_driver_t etb_capture_driver =
+{
+       .name = "etb",
+       .register_commands = etb_register_commands,
+       .init = etb_init,
+       .status = etb_status,
+       .start_capture = etb_start_capture,
+       .stop_capture = etb_stop_capture,
+       .read_trace = etb_read_trace,
+};
index 1a579cb39d7954e733652867810792b3dd139eef..e3dcb1d7ce76ce778fc6b1854053ecfc9c52521f 100644 (file)
@@ -1,75 +1,75 @@
-/***************************************************************************\r
- *   Copyright (C) 2007 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-#ifndef ETB_H\r
-#define ETB_H\r
-\r
-#include "command.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "arm_jtag.h"\r
-\r
-#include "etb.h"\r
-#include "etm.h"\r
-\r
-/* ETB registers */\r
-enum\r
-{\r
-    ETB_ID = 0x00,\r
-    ETB_RAM_DEPTH = 0x01,\r
-    ETB_RAM_WIDTH = 0x02,\r
-    ETB_STATUS = 0x03,\r
-    ETB_RAM_DATA = 0x04,\r
-    ETB_RAM_READ_POINTER = 0x05,\r
-    ETB_RAM_WRITE_POINTER = 0x06,\r
-    ETB_TRIGGER_COUNTER = 0x07,\r
-    ETB_CTRL = 0x08,\r
-};\r
-\r
-typedef struct etb_s\r
-{\r
-       etm_context_t *etm_ctx;\r
-       int chain_pos;\r
-       int cur_scan_chain;\r
-       reg_cache_t *reg_cache;\r
-       \r
-       /* ETB parameters */\r
-       int ram_depth;\r
-       int ram_width;\r
-} etb_t;\r
-\r
-typedef struct etb_reg_s\r
-{\r
-       int addr;\r
-       etb_t *etb;\r
-} etb_reg_t;\r
-\r
-extern etm_capture_driver_t etb_capture_driver;\r
-\r
-extern reg_cache_t* etb_build_reg_cache(etb_t *etb);\r
-extern int etb_read_reg(reg_t *reg);\r
-extern int etb_write_reg(reg_t *reg, u32 value);\r
-extern int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);\r
-extern int etb_store_reg(reg_t *reg);\r
-extern int etb_set_reg(reg_t *reg, u32 value);\r
-extern int etb_set_reg_w_exec(reg_t *reg, u8 *buf);\r
-\r
-extern int etb_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-#endif /* ETB_H */\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef ETB_H
+#define ETB_H
+
+#include "command.h"
+#include "target.h"
+#include "register.h"
+#include "arm_jtag.h"
+
+#include "etb.h"
+#include "etm.h"
+
+/* ETB registers */
+enum
+{
+    ETB_ID = 0x00,
+    ETB_RAM_DEPTH = 0x01,
+    ETB_RAM_WIDTH = 0x02,
+    ETB_STATUS = 0x03,
+    ETB_RAM_DATA = 0x04,
+    ETB_RAM_READ_POINTER = 0x05,
+    ETB_RAM_WRITE_POINTER = 0x06,
+    ETB_TRIGGER_COUNTER = 0x07,
+    ETB_CTRL = 0x08,
+};
+
+typedef struct etb_s
+{
+       etm_context_t *etm_ctx;
+       int chain_pos;
+       int cur_scan_chain;
+       reg_cache_t *reg_cache;
+       
+       /* ETB parameters */
+       int ram_depth;
+       int ram_width;
+} etb_t;
+
+typedef struct etb_reg_s
+{
+       int addr;
+       etb_t *etb;
+} etb_reg_t;
+
+extern etm_capture_driver_t etb_capture_driver;
+
+extern reg_cache_t* etb_build_reg_cache(etb_t *etb);
+extern int etb_read_reg(reg_t *reg);
+extern int etb_write_reg(reg_t *reg, u32 value);
+extern int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
+extern int etb_store_reg(reg_t *reg);
+extern int etb_set_reg(reg_t *reg, u32 value);
+extern int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+extern int etb_register_commands(struct command_context_s *cmd_ctx);
+
+#endif /* ETB_H */
index fe4ac77f6dd7386456b69edc828e17981a14a57d..8475a99fe9ca66a4c652118a3beef989a2253002 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 <string.h>\r
-\r
-#include "etm.h"\r
-#include "etb.h"\r
-\r
-#include "armv4_5.h"\r
-#include "arm7_9_common.h"\r
-#include "arm_disassembler.h"\r
-#include "arm_simulator.h"\r
-\r
-#include "log.h"\r
-#include "arm_jtag.h"\r
-#include "types.h"\r
-#include "binarybuffer.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "jtag.h"\r
-#include "fileio.h"\r
-\r
-#include <stdlib.h>\r
-\r
-/* ETM register access functionality \r
- * \r
- */\r
-\r
-bitfield_desc_t etm_comms_ctrl_bitfield_desc[] = \r
-{\r
-       {"R", 1},\r
-       {"W", 1},\r
-       {"reserved", 26},\r
-       {"version", 4}\r
-};\r
-\r
-int etm_reg_arch_info[] =\r
-{\r
-       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\r
-       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\r
-       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \r
-       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, \r
-       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,\r
-       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, \r
-       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\r
-       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\r
-       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, \r
-       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, \r
-       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,\r
-       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\r
-       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, \r
-       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, \r
-};\r
-\r
-int etm_reg_arch_size_info[] =\r
-{\r
-       32, 32, 17, 8, 3, 9, 32, 16,\r
-       17, 26, 25, 8, 17, 32, 32, 17,\r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       7, 7, 7, 7, 7, 7, 7, 7, \r
-       7, 7, 7, 7, 7, 7, 7, 7, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       16, 16, 16, 16, 18, 18, 18, 18,\r
-       17, 17, 17, 17, 16, 16, 16, 16,\r
-       17, 17, 17, 17, 17, 17, 2, \r
-       17, 17, 17, 17, 32, 32, 32, 32 \r
-};\r
-\r
-char* etm_reg_list[] =\r
-{\r
-       "ETM_CTRL",\r
-       "ETM_CONFIG",\r
-       "ETM_TRIG_EVENT",\r
-       "ETM_MMD_CTRL",\r
-       "ETM_STATUS",\r
-       "ETM_SYS_CONFIG",\r
-       "ETM_TRACE_RESOURCE_CTRL",\r
-       "ETM_TRACE_EN_CTRL2",\r
-       "ETM_TRACE_EN_EVENT",\r
-       "ETM_TRACE_EN_CTRL1",\r
-       "ETM_FIFOFULL_REGION",\r
-       "ETM_FIFOFULL_LEVEL",\r
-       "ETM_VIEWDATA_EVENT",\r
-       "ETM_VIEWDATA_CTRL1",\r
-       "ETM_VIEWDATA_CTRL2",\r
-       "ETM_VIEWDATA_CTRL3",\r
-       "ETM_ADDR_COMPARATOR_VALUE1",\r
-       "ETM_ADDR_COMPARATOR_VALUE2",\r
-       "ETM_ADDR_COMPARATOR_VALUE3",\r
-       "ETM_ADDR_COMPARATOR_VALUE4",\r
-       "ETM_ADDR_COMPARATOR_VALUE5",\r
-       "ETM_ADDR_COMPARATOR_VALUE6",\r
-       "ETM_ADDR_COMPARATOR_VALUE7",\r
-       "ETM_ADDR_COMPARATOR_VALUE8",\r
-       "ETM_ADDR_COMPARATOR_VALUE9",\r
-       "ETM_ADDR_COMPARATOR_VALUE10",\r
-       "ETM_ADDR_COMPARATOR_VALUE11",\r
-       "ETM_ADDR_COMPARATOR_VALUE12",\r
-       "ETM_ADDR_COMPARATOR_VALUE13",\r
-       "ETM_ADDR_COMPARATOR_VALUE14",\r
-       "ETM_ADDR_COMPARATOR_VALUE15",\r
-       "ETM_ADDR_COMPARATOR_VALUE16",\r
-       "ETM_ADDR_ACCESS_TYPE1",\r
-       "ETM_ADDR_ACCESS_TYPE2",\r
-       "ETM_ADDR_ACCESS_TYPE3",\r
-       "ETM_ADDR_ACCESS_TYPE4",\r
-       "ETM_ADDR_ACCESS_TYPE5",\r
-       "ETM_ADDR_ACCESS_TYPE6",\r
-       "ETM_ADDR_ACCESS_TYPE7",\r
-       "ETM_ADDR_ACCESS_TYPE8",\r
-       "ETM_ADDR_ACCESS_TYPE9",\r
-       "ETM_ADDR_ACCESS_TYPE10",\r
-       "ETM_ADDR_ACCESS_TYPE11",\r
-       "ETM_ADDR_ACCESS_TYPE12",\r
-       "ETM_ADDR_ACCESS_TYPE13",\r
-       "ETM_ADDR_ACCESS_TYPE14",\r
-       "ETM_ADDR_ACCESS_TYPE15",\r
-       "ETM_ADDR_ACCESS_TYPE16",\r
-       "ETM_DATA_COMPARATOR_VALUE1",\r
-       "ETM_DATA_COMPARATOR_VALUE2",\r
-       "ETM_DATA_COMPARATOR_VALUE3",\r
-       "ETM_DATA_COMPARATOR_VALUE4",\r
-       "ETM_DATA_COMPARATOR_VALUE5",\r
-       "ETM_DATA_COMPARATOR_VALUE6",\r
-       "ETM_DATA_COMPARATOR_VALUE7",\r
-       "ETM_DATA_COMPARATOR_VALUE8",\r
-       "ETM_DATA_COMPARATOR_VALUE9",\r
-       "ETM_DATA_COMPARATOR_VALUE10",\r
-       "ETM_DATA_COMPARATOR_VALUE11",\r
-       "ETM_DATA_COMPARATOR_VALUE12",\r
-       "ETM_DATA_COMPARATOR_VALUE13",\r
-       "ETM_DATA_COMPARATOR_VALUE14",\r
-       "ETM_DATA_COMPARATOR_VALUE15",\r
-       "ETM_DATA_COMPARATOR_VALUE16",\r
-       "ETM_DATA_COMPARATOR_MASK1",\r
-       "ETM_DATA_COMPARATOR_MASK2",\r
-       "ETM_DATA_COMPARATOR_MASK3",\r
-       "ETM_DATA_COMPARATOR_MASK4",\r
-       "ETM_DATA_COMPARATOR_MASK5",\r
-       "ETM_DATA_COMPARATOR_MASK6",\r
-       "ETM_DATA_COMPARATOR_MASK7",\r
-       "ETM_DATA_COMPARATOR_MASK8",\r
-       "ETM_DATA_COMPARATOR_MASK9",\r
-       "ETM_DATA_COMPARATOR_MASK10",\r
-       "ETM_DATA_COMPARATOR_MASK11",\r
-       "ETM_DATA_COMPARATOR_MASK12",\r
-       "ETM_DATA_COMPARATOR_MASK13",\r
-       "ETM_DATA_COMPARATOR_MASK14",\r
-       "ETM_DATA_COMPARATOR_MASK15",\r
-       "ETM_DATA_COMPARATOR_MASK16",\r
-       "ETM_COUNTER_INITAL_VALUE1",\r
-       "ETM_COUNTER_INITAL_VALUE2",\r
-       "ETM_COUNTER_INITAL_VALUE3",\r
-       "ETM_COUNTER_INITAL_VALUE4",\r
-       "ETM_COUNTER_ENABLE1",\r
-       "ETM_COUNTER_ENABLE2",\r
-       "ETM_COUNTER_ENABLE3",\r
-       "ETM_COUNTER_ENABLE4",\r
-       "ETM_COUNTER_RELOAD_VALUE1",\r
-       "ETM_COUNTER_RELOAD_VALUE2",\r
-       "ETM_COUNTER_RELOAD_VALUE3",\r
-       "ETM_COUNTER_RELOAD_VALUE4",\r
-       "ETM_COUNTER_VALUE1",\r
-       "ETM_COUNTER_VALUE2",\r
-       "ETM_COUNTER_VALUE3",\r
-       "ETM_COUNTER_VALUE4",\r
-       "ETM_SEQUENCER_CTRL1",\r
-       "ETM_SEQUENCER_CTRL2",\r
-       "ETM_SEQUENCER_CTRL3",\r
-       "ETM_SEQUENCER_CTRL4",\r
-       "ETM_SEQUENCER_CTRL5",\r
-       "ETM_SEQUENCER_CTRL6",\r
-       "ETM_SEQUENCER_STATE",\r
-       "ETM_EXTERNAL_OUTPUT1",\r
-       "ETM_EXTERNAL_OUTPUT2",\r
-       "ETM_EXTERNAL_OUTPUT3",\r
-       "ETM_EXTERNAL_OUTPUT4",\r
-       "ETM_CONTEXTID_COMPARATOR_VALUE1",\r
-       "ETM_CONTEXTID_COMPARATOR_VALUE2",\r
-       "ETM_CONTEXTID_COMPARATOR_VALUE3",\r
-       "ETM_CONTEXTID_COMPARATOR_MASK"\r
-};  \r
-\r
-int etm_reg_arch_type = -1;\r
-\r
-int etm_get_reg(reg_t *reg);\r
-int etm_set_reg(reg_t *reg, u32 value);\r
-int etm_set_reg_w_exec(reg_t *reg, u8 *buf);\r
-\r
-int etm_write_reg(reg_t *reg, u32 value);\r
-int etm_read_reg(reg_t *reg);\r
-\r
-command_t *etm_cmd = NULL;\r
-\r
-reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)\r
-{\r
-       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));\r
-       reg_t *reg_list = NULL;\r
-       etm_reg_t *arch_info = NULL;\r
-       int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);\r
-       int i;\r
-       u32 etm_ctrl_value;\r
-       \r
-       /* register a register arch-type for etm registers only once */\r
-       if (etm_reg_arch_type == -1)\r
-               etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);\r
-       \r
-       /* the actual registers are kept in two arrays */\r
-       reg_list = calloc(num_regs, sizeof(reg_t));\r
-       arch_info = calloc(num_regs, sizeof(etm_reg_t));\r
-       \r
-       /* fill in values for the reg cache */\r
-       reg_cache->name = "etm registers";\r
-       reg_cache->next = NULL;\r
-       reg_cache->reg_list = reg_list;\r
-       reg_cache->num_regs = num_regs;\r
-       \r
-       /* set up registers */\r
-       for (i = 0; i < num_regs; i++)\r
-       {\r
-               reg_list[i].name = etm_reg_list[i];\r
-               reg_list[i].size = 32;\r
-               reg_list[i].dirty = 0;\r
-               reg_list[i].valid = 0;\r
-               reg_list[i].bitfield_desc = NULL;\r
-               reg_list[i].num_bitfields = 0;\r
-               reg_list[i].value = calloc(1, 4);\r
-               reg_list[i].arch_info = &arch_info[i];\r
-               reg_list[i].arch_type = etm_reg_arch_type;\r
-               reg_list[i].size = etm_reg_arch_size_info[i];\r
-               arch_info[i].addr = etm_reg_arch_info[i];\r
-               arch_info[i].jtag_info = jtag_info;\r
-       }\r
-\r
-       /* initialize some ETM control register settings */     \r
-       etm_get_reg(&reg_list[ETM_CTRL]);\r
-       etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);\r
-       \r
-       /* clear the ETM powerdown bit (0) */\r
-       etm_ctrl_value &= ~0x1;\r
-               \r
-       /* configure port width (6:4), mode (17:16) and clocking (13) */\r
-       etm_ctrl_value = (etm_ctrl_value & \r
-               ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)\r
-               | etm_ctx->portmode;\r
-       \r
-       buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);\r
-       etm_store_reg(&reg_list[ETM_CTRL]);\r
-       \r
-       /* the ETM might have an ETB connected */\r
-       if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)\r
-       {\r
-               etb_t *etb = etm_ctx->capture_driver_priv;\r
-               \r
-               if (!etb)\r
-               {\r
-                       ERROR("etb selected as etm capture driver, but no ETB configured");\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               reg_cache->next = etb_build_reg_cache(etb);\r
-               \r
-               etb->reg_cache = reg_cache->next;\r
-       }\r
-       \r
-       if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)\r
-       {\r
-               ERROR("ETM capture driver initialization failed");\r
-               exit(-1);\r
-       }\r
-       \r
-       return reg_cache;\r
-}\r
-\r
-int etm_get_reg(reg_t *reg)\r
-{\r
-       if (etm_read_reg(reg) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling etm register read");\r
-               exit(-1);\r
-       }\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register read failed");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)\r
-{\r
-       etm_reg_t *etm_reg = reg->arch_info;\r
-       u8 reg_addr = etm_reg->addr & 0x7f;\r
-       scan_field_t fields[3];\r
-       \r
-       DEBUG("%i", etm_reg->addr);\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(etm_reg->jtag_info, 0x6);\r
-       arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = etm_reg->jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = reg->value;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etm_reg->jtag_info->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etm_reg->jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       fields[0].in_value = reg->value;\r
-       jtag_set_check_value(fields+0, check_value, check_mask, NULL);  \r
-               \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_read_reg(reg_t *reg)\r
-{\r
-       return etm_read_reg_w_check(reg, NULL, NULL);   \r
-}\r
-\r
-int etm_set_reg(reg_t *reg, u32 value)\r
-{\r
-       if (etm_write_reg(reg, value) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling etm register write");\r
-               exit(-1);\r
-       }\r
-       \r
-       buf_set_u32(reg->value, 0, reg->size, value);\r
-       reg->valid = 1;\r
-       reg->dirty = 0;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_set_reg_w_exec(reg_t *reg, u8 *buf)\r
-{\r
-       etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register write failed");\r
-               exit(-1);\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_write_reg(reg_t *reg, u32 value)\r
-{\r
-       etm_reg_t *etm_reg = reg->arch_info;\r
-       u8 reg_addr = etm_reg->addr & 0x7f;\r
-       scan_field_t fields[3];\r
-       \r
-       DEBUG("%i: 0x%8.8x", etm_reg->addr, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(etm_reg->jtag_info, 0x6);\r
-       arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = etm_reg->jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = malloc(4);\r
-       buf_set_u32(fields[0].out_value, 0, 32, value);\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etm_reg->jtag_info->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etm_reg->jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 1);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       free(fields[0].out_value);\r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_store_reg(reg_t *reg)\r
-{\r
-       return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));\r
-}\r
-\r
-/* ETM trace analysis functionality\r
- * \r
- */\r
-extern etm_capture_driver_t etb_capture_driver;\r
-extern etm_capture_driver_t etm_dummy_capture_driver;\r
-#if BUILD_OOCD_TRACE == 1\r
-extern etm_capture_driver_t oocd_trace_capture_driver;\r
-#endif\r
-\r
-etm_capture_driver_t *etm_capture_drivers[] = \r
-{\r
-       &etb_capture_driver,\r
-       &etm_dummy_capture_driver,\r
-#if BUILD_OOCD_TRACE == 1\r
-       &oocd_trace_capture_driver,\r
-#endif\r
-       NULL\r
-};\r
-\r
-char *etmv1v1_branch_reason_strings[] =\r
-{\r
-       "normal PC change",\r
-       "tracing enabled",\r
-       "trace restarted after overflow",\r
-       "exit from debug",\r
-       "periodic synchronization",\r
-       "reserved",\r
-       "reserved",\r
-       "reserved",\r
-};\r
-\r
-int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)\r
-{\r
-       int i;\r
-       int section = -1;\r
-       u32 size_read;\r
-       u32 opcode;\r
-       int retval;\r
-       \r
-       if (!ctx->image)\r
-               return ERROR_TRACE_IMAGE_UNAVAILABLE;\r
-       \r
-       /* search for the section the current instruction belongs to */ \r
-       for (i = 0; i < ctx->image->num_sections; i++)\r
-       {\r
-               if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&\r
-                       (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))\r
-               {\r
-                       section = i;\r
-                       break;\r
-               }\r
-       }\r
-       \r
-       if (section == -1)\r
-       {\r
-               /* current instruction couldn't be found in the image */\r
-               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-       }\r
-       \r
-       if (ctx->core_state == ARMV4_5_STATE_ARM)\r
-       {\r
-               u8 buf[4];\r
-               if ((retval = image_read_section(ctx->image, section, \r
-                       ctx->current_pc - ctx->image->sections[section].base_address,\r
-                       4, buf, &size_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("error while reading instruction: %i", retval);\r
-                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-               }\r
-               opcode = target_buffer_get_u32(ctx->target, buf);\r
-               arm_evaluate_opcode(opcode, ctx->current_pc, instruction);\r
-       }\r
-       else if (ctx->core_state == ARMV4_5_STATE_THUMB)\r
-       {\r
-               u8 buf[2];\r
-               if ((retval = image_read_section(ctx->image, section, \r
-                       ctx->current_pc - ctx->image->sections[section].base_address,\r
-                       2, buf, &size_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("error while reading instruction: %i", retval);\r
-                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-               }\r
-               opcode = target_buffer_get_u16(ctx->target, buf);\r
-               thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);\r
-       }\r
-       else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)\r
-       {\r
-               ERROR("BUG: tracing of jazelle code not supported");\r
-               exit(-1);\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: unknown core state encountered");\r
-               exit(-1);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)\r
-{\r
-       while (ctx->data_index < ctx->trace_depth)\r
-       {\r
-               /* if the caller specified an address packet offset, skip until the\r
-                * we reach the n-th cycle marked with tracesync */\r
-               if (apo > 0)\r
-               {\r
-                       if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)\r
-                               apo--;\r
-                       \r
-                       if (apo > 0)\r
-                       {\r
-                               ctx->data_index++;\r
-                               ctx->data_half = 0;\r
-                       }\r
-                       continue;\r
-               }\r
-               \r
-               /* no tracedata output during a TD cycle\r
-                * or in a trigger cycle */\r
-               if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)\r
-                       || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))\r
-               {\r
-                       ctx->data_index++;\r
-                       ctx->data_half = 0;\r
-                       continue;\r
-               }\r
-               \r
-               if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)\r
-               {\r
-                       if (ctx->data_half == 0)\r
-                       {\r
-                               *packet = ctx->trace_data[ctx->data_index].packet & 0xff;\r
-                               ctx->data_half = 1;\r
-                       }\r
-                       else\r
-                       {\r
-                               *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;\r
-                               ctx->data_half = 0;\r
-                               ctx->data_index++;\r
-                       }\r
-               }\r
-               else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)\r
-               {\r
-                       *packet = ctx->trace_data[ctx->data_index].packet & 0xff;\r
-                       ctx->data_index++;\r
-               }\r
-               else\r
-               {\r
-                       /* on a 4-bit port, a packet will be output during two consecutive cycles */\r
-                       if (ctx->data_index > (ctx->trace_depth - 2))\r
-                               return -1;\r
-                       \r
-                       *packet = ctx->trace_data[ctx->data_index].packet & 0xf;\r
-                       *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;\r
-                       ctx->data_index += 2;\r
-               }\r
-                                       \r
-               return 0;\r
-       }\r
-       \r
-       return -1;\r
-}\r
-\r
-int etmv1_branch_address(etm_context_t *ctx)\r
-{\r
-       int retval;\r
-       u8 packet;\r
-       int shift = 0;\r
-       int apo;\r
-       int i;\r
-       \r
-       /* quit analysis if less than two cycles are left in the trace\r
-        * because we can't extract the APO */\r
-       if (ctx->data_index > (ctx->trace_depth - 2))\r
-               return -1;\r
-               \r
-       /* a BE could be output during an APO cycle, skip the current\r
-        * and continue with the new one */\r
-       if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)\r
-               return 1;\r
-       if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)\r
-               return 2;\r
-               \r
-       /* address packet offset encoded in the next two cycles' pipestat bits */\r
-       apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;\r
-       apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;\r
-       \r
-       /* count number of tracesync cycles between current pipe_index and data_index\r
-        * i.e. the number of tracesyncs that data_index already passed by\r
-        * to subtract them from the APO */\r
-       for (i = ctx->pipe_index; i < ctx->data_index; i++)\r
-       {\r
-               if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)\r
-                       apo--;\r
-       }\r
-       \r
-       /* extract up to four 7-bit packets */\r
-       do {\r
-               if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)\r
-                       return -1;\r
-               ctx->last_branch &= ~(0x7f << shift);\r
-               ctx->last_branch |= (packet & 0x7f) << shift;\r
-               shift += 7;\r
-       } while ((packet & 0x80) && (shift < 28));\r
-       \r
-       /* one last packet holding 4 bits of the address, plus the branch reason code */\r
-       if ((shift == 28) && (packet & 0x80))\r
-       {\r
-               if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)\r
-                       return -1;\r
-               ctx->last_branch &= 0x0fffffff;\r
-               ctx->last_branch |= (packet & 0x0f) << 28;\r
-               ctx->last_branch_reason = (packet & 0x70) >> 4;\r
-               shift += 4;\r
-       }\r
-       else\r
-       {\r
-               ctx->last_branch_reason = 0;\r
-       }\r
-       \r
-       if (shift == 32)\r
-       {\r
-               ctx->pc_ok = 1;\r
-       }\r
-       \r
-       /* if a full address was output, we might have branched into Jazelle state */\r
-       if ((shift == 32) && (packet & 0x80))\r
-       {\r
-               ctx->core_state = ARMV4_5_STATE_JAZELLE;\r
-       }\r
-       else\r
-       {\r
-               /* if we didn't branch into Jazelle state, the current processor state is\r
-                * encoded in bit 0 of the branch target address */\r
-               if (ctx->last_branch & 0x1)\r
-               {\r
-                       ctx->core_state = ARMV4_5_STATE_THUMB;\r
-                       ctx->last_branch &= ~0x1;\r
-               }\r
-               else\r
-               {\r
-                       ctx->core_state = ARMV4_5_STATE_ARM;\r
-                       ctx->last_branch &= ~0x3;\r
-               }\r
-       }\r
-       \r
-       return 0;\r
-}\r
-\r
-int etmv1_data(etm_context_t *ctx, int size, u32 *data)\r
-{\r
-       int j;\r
-       u8 buf[4];\r
-       int retval;\r
-       \r
-       for (j = 0; j < size; j++)\r
-       {\r
-               if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)\r
-                       return -1;\r
-       }\r
-       \r
-       if (size == 8)\r
-               ERROR("TODO: add support for 64-bit values");\r
-       else if (size == 4)\r
-               *data = target_buffer_get_u32(ctx->target, buf);\r
-       else if (size == 2)\r
-               *data = target_buffer_get_u16(ctx->target, buf);\r
-       else if (size == 1)\r
-               *data = buf[0];\r
-               \r
-       return 0;\r
-}\r
-\r
-int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       arm_instruction_t instruction;\r
-       \r
-       /* read the trace data if it wasn't read already */\r
-       if (ctx->trace_depth == 0)\r
-               ctx->capture_driver->read_trace(ctx);\r
-       \r
-       /* start at the beginning of the captured trace */\r
-       ctx->pipe_index = 0;\r
-       ctx->data_index = 0;\r
-       ctx->data_half = 0;\r
-\r
-       /* neither the PC nor the data pointer are valid */     \r
-       ctx->pc_ok = 0;\r
-       ctx->ptr_ok = 0;\r
-       \r
-       while (ctx->pipe_index < ctx->trace_depth)\r
-       {\r
-               u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;\r
-               u32 next_pc = ctx->current_pc;\r
-               u32 old_data_index = ctx->data_index;\r
-               u32 old_data_half = ctx->data_half;\r
-               u32 old_index = ctx->pipe_index;\r
-               u32 last_instruction = ctx->last_instruction;\r
-               u32 cycles = 0;\r
-               int current_pc_ok = ctx->pc_ok;\r
-               \r
-               if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)\r
-               {\r
-                       command_print(cmd_ctx, "--- trigger ---");\r
-               }\r
-\r
-               /* instructions execute in IE/D or BE/D cycles */\r
-               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))\r
-                       ctx->last_instruction = ctx->pipe_index;\r
-               \r
-               /* if we don't have a valid pc skip until we reach an indirect branch */\r
-               if ((!ctx->pc_ok) && (pipestat != STAT_BE))\r
-               {\r
-                       ctx->pipe_index++;\r
-                       continue;\r
-               }\r
-               \r
-               /* any indirect branch could have interrupted instruction flow\r
-                * - the branch reason code could indicate a trace discontinuity\r
-                * - a branch to the exception vectors indicates an exception\r
-                */\r
-               if ((pipestat == STAT_BE) || (pipestat == STAT_BD))\r
-               {\r
-                       /* backup current data index, to be able to consume the branch address\r
-                        * before examining data address and values\r
-                        */\r
-                       old_data_index = ctx->data_index;\r
-                       old_data_half = ctx->data_half;\r
-\r
-                       ctx->last_instruction = ctx->pipe_index;\r
-                       \r
-                       if ((retval = etmv1_branch_address(ctx)) != 0)\r
-                       {\r
-                               /* negative return value from etmv1_branch_address means we ran out of packets,\r
-                                * quit analysing the trace */\r
-                               if (retval < 0)\r
-                                       break;\r
-                               \r
-                               /* a positive return values means the current branch was abandoned,\r
-                                * and a new branch was encountered in cycle ctx->pipe_index + retval;\r
-                                */\r
-                               WARNING("abandoned branch encountered, correctnes of analysis uncertain");\r
-                               ctx->pipe_index += retval;\r
-                               continue;\r
-                       }\r
-                       \r
-                       /* skip over APO cycles */\r
-                       ctx->pipe_index += 2;\r
-                       \r
-                       switch (ctx->last_branch_reason)\r
-                       {\r
-                               case 0x0:       /* normal PC change */\r
-                                       next_pc = ctx->last_branch;\r
-                                       break;\r
-                               case 0x1:       /* tracing enabled */\r
-                                       command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                                       break;\r
-                               case 0x2:       /* trace restarted after FIFO overflow */\r
-                                       command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                                       break;\r
-                               case 0x3:       /* exit from debug state */\r
-                                       command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                                       break;\r
-                               case 0x4:       /* periodic synchronization point */\r
-                                       next_pc = ctx->last_branch;\r
-                                       /* if we had no valid PC prior to this synchronization point,\r
-                                        * we have to move on with the next trace cycle\r
-                                        */\r
-                                       if (!current_pc_ok)\r
-                                       {\r
-                                               command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);\r
-                                               ctx->current_pc = next_pc;\r
-                                               ctx->pipe_index++;\r
-                                               continue;\r
-                                       }\r
-                                       break;\r
-                               default:        /* reserved */\r
-                                       ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);             \r
-                                       exit(-1);\r
-                                       break;\r
-                       }\r
-                       \r
-                       /* if we got here the branch was a normal PC change\r
-                        * (or a periodic synchronization point, which means the same for that matter)\r
-                        * if we didn't accquire a complete PC continue with the next cycle\r
-                        */\r
-                       if (!ctx->pc_ok)\r
-                               continue;\r
-                       \r
-                       /* indirect branch to the exception vector means an exception occured */\r
-                       if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))\r
-                               || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))\r
-                       {\r
-                               if ((ctx->last_branch & 0xff) == 0x10)\r
-                               {\r
-                                       command_print(cmd_ctx, "data abort");\r
-                               }\r
-                               else\r
-                               {\r
-                                       command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               /* an instruction was executed (or not, depending on the condition flags)\r
-                * retrieve it from the image for displaying */\r
-               if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&\r
-                       !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&\r
-                               ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  \r
-               {\r
-                       if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)\r
-                       {\r
-                               /* can't continue tracing with no image available */\r
-                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)\r
-                               {\r
-                                       return retval;\r
-                               }\r
-                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)\r
-                               {\r
-                                       /* TODO: handle incomplete images \r
-                                        * for now we just quit the analsysis*/\r
-                                       return retval;\r
-                               }\r
-                       }\r
-                       \r
-                       cycles = old_index - last_instruction;\r
-               }\r
-               \r
-               if ((pipestat == STAT_ID) || (pipestat == STAT_BD))\r
-               {\r
-                       u32 new_data_index = ctx->data_index;\r
-                       u32 new_data_half = ctx->data_half;\r
-                       \r
-                       /* in case of a branch with data, the branch target address was consumed before\r
-                        * we temporarily go back to the saved data index */\r
-                       if (pipestat == STAT_BD)\r
-                       {\r
-                               ctx->data_index = old_data_index;\r
-                               ctx->data_half = old_data_half;\r
-                       }\r
-                       \r
-                       if (ctx->tracemode & ETMV1_TRACE_ADDR)\r
-                       {                       \r
-                               u8 packet;\r
-                               int shift = 0;\r
-                               \r
-                               do {\r
-                                       if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)\r
-                                               return ERROR_ETM_ANALYSIS_FAILED;\r
-                                       ctx->last_ptr &= ~(0x7f << shift);\r
-                                       ctx->last_ptr |= (packet & 0x7f) << shift;\r
-                                       shift += 7;\r
-                               } while ((packet & 0x80) && (shift < 32));\r
-                               \r
-                               if (shift >= 32)\r
-                                       ctx->ptr_ok = 1;\r
-                               \r
-                               if (ctx->ptr_ok)\r
-                               {\r
-                                       command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);\r
-                               }\r
-                       }\r
-                       \r
-                       if (ctx->tracemode & ETMV1_TRACE_DATA)\r
-                       {\r
-                               if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))\r
-                               {\r
-                                       int i;\r
-                                       for (i = 0; i < 16; i++)\r
-                                       {\r
-                                               if (instruction.info.load_store_multiple.register_list & (1 << i))\r
-                                               {\r
-                                                       u32 data;\r
-                                                       if (etmv1_data(ctx, 4, &data) != 0)\r
-                                                               return ERROR_ETM_ANALYSIS_FAILED;\r
-                                                       command_print(cmd_ctx, "data: 0x%8.8x", data);\r
-                                               }\r
-                                       }\r
-                               }\r
-                               else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))\r
-                               {\r
-                                       u32 data;\r
-                                       if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)\r
-                                               return ERROR_ETM_ANALYSIS_FAILED;\r
-                                       command_print(cmd_ctx, "data: 0x%8.8x", data);\r
-                               }\r
-                       }\r
-                       \r
-                       /* restore data index after consuming BD address and data */\r
-                       if (pipestat == STAT_BD)\r
-                       {\r
-                               ctx->data_index = new_data_index;\r
-                               ctx->data_half = new_data_half;\r
-                       }\r
-               }\r
-               \r
-               /* adjust PC */\r
-               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))\r
-               {\r
-                       if (((instruction.type == ARM_B) ||\r
-                               (instruction.type == ARM_BL) ||\r
-                               (instruction.type == ARM_BLX)) &&\r
-                               (instruction.info.b_bl_bx_blx.target_address != -1))\r
-                       {\r
-                               next_pc = instruction.info.b_bl_bx_blx.target_address;\r
-                       }\r
-                       else\r
-                       {\r
-                               next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
-                       }\r
-               }\r
-               else if (pipestat == STAT_IN)\r
-               {\r
-                       next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
-               }\r
-\r
-               if ((pipestat != STAT_TD) && (pipestat != STAT_WT))\r
-               {\r
-                       char cycles_text[32] = "";\r
-                       \r
-                       /* if the trace was captured with cycle accurate tracing enabled,\r
-                        * output the number of cycles since the last executed instruction\r
-                        */\r
-                       if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)\r
-                       {\r
-                               snprintf(cycles_text, 32, " (%i %s)",\r
-                                       cycles,\r
-                                       (cycles == 1) ? "cycle" : "cycles");\r
-                       }\r
-                       \r
-                       command_print(cmd_ctx, "%s%s%s",\r
-                               instruction.text,\r
-                               (pipestat == STAT_IN) ? " (not executed)" : "",\r
-                               cycles_text);\r
-\r
-                       ctx->current_pc = next_pc;\r
-                       \r
-                       /* packets for an instruction don't start on or before the preceding\r
-                        * functional pipestat (i.e. other than WT or TD)\r
-                        */\r
-                       if (ctx->data_index <= ctx->pipe_index)\r
-                       {\r
-                               ctx->data_index = ctx->pipe_index + 1;\r
-                               ctx->data_half = 0;\r
-                       }\r
-               }\r
-               \r
-               ctx->pipe_index += 1;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etmv1_tracemode_t tracemode;\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!arm7_9->etm_ctx)\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       tracemode = arm7_9->etm_ctx->tracemode;\r
-\r
-       if (argc == 4)\r
-       {\r
-               if (strcmp(args[0], "none") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_NONE;\r
-               }\r
-               else if (strcmp(args[0], "data") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_DATA;\r
-               }\r
-               else if (strcmp(args[0], "address") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_ADDR;\r
-               }\r
-               else if (strcmp(args[0], "all") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "invalid option '%s'", args[0]);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               switch (strtol(args[1], NULL, 0))\r
-               {\r
-                       case 0:\r
-                               tracemode |= ETMV1_CONTEXTID_NONE;\r
-                               break;\r
-                       case 8:\r
-                               tracemode |= ETMV1_CONTEXTID_8;\r
-                               break;\r
-                       case 16:\r
-                               tracemode |= ETMV1_CONTEXTID_16;\r
-                               break;\r
-                       case 32:\r
-                               tracemode |= ETMV1_CONTEXTID_32;\r
-                               break;\r
-                       default:\r
-                               command_print(cmd_ctx, "invalid option '%s'", args[1]);\r
-                               return ERROR_OK;\r
-               }\r
-               \r
-               if (strcmp(args[2], "enable") == 0)\r
-               {\r
-                       tracemode |= ETMV1_CYCLE_ACCURATE;\r
-               }\r
-               else if (strcmp(args[2], "disable") == 0)\r
-               {\r
-                       tracemode |= 0;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "invalid option '%s'", args[2]);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               if (strcmp(args[3], "enable") == 0)\r
-               {\r
-                       tracemode |= ETMV1_BRANCH_OUTPUT;\r
-               }\r
-               else if (strcmp(args[3], "disable") == 0)\r
-               {\r
-                       tracemode |= 0;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "invalid option '%s'", args[2]);\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       else if (argc != 0)\r
-       {\r
-               command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       command_print(cmd_ctx, "current tracemode configuration:");\r
-       \r
-       switch (tracemode & ETMV1_TRACE_MASK)\r
-       {\r
-               case ETMV1_TRACE_NONE:\r
-                       command_print(cmd_ctx, "data tracing: none");\r
-                       break;\r
-               case ETMV1_TRACE_DATA:\r
-                       command_print(cmd_ctx, "data tracing: data only");\r
-                       break;\r
-               case ETMV1_TRACE_ADDR:\r
-                       command_print(cmd_ctx, "data tracing: address only");\r
-                       break;\r
-               case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:\r
-                       command_print(cmd_ctx, "data tracing: address and data");\r
-                       break;\r
-       }\r
-       \r
-       switch (tracemode & ETMV1_CONTEXTID_MASK)\r
-       {\r
-               case ETMV1_CONTEXTID_NONE:\r
-                       command_print(cmd_ctx, "contextid tracing: none");\r
-                       break;\r
-               case ETMV1_CONTEXTID_8:\r
-                       command_print(cmd_ctx, "contextid tracing: 8 bit");\r
-                       break;\r
-               case ETMV1_CONTEXTID_16:\r
-                       command_print(cmd_ctx, "contextid tracing: 16 bit");\r
-                       break;\r
-               case ETMV1_CONTEXTID_32:\r
-                       command_print(cmd_ctx, "contextid tracing: 32 bit");\r
-                       break;\r
-       }\r
-       \r
-       if (tracemode & ETMV1_CYCLE_ACCURATE)\r
-       {\r
-               command_print(cmd_ctx, "cycle-accurate tracing enabled");\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "cycle-accurate tracing disabled");\r
-       }\r
-\r
-       if (tracemode & ETMV1_BRANCH_OUTPUT)\r
-       {\r
-               command_print(cmd_ctx, "full branch address output enabled");\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "full branch address output disabled");\r
-       }\r
-       \r
-       /* only update ETM_CTRL register if tracemode changed */\r
-       if (arm7_9->etm_ctx->tracemode != tracemode)\r
-       {\r
-               reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
-               \r
-               etm_get_reg(etm_ctrl_reg);\r
-               \r
-               buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);\r
-               buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);\r
-               buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);\r
-               buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);\r
-               etm_store_reg(etm_ctrl_reg);\r
-               \r
-               arm7_9->etm_ctx->tracemode = tracemode;\r
-               \r
-               /* invalidate old trace data */\r
-               arm7_9->etm_ctx->capture_status = TRACE_IDLE;\r
-               if (arm7_9->etm_ctx->trace_depth > 0)\r
-               {\r
-                       free(arm7_9->etm_ctx->trace_data);\r
-                       arm7_9->etm_ctx->trace_data = NULL;\r
-               }\r
-               arm7_9->etm_ctx->trace_depth = 0;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_portmode_t portmode = 0x0;\r
-       etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));\r
-       int i;\r
-       \r
-       if (argc != 5)\r
-       {\r
-               ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");\r
-               exit(-1);\r
-       }\r
-       \r
-       target = get_target_by_num(strtoul(args[0], NULL, 0));\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("target number '%s' not defined", args[0]);\r
-               exit(-1);\r
-       }\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       switch (strtoul(args[1], NULL, 0))\r
-       {\r
-               case 4:\r
-                       portmode |= ETM_PORT_4BIT;\r
-                       break;\r
-               case 8:\r
-                       portmode |= ETM_PORT_8BIT;\r
-                       break;\r
-               case 16:\r
-                       portmode |= ETM_PORT_16BIT;\r
-                       break;\r
-               default:\r
-                       command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);\r
-                       return ERROR_OK;\r
-       }\r
-       \r
-       if (strcmp("normal", args[2]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_NORMAL;\r
-       }\r
-       else if (strcmp("multiplexed", args[2]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_MUXED;\r
-       }\r
-       else if (strcmp("demultiplexed", args[2]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_DEMUXED;\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (strcmp("half", args[3]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_HALF_CLOCK;\r
-       }\r
-       else if (strcmp("full", args[3]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_FULL_CLOCK;\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       for (i=0; etm_capture_drivers[i]; i++)\r
-       {\r
-               if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)\r
-               {\r
-                       if (etm_capture_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)\r
-                       {\r
-                               free(etm_ctx);\r
-                               exit(-1);\r
-                       }\r
-               \r
-                       etm_ctx->capture_driver = etm_capture_drivers[i];\r
-\r
-                       break;\r
-               }\r
-       }\r
-       \r
-       if (!etm_capture_drivers[i])\r
-       {\r
-               /* no supported capture driver found, don't register an ETM */\r
-               free(etm_ctx);\r
-               ERROR("trace capture driver '%s' not found", args[4]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       etm_ctx->target = target;\r
-       etm_ctx->trigger_percent = 50;\r
-       etm_ctx->trace_data = NULL;\r
-       etm_ctx->trace_depth = 0;\r
-       etm_ctx->portmode = portmode;\r
-       etm_ctx->tracemode = 0x0;\r
-       etm_ctx->core_state = ARMV4_5_STATE_ARM;\r
-       etm_ctx->image = NULL;\r
-       etm_ctx->pipe_index = 0;\r
-       etm_ctx->data_index = 0;\r
-       etm_ctx->current_pc = 0x0;\r
-       etm_ctx->pc_ok = 0;\r
-       etm_ctx->last_branch = 0x0;\r
-       etm_ctx->last_branch_reason = 0x0;\r
-       etm_ctx->last_ptr = 0x0;\r
-       etm_ctx->ptr_ok = 0x0;\r
-       etm_ctx->context_id = 0x0;\r
-       etm_ctx->last_instruction = 0;\r
-       \r
-       arm7_9->etm_ctx = etm_ctx;\r
-       \r
-       etm_register_user_commands(cmd_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       reg_t *etm_config_reg;\r
-       reg_t *etm_sys_config_reg;\r
-       \r
-       int max_port_size;\r
-               \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!arm7_9->etm_ctx)\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];\r
-       etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];\r
-       \r
-       etm_get_reg(etm_config_reg);\r
-       command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));\r
-       command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));\r
-       command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));\r
-       command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));\r
-       command_print(cmd_ctx, "sequencer %spresent",\r
-                       (buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));\r
-       command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));\r
-       command_print(cmd_ctx, "FIFO full %spresent",\r
-                       (buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));\r
-       \r
-       etm_get_reg(etm_sys_config_reg);\r
-\r
-       switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))\r
-       {\r
-               case 0:\r
-                       max_port_size = 4;\r
-                       break;\r
-               case 1:\r
-                       max_port_size = 8;\r
-                       break;\r
-               case 2:\r
-                       max_port_size = 16;\r
-                       break;\r
-       }\r
-       command_print(cmd_ctx, "max. port size: %i", max_port_size);\r
-       \r
-       command_print(cmd_ctx, "half-rate clocking %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "full-rate clocking %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "normal trace format %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "multiplex trace format %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "demultiplex trace format %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "FIFO full %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       trace_status_t trace_status;\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!arm7_9->etm_ctx)\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);\r
-       \r
-       if (trace_status == TRACE_IDLE)\r
-       {\r
-               command_print(cmd_ctx, "tracing is idle");\r
-       }\r
-       else\r
-       {\r
-               static char *completed = " completed";\r
-               static char *running = " is running";\r
-               static char *overflowed = ", trace overflowed";\r
-               static char *triggered = ", trace triggered";\r
-               \r
-               command_print(cmd_ctx, "trace collection%s%s%s", \r
-                       (trace_status & TRACE_RUNNING) ? running : completed,\r
-                       (trace_status & TRACE_OVERFLOWED) ? overflowed : "",\r
-                       (trace_status & TRACE_TRIGGERED) ? triggered : "");\r
-               \r
-               if (arm7_9->etm_ctx->trace_depth > 0)\r
-               {\r
-                       command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->image)\r
-       {\r
-               image_close(etm_ctx->image);\r
-               free(etm_ctx->image);\r
-               command_print(cmd_ctx, "previously loaded image found and closed");\r
-       }\r
-       \r
-       etm_ctx->image = malloc(sizeof(image_t));\r
-       etm_ctx->image->base_address_set = 0;\r
-       etm_ctx->image->start_address_set = 0;\r
-       \r
-       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */\r
-       if (argc >= 2)\r
-       {\r
-               etm_ctx->image->base_address_set = 1;\r
-               etm_ctx->image->base_address = strtoul(args[1], NULL, 0);\r
-       }\r
-       else\r
-       {\r
-               etm_ctx->image->base_address_set = 0;\r
-       }\r
-               \r
-       if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);\r
-               free(etm_ctx->image);\r
-               etm_ctx->image = NULL;\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       fileio_t file;\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       int i;\r
-       \r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: etm dump <file>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->capture_driver->status == TRACE_IDLE)\r
-       {\r
-               command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)\r
-       {\r
-               /* TODO: if on-the-fly capture is to be supported, this needs to be changed */\r
-               command_print(cmd_ctx, "trace capture not completed");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       /* read the trace data if it wasn't read already */\r
-       if (etm_ctx->trace_depth == 0)\r
-               etm_ctx->capture_driver->read_trace(etm_ctx);\r
-       \r
-       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "file open error: %s", file.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       fileio_write_u32(&file, etm_ctx->capture_status);\r
-       fileio_write_u32(&file, etm_ctx->portmode);\r
-       fileio_write_u32(&file, etm_ctx->tracemode);\r
-       fileio_write_u32(&file, etm_ctx->trace_depth);\r
-       \r
-       for (i = 0; i < etm_ctx->trace_depth; i++)\r
-       {\r
-               fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);\r
-               fileio_write_u32(&file, etm_ctx->trace_data[i].packet);\r
-               fileio_write_u32(&file, etm_ctx->trace_data[i].flags);\r
-       }\r
-       \r
-       fileio_close(&file);\r
-       \r
-       return ERROR_OK;        \r
-}\r
-\r
-int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       fileio_t file;\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       int i;\r
-       \r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: etm load <file>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)\r
-       {\r
-               command_print(cmd_ctx, "trace capture running, stop first");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "file open error: %s", file.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (file.size % 4)\r
-       {\r
-               command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->trace_depth > 0)\r
-       {\r
-               free(etm_ctx->trace_data);\r
-       }\r
-       \r
-       fileio_read_u32(&file, &etm_ctx->capture_status);\r
-       fileio_read_u32(&file, &etm_ctx->portmode);\r
-       fileio_read_u32(&file, &etm_ctx->tracemode);\r
-       fileio_read_u32(&file, &etm_ctx->trace_depth);\r
-       \r
-       etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);\r
-       \r
-       for (i = 0; i < etm_ctx->trace_depth; i++)\r
-       {\r
-               u32 pipestat, packet, flags;\r
-               fileio_read_u32(&file, &pipestat);\r
-               fileio_read_u32(&file, &packet);\r
-               fileio_read_u32(&file, &flags);\r
-               etm_ctx->trace_data[i].pipestat = pipestat & 0xff;\r
-               etm_ctx->trace_data[i].packet = packet & 0xffff;\r
-               etm_ctx->trace_data[i].flags = flags;\r
-       }\r
-       \r
-       fileio_close(&file);\r
-       \r
-       return ERROR_OK;        \r
-}\r
-\r
-int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (argc > 0)\r
-       {\r
-               u32 new_value = strtoul(args[0], NULL, 0);\r
-               \r
-               if ((new_value < 2) || (new_value > 100))\r
-               {\r
-                       command_print(cmd_ctx, "valid settings are 2% to 100%");\r
-               }\r
-               else\r
-               {\r
-                       etm_ctx->trigger_percent = new_value;\r
-               }\r
-       }\r
-       \r
-       command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       reg_t *etm_ctrl_reg;\r
-\r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       /* invalidate old tracing data */\r
-       arm7_9->etm_ctx->capture_status = TRACE_IDLE;\r
-       if (arm7_9->etm_ctx->trace_depth > 0)\r
-       {\r
-               free(arm7_9->etm_ctx->trace_data);\r
-               arm7_9->etm_ctx->trace_data = NULL;\r
-       }\r
-       arm7_9->etm_ctx->trace_depth = 0;\r
-               \r
-       etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
-       etm_get_reg(etm_ctrl_reg);\r
-               \r
-       /* Clear programming bit (10), set port selection bit (11) */\r
-       buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);\r
-\r
-       etm_store_reg(etm_ctrl_reg);\r
-       jtag_execute_queue();\r
-\r
-       etm_ctx->capture_driver->start_capture(etm_ctx);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       reg_t *etm_ctrl_reg;\r
-\r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
-       etm_get_reg(etm_ctrl_reg);\r
-               \r
-       /* Set programming bit (10), clear port selection bit (11) */\r
-       buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);\r
-\r
-       etm_store_reg(etm_ctrl_reg);    \r
-       jtag_execute_queue();\r
-       \r
-       etm_ctx->capture_driver->stop_capture(etm_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       int retval;\r
-\r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)\r
-       {\r
-               switch(retval)\r
-               {\r
-                       case ERROR_ETM_ANALYSIS_FAILED:\r
-                               command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");\r
-                               break;\r
-                       case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:\r
-                               command_print(cmd_ctx, "no instruction for current address available, analysis aborted");\r
-                               break;\r
-                       case ERROR_TRACE_IMAGE_UNAVAILABLE:\r
-                               command_print(cmd_ctx, "no image available for trace analysis");\r
-                               break;\r
-                       default:\r
-                               command_print(cmd_ctx, "unknown error: %i", retval);\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, NULL);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_register_user_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,\r
-               COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,\r
-               COMMAND_EXEC, "display info about the current target's ETM");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,\r
-               COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");\r
-       register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,\r
-               COMMAND_EXEC, "display current target's ETM status");\r
-       register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,\r
-               COMMAND_EXEC, "start ETM trace collection");\r
-       register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,\r
-               COMMAND_EXEC, "stop ETM trace collection");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,\r
-               COMMAND_EXEC, "anaylze collected ETM trace");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,\r
-               COMMAND_EXEC, "load image from <file> [base address]");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,\r
-               COMMAND_EXEC, "dump captured trace data <file>");\r
-       register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,\r
-               COMMAND_EXEC, "load trace data for analysis <file>");\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 <string.h>
+
+#include "etm.h"
+#include "etb.h"
+
+#include "armv4_5.h"
+#include "arm7_9_common.h"
+#include "arm_disassembler.h"
+#include "arm_simulator.h"
+
+#include "log.h"
+#include "arm_jtag.h"
+#include "types.h"
+#include "binarybuffer.h"
+#include "target.h"
+#include "register.h"
+#include "jtag.h"
+#include "fileio.h"
+
+#include <stdlib.h>
+
+/* ETM register access functionality 
+ * 
+ */
+
+bitfield_desc_t etm_comms_ctrl_bitfield_desc[] = 
+{
+       {"R", 1},
+       {"W", 1},
+       {"reserved", 26},
+       {"version", 4}
+};
+
+int etm_reg_arch_info[] =
+{
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
+       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
+       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
+       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 
+       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
+};
+
+int etm_reg_arch_size_info[] =
+{
+       32, 32, 17, 8, 3, 9, 32, 16,
+       17, 26, 25, 8, 17, 32, 32, 17,
+       32, 32, 32, 32, 32, 32, 32, 32, 
+       32, 32, 32, 32, 32, 32, 32, 32, 
+       7, 7, 7, 7, 7, 7, 7, 7, 
+       7, 7, 7, 7, 7, 7, 7, 7, 
+       32, 32, 32, 32, 32, 32, 32, 32, 
+       32, 32, 32, 32, 32, 32, 32, 32, 
+       32, 32, 32, 32, 32, 32, 32, 32, 
+       32, 32, 32, 32, 32, 32, 32, 32, 
+       16, 16, 16, 16, 18, 18, 18, 18,
+       17, 17, 17, 17, 16, 16, 16, 16,
+       17, 17, 17, 17, 17, 17, 2, 
+       17, 17, 17, 17, 32, 32, 32, 32 
+};
+
+char* etm_reg_list[] =
+{
+       "ETM_CTRL",
+       "ETM_CONFIG",
+       "ETM_TRIG_EVENT",
+       "ETM_MMD_CTRL",
+       "ETM_STATUS",
+       "ETM_SYS_CONFIG",
+       "ETM_TRACE_RESOURCE_CTRL",
+       "ETM_TRACE_EN_CTRL2",
+       "ETM_TRACE_EN_EVENT",
+       "ETM_TRACE_EN_CTRL1",
+       "ETM_FIFOFULL_REGION",
+       "ETM_FIFOFULL_LEVEL",
+       "ETM_VIEWDATA_EVENT",
+       "ETM_VIEWDATA_CTRL1",
+       "ETM_VIEWDATA_CTRL2",
+       "ETM_VIEWDATA_CTRL3",
+       "ETM_ADDR_COMPARATOR_VALUE1",
+       "ETM_ADDR_COMPARATOR_VALUE2",
+       "ETM_ADDR_COMPARATOR_VALUE3",
+       "ETM_ADDR_COMPARATOR_VALUE4",
+       "ETM_ADDR_COMPARATOR_VALUE5",
+       "ETM_ADDR_COMPARATOR_VALUE6",
+       "ETM_ADDR_COMPARATOR_VALUE7",
+       "ETM_ADDR_COMPARATOR_VALUE8",
+       "ETM_ADDR_COMPARATOR_VALUE9",
+       "ETM_ADDR_COMPARATOR_VALUE10",
+       "ETM_ADDR_COMPARATOR_VALUE11",
+       "ETM_ADDR_COMPARATOR_VALUE12",
+       "ETM_ADDR_COMPARATOR_VALUE13",
+       "ETM_ADDR_COMPARATOR_VALUE14",
+       "ETM_ADDR_COMPARATOR_VALUE15",
+       "ETM_ADDR_COMPARATOR_VALUE16",
+       "ETM_ADDR_ACCESS_TYPE1",
+       "ETM_ADDR_ACCESS_TYPE2",
+       "ETM_ADDR_ACCESS_TYPE3",
+       "ETM_ADDR_ACCESS_TYPE4",
+       "ETM_ADDR_ACCESS_TYPE5",
+       "ETM_ADDR_ACCESS_TYPE6",
+       "ETM_ADDR_ACCESS_TYPE7",
+       "ETM_ADDR_ACCESS_TYPE8",
+       "ETM_ADDR_ACCESS_TYPE9",
+       "ETM_ADDR_ACCESS_TYPE10",
+       "ETM_ADDR_ACCESS_TYPE11",
+       "ETM_ADDR_ACCESS_TYPE12",
+       "ETM_ADDR_ACCESS_TYPE13",
+       "ETM_ADDR_ACCESS_TYPE14",
+       "ETM_ADDR_ACCESS_TYPE15",
+       "ETM_ADDR_ACCESS_TYPE16",
+       "ETM_DATA_COMPARATOR_VALUE1",
+       "ETM_DATA_COMPARATOR_VALUE2",
+       "ETM_DATA_COMPARATOR_VALUE3",
+       "ETM_DATA_COMPARATOR_VALUE4",
+       "ETM_DATA_COMPARATOR_VALUE5",
+       "ETM_DATA_COMPARATOR_VALUE6",
+       "ETM_DATA_COMPARATOR_VALUE7",
+       "ETM_DATA_COMPARATOR_VALUE8",
+       "ETM_DATA_COMPARATOR_VALUE9",
+       "ETM_DATA_COMPARATOR_VALUE10",
+       "ETM_DATA_COMPARATOR_VALUE11",
+       "ETM_DATA_COMPARATOR_VALUE12",
+       "ETM_DATA_COMPARATOR_VALUE13",
+       "ETM_DATA_COMPARATOR_VALUE14",
+       "ETM_DATA_COMPARATOR_VALUE15",
+       "ETM_DATA_COMPARATOR_VALUE16",
+       "ETM_DATA_COMPARATOR_MASK1",
+       "ETM_DATA_COMPARATOR_MASK2",
+       "ETM_DATA_COMPARATOR_MASK3",
+       "ETM_DATA_COMPARATOR_MASK4",
+       "ETM_DATA_COMPARATOR_MASK5",
+       "ETM_DATA_COMPARATOR_MASK6",
+       "ETM_DATA_COMPARATOR_MASK7",
+       "ETM_DATA_COMPARATOR_MASK8",
+       "ETM_DATA_COMPARATOR_MASK9",
+       "ETM_DATA_COMPARATOR_MASK10",
+       "ETM_DATA_COMPARATOR_MASK11",
+       "ETM_DATA_COMPARATOR_MASK12",
+       "ETM_DATA_COMPARATOR_MASK13",
+       "ETM_DATA_COMPARATOR_MASK14",
+       "ETM_DATA_COMPARATOR_MASK15",
+       "ETM_DATA_COMPARATOR_MASK16",
+       "ETM_COUNTER_INITAL_VALUE1",
+       "ETM_COUNTER_INITAL_VALUE2",
+       "ETM_COUNTER_INITAL_VALUE3",
+       "ETM_COUNTER_INITAL_VALUE4",
+       "ETM_COUNTER_ENABLE1",
+       "ETM_COUNTER_ENABLE2",
+       "ETM_COUNTER_ENABLE3",
+       "ETM_COUNTER_ENABLE4",
+       "ETM_COUNTER_RELOAD_VALUE1",
+       "ETM_COUNTER_RELOAD_VALUE2",
+       "ETM_COUNTER_RELOAD_VALUE3",
+       "ETM_COUNTER_RELOAD_VALUE4",
+       "ETM_COUNTER_VALUE1",
+       "ETM_COUNTER_VALUE2",
+       "ETM_COUNTER_VALUE3",
+       "ETM_COUNTER_VALUE4",
+       "ETM_SEQUENCER_CTRL1",
+       "ETM_SEQUENCER_CTRL2",
+       "ETM_SEQUENCER_CTRL3",
+       "ETM_SEQUENCER_CTRL4",
+       "ETM_SEQUENCER_CTRL5",
+       "ETM_SEQUENCER_CTRL6",
+       "ETM_SEQUENCER_STATE",
+       "ETM_EXTERNAL_OUTPUT1",
+       "ETM_EXTERNAL_OUTPUT2",
+       "ETM_EXTERNAL_OUTPUT3",
+       "ETM_EXTERNAL_OUTPUT4",
+       "ETM_CONTEXTID_COMPARATOR_VALUE1",
+       "ETM_CONTEXTID_COMPARATOR_VALUE2",
+       "ETM_CONTEXTID_COMPARATOR_VALUE3",
+       "ETM_CONTEXTID_COMPARATOR_MASK"
+};  
+
+int etm_reg_arch_type = -1;
+
+int etm_get_reg(reg_t *reg);
+int etm_set_reg(reg_t *reg, u32 value);
+int etm_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int etm_write_reg(reg_t *reg, u32 value);
+int etm_read_reg(reg_t *reg);
+
+command_t *etm_cmd = NULL;
+
+reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
+{
+       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
+       reg_t *reg_list = NULL;
+       etm_reg_t *arch_info = NULL;
+       int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);
+       int i;
+       u32 etm_ctrl_value;
+       
+       /* register a register arch-type for etm registers only once */
+       if (etm_reg_arch_type == -1)
+               etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);
+       
+       /* the actual registers are kept in two arrays */
+       reg_list = calloc(num_regs, sizeof(reg_t));
+       arch_info = calloc(num_regs, sizeof(etm_reg_t));
+       
+       /* fill in values for the reg cache */
+       reg_cache->name = "etm registers";
+       reg_cache->next = NULL;
+       reg_cache->reg_list = reg_list;
+       reg_cache->num_regs = num_regs;
+       
+       /* set up registers */
+       for (i = 0; i < num_regs; i++)
+       {
+               reg_list[i].name = etm_reg_list[i];
+               reg_list[i].size = 32;
+               reg_list[i].dirty = 0;
+               reg_list[i].valid = 0;
+               reg_list[i].bitfield_desc = NULL;
+               reg_list[i].num_bitfields = 0;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].arch_info = &arch_info[i];
+               reg_list[i].arch_type = etm_reg_arch_type;
+               reg_list[i].size = etm_reg_arch_size_info[i];
+               arch_info[i].addr = etm_reg_arch_info[i];
+               arch_info[i].jtag_info = jtag_info;
+       }
+
+       /* initialize some ETM control register settings */     
+       etm_get_reg(&reg_list[ETM_CTRL]);
+       etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);
+       
+       /* clear the ETM powerdown bit (0) */
+       etm_ctrl_value &= ~0x1;
+               
+       /* configure port width (6:4), mode (17:16) and clocking (13) */
+       etm_ctrl_value = (etm_ctrl_value & 
+               ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)
+               | etm_ctx->portmode;
+       
+       buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);
+       etm_store_reg(&reg_list[ETM_CTRL]);
+       
+       /* the ETM might have an ETB connected */
+       if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)
+       {
+               etb_t *etb = etm_ctx->capture_driver_priv;
+               
+               if (!etb)
+               {
+                       ERROR("etb selected as etm capture driver, but no ETB configured");
+                       return ERROR_OK;
+               }
+               
+               reg_cache->next = etb_build_reg_cache(etb);
+               
+               etb->reg_cache = reg_cache->next;
+       }
+       
+       if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)
+       {
+               ERROR("ETM capture driver initialization failed");
+               exit(-1);
+       }
+       
+       return reg_cache;
+}
+
+int etm_get_reg(reg_t *reg)
+{
+       if (etm_read_reg(reg) != ERROR_OK)
+       {
+               ERROR("BUG: error scheduling etm register read");
+               exit(-1);
+       }
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("register read failed");
+       }
+       
+       return ERROR_OK;
+}
+
+int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
+{
+       etm_reg_t *etm_reg = reg->arch_info;
+       u8 reg_addr = etm_reg->addr & 0x7f;
+       scan_field_t fields[3];
+       
+       DEBUG("%i", etm_reg->addr);
+
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(etm_reg->jtag_info, 0x6);
+       arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
+       
+       fields[0].device = etm_reg->jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = reg->value;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = etm_reg->jtag_info->chain_pos;
+       fields[1].num_bits = 7;
+       fields[1].out_value = malloc(1);
+       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = etm_reg->jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = malloc(1);
+       buf_set_u32(fields[2].out_value, 0, 1, 0);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       fields[0].in_value = reg->value;
+       jtag_set_check_value(fields+0, check_value, check_mask, NULL);  
+               
+       jtag_add_dr_scan(3, fields, -1);
+
+       free(fields[1].out_value);
+       free(fields[2].out_value);
+       
+       return ERROR_OK;
+}
+
+int etm_read_reg(reg_t *reg)
+{
+       return etm_read_reg_w_check(reg, NULL, NULL);   
+}
+
+int etm_set_reg(reg_t *reg, u32 value)
+{
+       if (etm_write_reg(reg, value) != ERROR_OK)
+       {
+               ERROR("BUG: error scheduling etm register write");
+               exit(-1);
+       }
+       
+       buf_set_u32(reg->value, 0, reg->size, value);
+       reg->valid = 1;
+       reg->dirty = 0;
+       
+       return ERROR_OK;
+}
+
+int etm_set_reg_w_exec(reg_t *reg, u8 *buf)
+{
+       etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));
+       
+       if (jtag_execute_queue() != ERROR_OK)
+       {
+               ERROR("register write failed");
+               exit(-1);
+       }
+       return ERROR_OK;
+}
+
+int etm_write_reg(reg_t *reg, u32 value)
+{
+       etm_reg_t *etm_reg = reg->arch_info;
+       u8 reg_addr = etm_reg->addr & 0x7f;
+       scan_field_t fields[3];
+       
+       DEBUG("%i: 0x%8.8x", etm_reg->addr, value);
+       
+       jtag_add_end_state(TAP_RTI);
+       arm_jtag_scann(etm_reg->jtag_info, 0x6);
+       arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
+       
+       fields[0].device = etm_reg->jtag_info->chain_pos;
+       fields[0].num_bits = 32;
+       fields[0].out_value = malloc(4);
+       buf_set_u32(fields[0].out_value, 0, 32, value);
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+       
+       fields[1].device = etm_reg->jtag_info->chain_pos;
+       fields[1].num_bits = 7;
+       fields[1].out_value = malloc(1);
+       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       fields[2].device = etm_reg->jtag_info->chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = malloc(1);
+       buf_set_u32(fields[2].out_value, 0, 1, 1);
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_check_value = NULL;
+       fields[2].in_check_mask = NULL;
+       fields[2].in_handler = NULL;
+       fields[2].in_handler_priv = NULL;
+       
+       jtag_add_dr_scan(3, fields, -1);
+       
+       free(fields[0].out_value);
+       free(fields[1].out_value);
+       free(fields[2].out_value);
+       
+       return ERROR_OK;
+}
+
+int etm_store_reg(reg_t *reg)
+{
+       return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
+/* ETM trace analysis functionality
+ * 
+ */
+extern etm_capture_driver_t etb_capture_driver;
+extern etm_capture_driver_t etm_dummy_capture_driver;
+#if BUILD_OOCD_TRACE == 1
+extern etm_capture_driver_t oocd_trace_capture_driver;
+#endif
+
+etm_capture_driver_t *etm_capture_drivers[] = 
+{
+       &etb_capture_driver,
+       &etm_dummy_capture_driver,
+#if BUILD_OOCD_TRACE == 1
+       &oocd_trace_capture_driver,
+#endif
+       NULL
+};
+
+char *etmv1v1_branch_reason_strings[] =
+{
+       "normal PC change",
+       "tracing enabled",
+       "trace restarted after overflow",
+       "exit from debug",
+       "periodic synchronization",
+       "reserved",
+       "reserved",
+       "reserved",
+};
+
+int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
+{
+       int i;
+       int section = -1;
+       u32 size_read;
+       u32 opcode;
+       int retval;
+       
+       if (!ctx->image)
+               return ERROR_TRACE_IMAGE_UNAVAILABLE;
+       
+       /* search for the section the current instruction belongs to */ 
+       for (i = 0; i < ctx->image->num_sections; i++)
+       {
+               if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&
+                       (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))
+               {
+                       section = i;
+                       break;
+               }
+       }
+       
+       if (section == -1)
+       {
+               /* current instruction couldn't be found in the image */
+               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+       }
+       
+       if (ctx->core_state == ARMV4_5_STATE_ARM)
+       {
+               u8 buf[4];
+               if ((retval = image_read_section(ctx->image, section, 
+                       ctx->current_pc - ctx->image->sections[section].base_address,
+                       4, buf, &size_read)) != ERROR_OK)
+               {
+                       ERROR("error while reading instruction: %i", retval);
+                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+               }
+               opcode = target_buffer_get_u32(ctx->target, buf);
+               arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
+       }
+       else if (ctx->core_state == ARMV4_5_STATE_THUMB)
+       {
+               u8 buf[2];
+               if ((retval = image_read_section(ctx->image, section, 
+                       ctx->current_pc - ctx->image->sections[section].base_address,
+                       2, buf, &size_read)) != ERROR_OK)
+               {
+                       ERROR("error while reading instruction: %i", retval);
+                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+               }
+               opcode = target_buffer_get_u16(ctx->target, buf);
+               thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
+       }
+       else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
+       {
+               ERROR("BUG: tracing of jazelle code not supported");
+               exit(-1);
+       }
+       else
+       {
+               ERROR("BUG: unknown core state encountered");
+               exit(-1);
+       }
+       
+       return ERROR_OK;
+}
+
+int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)
+{
+       while (ctx->data_index < ctx->trace_depth)
+       {
+               /* if the caller specified an address packet offset, skip until the
+                * we reach the n-th cycle marked with tracesync */
+               if (apo > 0)
+               {
+                       if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)
+                               apo--;
+                       
+                       if (apo > 0)
+                       {
+                               ctx->data_index++;
+                               ctx->data_half = 0;
+                       }
+                       continue;
+               }
+               
+               /* no tracedata output during a TD cycle
+                * or in a trigger cycle */
+               if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)
+                       || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))
+               {
+                       ctx->data_index++;
+                       ctx->data_half = 0;
+                       continue;
+               }
+               
+               if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)
+               {
+                       if (ctx->data_half == 0)
+                       {
+                               *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
+                               ctx->data_half = 1;
+                       }
+                       else
+                       {
+                               *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;
+                               ctx->data_half = 0;
+                               ctx->data_index++;
+                       }
+               }
+               else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+               {
+                       *packet = ctx->trace_data[ctx->data_index].packet & 0xff;
+                       ctx->data_index++;
+               }
+               else
+               {
+                       /* on a 4-bit port, a packet will be output during two consecutive cycles */
+                       if (ctx->data_index > (ctx->trace_depth - 2))
+                               return -1;
+                       
+                       *packet = ctx->trace_data[ctx->data_index].packet & 0xf;
+                       *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;
+                       ctx->data_index += 2;
+               }
+                                       
+               return 0;
+       }
+       
+       return -1;
+}
+
+int etmv1_branch_address(etm_context_t *ctx)
+{
+       int retval;
+       u8 packet;
+       int shift = 0;
+       int apo;
+       int i;
+       
+       /* quit analysis if less than two cycles are left in the trace
+        * because we can't extract the APO */
+       if (ctx->data_index > (ctx->trace_depth - 2))
+               return -1;
+               
+       /* a BE could be output during an APO cycle, skip the current
+        * and continue with the new one */
+       if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)
+               return 1;
+       if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)
+               return 2;
+               
+       /* address packet offset encoded in the next two cycles' pipestat bits */
+       apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;
+       apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;
+       
+       /* count number of tracesync cycles between current pipe_index and data_index
+        * i.e. the number of tracesyncs that data_index already passed by
+        * to subtract them from the APO */
+       for (i = ctx->pipe_index; i < ctx->data_index; i++)
+       {
+               if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)
+                       apo--;
+       }
+       
+       /* extract up to four 7-bit packets */
+       do {
+               if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)
+                       return -1;
+               ctx->last_branch &= ~(0x7f << shift);
+               ctx->last_branch |= (packet & 0x7f) << shift;
+               shift += 7;
+       } while ((packet & 0x80) && (shift < 28));
+       
+       /* one last packet holding 4 bits of the address, plus the branch reason code */
+       if ((shift == 28) && (packet & 0x80))
+       {
+               if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
+                       return -1;
+               ctx->last_branch &= 0x0fffffff;
+               ctx->last_branch |= (packet & 0x0f) << 28;
+               ctx->last_branch_reason = (packet & 0x70) >> 4;
+               shift += 4;
+       }
+       else
+       {
+               ctx->last_branch_reason = 0;
+       }
+       
+       if (shift == 32)
+       {
+               ctx->pc_ok = 1;
+       }
+       
+       /* if a full address was output, we might have branched into Jazelle state */
+       if ((shift == 32) && (packet & 0x80))
+       {
+               ctx->core_state = ARMV4_5_STATE_JAZELLE;
+       }
+       else
+       {
+               /* if we didn't branch into Jazelle state, the current processor state is
+                * encoded in bit 0 of the branch target address */
+               if (ctx->last_branch & 0x1)
+               {
+                       ctx->core_state = ARMV4_5_STATE_THUMB;
+                       ctx->last_branch &= ~0x1;
+               }
+               else
+               {
+                       ctx->core_state = ARMV4_5_STATE_ARM;
+                       ctx->last_branch &= ~0x3;
+               }
+       }
+       
+       return 0;
+}
+
+int etmv1_data(etm_context_t *ctx, int size, u32 *data)
+{
+       int j;
+       u8 buf[4];
+       int retval;
+       
+       for (j = 0; j < size; j++)
+       {
+               if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)
+                       return -1;
+       }
+       
+       if (size == 8)
+               ERROR("TODO: add support for 64-bit values");
+       else if (size == 4)
+               *data = target_buffer_get_u32(ctx->target, buf);
+       else if (size == 2)
+               *data = target_buffer_get_u16(ctx->target, buf);
+       else if (size == 1)
+               *data = buf[0];
+               
+       return 0;
+}
+
+int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
+{
+       int retval;
+       arm_instruction_t instruction;
+       
+       /* read the trace data if it wasn't read already */
+       if (ctx->trace_depth == 0)
+               ctx->capture_driver->read_trace(ctx);
+       
+       /* start at the beginning of the captured trace */
+       ctx->pipe_index = 0;
+       ctx->data_index = 0;
+       ctx->data_half = 0;
+
+       /* neither the PC nor the data pointer are valid */     
+       ctx->pc_ok = 0;
+       ctx->ptr_ok = 0;
+       
+       while (ctx->pipe_index < ctx->trace_depth)
+       {
+               u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;
+               u32 next_pc = ctx->current_pc;
+               u32 old_data_index = ctx->data_index;
+               u32 old_data_half = ctx->data_half;
+               u32 old_index = ctx->pipe_index;
+               u32 last_instruction = ctx->last_instruction;
+               u32 cycles = 0;
+               int current_pc_ok = ctx->pc_ok;
+               
+               if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
+               {
+                       command_print(cmd_ctx, "--- trigger ---");
+               }
+
+               /* instructions execute in IE/D or BE/D cycles */
+               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
+                       ctx->last_instruction = ctx->pipe_index;
+               
+               /* if we don't have a valid pc skip until we reach an indirect branch */
+               if ((!ctx->pc_ok) && (pipestat != STAT_BE))
+               {
+                       ctx->pipe_index++;
+                       continue;
+               }
+               
+               /* any indirect branch could have interrupted instruction flow
+                * - the branch reason code could indicate a trace discontinuity
+                * - a branch to the exception vectors indicates an exception
+                */
+               if ((pipestat == STAT_BE) || (pipestat == STAT_BD))
+               {
+                       /* backup current data index, to be able to consume the branch address
+                        * before examining data address and values
+                        */
+                       old_data_index = ctx->data_index;
+                       old_data_half = ctx->data_half;
+
+                       ctx->last_instruction = ctx->pipe_index;
+                       
+                       if ((retval = etmv1_branch_address(ctx)) != 0)
+                       {
+                               /* negative return value from etmv1_branch_address means we ran out of packets,
+                                * quit analysing the trace */
+                               if (retval < 0)
+                                       break;
+                               
+                               /* a positive return values means the current branch was abandoned,
+                                * and a new branch was encountered in cycle ctx->pipe_index + retval;
+                                */
+                               WARNING("abandoned branch encountered, correctnes of analysis uncertain");
+                               ctx->pipe_index += retval;
+                               continue;
+                       }
+                       
+                       /* skip over APO cycles */
+                       ctx->pipe_index += 2;
+                       
+                       switch (ctx->last_branch_reason)
+                       {
+                               case 0x0:       /* normal PC change */
+                                       next_pc = ctx->last_branch;
+                                       break;
+                               case 0x1:       /* tracing enabled */
+                                       command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);
+                                       ctx->current_pc = ctx->last_branch;
+                                       ctx->pipe_index++;
+                                       continue;
+                                       break;
+                               case 0x2:       /* trace restarted after FIFO overflow */
+                                       command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);
+                                       ctx->current_pc = ctx->last_branch;
+                                       ctx->pipe_index++;
+                                       continue;
+                                       break;
+                               case 0x3:       /* exit from debug state */
+                                       command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);
+                                       ctx->current_pc = ctx->last_branch;
+                                       ctx->pipe_index++;
+                                       continue;
+                                       break;
+                               case 0x4:       /* periodic synchronization point */
+                                       next_pc = ctx->last_branch;
+                                       /* if we had no valid PC prior to this synchronization point,
+                                        * we have to move on with the next trace cycle
+                                        */
+                                       if (!current_pc_ok)
+                                       {
+                                               command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);
+                                               ctx->current_pc = next_pc;
+                                               ctx->pipe_index++;
+                                               continue;
+                                       }
+                                       break;
+                               default:        /* reserved */
+                                       ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);             
+                                       exit(-1);
+                                       break;
+                       }
+                       
+                       /* if we got here the branch was a normal PC change
+                        * (or a periodic synchronization point, which means the same for that matter)
+                        * if we didn't accquire a complete PC continue with the next cycle
+                        */
+                       if (!ctx->pc_ok)
+                               continue;
+                       
+                       /* indirect branch to the exception vector means an exception occured */
+                       if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))
+                               || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))
+                       {
+                               if ((ctx->last_branch & 0xff) == 0x10)
+                               {
+                                       command_print(cmd_ctx, "data abort");
+                               }
+                               else
+                               {
+                                       command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);
+                                       ctx->current_pc = ctx->last_branch;
+                                       ctx->pipe_index++;
+                                       continue;
+                               }
+                       }
+               }
+               
+               /* an instruction was executed (or not, depending on the condition flags)
+                * retrieve it from the image for displaying */
+               if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&
+                       !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&
+                               ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  
+               {
+                       if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)
+                       {
+                               /* can't continue tracing with no image available */
+                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+                               {
+                                       return retval;
+                               }
+                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+                               {
+                                       /* TODO: handle incomplete images 
+                                        * for now we just quit the analsysis*/
+                                       return retval;
+                               }
+                       }
+                       
+                       cycles = old_index - last_instruction;
+               }
+               
+               if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
+               {
+                       u32 new_data_index = ctx->data_index;
+                       u32 new_data_half = ctx->data_half;
+                       
+                       /* in case of a branch with data, the branch target address was consumed before
+                        * we temporarily go back to the saved data index */
+                       if (pipestat == STAT_BD)
+                       {
+                               ctx->data_index = old_data_index;
+                               ctx->data_half = old_data_half;
+                       }
+                       
+                       if (ctx->tracemode & ETMV1_TRACE_ADDR)
+                       {                       
+                               u8 packet;
+                               int shift = 0;
+                               
+                               do {
+                                       if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
+                                               return ERROR_ETM_ANALYSIS_FAILED;
+                                       ctx->last_ptr &= ~(0x7f << shift);
+                                       ctx->last_ptr |= (packet & 0x7f) << shift;
+                                       shift += 7;
+                               } while ((packet & 0x80) && (shift < 32));
+                               
+                               if (shift >= 32)
+                                       ctx->ptr_ok = 1;
+                               
+                               if (ctx->ptr_ok)
+                               {
+                                       command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);
+                               }
+                       }
+                       
+                       if (ctx->tracemode & ETMV1_TRACE_DATA)
+                       {
+                               if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))
+                               {
+                                       int i;
+                                       for (i = 0; i < 16; i++)
+                                       {
+                                               if (instruction.info.load_store_multiple.register_list & (1 << i))
+                                               {
+                                                       u32 data;
+                                                       if (etmv1_data(ctx, 4, &data) != 0)
+                                                               return ERROR_ETM_ANALYSIS_FAILED;
+                                                       command_print(cmd_ctx, "data: 0x%8.8x", data);
+                                               }
+                                       }
+                               }
+                               else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))
+                               {
+                                       u32 data;
+                                       if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)
+                                               return ERROR_ETM_ANALYSIS_FAILED;
+                                       command_print(cmd_ctx, "data: 0x%8.8x", data);
+                               }
+                       }
+                       
+                       /* restore data index after consuming BD address and data */
+                       if (pipestat == STAT_BD)
+                       {
+                               ctx->data_index = new_data_index;
+                               ctx->data_half = new_data_half;
+                       }
+               }
+               
+               /* adjust PC */
+               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
+               {
+                       if (((instruction.type == ARM_B) ||
+                               (instruction.type == ARM_BL) ||
+                               (instruction.type == ARM_BLX)) &&
+                               (instruction.info.b_bl_bx_blx.target_address != -1))
+                       {
+                               next_pc = instruction.info.b_bl_bx_blx.target_address;
+                       }
+                       else
+                       {
+                               next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                       }
+               }
+               else if (pipestat == STAT_IN)
+               {
+                       next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+               }
+
+               if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
+               {
+                       char cycles_text[32] = "";
+                       
+                       /* if the trace was captured with cycle accurate tracing enabled,
+                        * output the number of cycles since the last executed instruction
+                        */
+                       if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)
+                       {
+                               snprintf(cycles_text, 32, " (%i %s)",
+                                       cycles,
+                                       (cycles == 1) ? "cycle" : "cycles");
+                       }
+                       
+                       command_print(cmd_ctx, "%s%s%s",
+                               instruction.text,
+                               (pipestat == STAT_IN) ? " (not executed)" : "",
+                               cycles_text);
+
+                       ctx->current_pc = next_pc;
+                       
+                       /* packets for an instruction don't start on or before the preceding
+                        * functional pipestat (i.e. other than WT or TD)
+                        */
+                       if (ctx->data_index <= ctx->pipe_index)
+                       {
+                               ctx->data_index = ctx->pipe_index + 1;
+                               ctx->data_half = 0;
+                       }
+               }
+               
+               ctx->pipe_index += 1;
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etmv1_tracemode_t tracemode;
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!arm7_9->etm_ctx)
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       tracemode = arm7_9->etm_ctx->tracemode;
+
+       if (argc == 4)
+       {
+               if (strcmp(args[0], "none") == 0)
+               {
+                       tracemode = ETMV1_TRACE_NONE;
+               }
+               else if (strcmp(args[0], "data") == 0)
+               {
+                       tracemode = ETMV1_TRACE_DATA;
+               }
+               else if (strcmp(args[0], "address") == 0)
+               {
+                       tracemode = ETMV1_TRACE_ADDR;
+               }
+               else if (strcmp(args[0], "all") == 0)
+               {
+                       tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
+               }
+               else
+               {
+                       command_print(cmd_ctx, "invalid option '%s'", args[0]);
+                       return ERROR_OK;
+               }
+               
+               switch (strtol(args[1], NULL, 0))
+               {
+                       case 0:
+                               tracemode |= ETMV1_CONTEXTID_NONE;
+                               break;
+                       case 8:
+                               tracemode |= ETMV1_CONTEXTID_8;
+                               break;
+                       case 16:
+                               tracemode |= ETMV1_CONTEXTID_16;
+                               break;
+                       case 32:
+                               tracemode |= ETMV1_CONTEXTID_32;
+                               break;
+                       default:
+                               command_print(cmd_ctx, "invalid option '%s'", args[1]);
+                               return ERROR_OK;
+               }
+               
+               if (strcmp(args[2], "enable") == 0)
+               {
+                       tracemode |= ETMV1_CYCLE_ACCURATE;
+               }
+               else if (strcmp(args[2], "disable") == 0)
+               {
+                       tracemode |= 0;
+               }
+               else
+               {
+                       command_print(cmd_ctx, "invalid option '%s'", args[2]);
+                       return ERROR_OK;
+               }
+               
+               if (strcmp(args[3], "enable") == 0)
+               {
+                       tracemode |= ETMV1_BRANCH_OUTPUT;
+               }
+               else if (strcmp(args[3], "disable") == 0)
+               {
+                       tracemode |= 0;
+               }
+               else
+               {
+                       command_print(cmd_ctx, "invalid option '%s'", args[2]);
+                       return ERROR_OK;
+               }
+       }
+       else if (argc != 0)
+       {
+               command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");
+               return ERROR_OK;
+       }
+       
+       command_print(cmd_ctx, "current tracemode configuration:");
+       
+       switch (tracemode & ETMV1_TRACE_MASK)
+       {
+               case ETMV1_TRACE_NONE:
+                       command_print(cmd_ctx, "data tracing: none");
+                       break;
+               case ETMV1_TRACE_DATA:
+                       command_print(cmd_ctx, "data tracing: data only");
+                       break;
+               case ETMV1_TRACE_ADDR:
+                       command_print(cmd_ctx, "data tracing: address only");
+                       break;
+               case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:
+                       command_print(cmd_ctx, "data tracing: address and data");
+                       break;
+       }
+       
+       switch (tracemode & ETMV1_CONTEXTID_MASK)
+       {
+               case ETMV1_CONTEXTID_NONE:
+                       command_print(cmd_ctx, "contextid tracing: none");
+                       break;
+               case ETMV1_CONTEXTID_8:
+                       command_print(cmd_ctx, "contextid tracing: 8 bit");
+                       break;
+               case ETMV1_CONTEXTID_16:
+                       command_print(cmd_ctx, "contextid tracing: 16 bit");
+                       break;
+               case ETMV1_CONTEXTID_32:
+                       command_print(cmd_ctx, "contextid tracing: 32 bit");
+                       break;
+       }
+       
+       if (tracemode & ETMV1_CYCLE_ACCURATE)
+       {
+               command_print(cmd_ctx, "cycle-accurate tracing enabled");
+       }
+       else
+       {
+               command_print(cmd_ctx, "cycle-accurate tracing disabled");
+       }
+
+       if (tracemode & ETMV1_BRANCH_OUTPUT)
+       {
+               command_print(cmd_ctx, "full branch address output enabled");
+       }
+       else
+       {
+               command_print(cmd_ctx, "full branch address output disabled");
+       }
+       
+       /* only update ETM_CTRL register if tracemode changed */
+       if (arm7_9->etm_ctx->tracemode != tracemode)
+       {
+               reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+               
+               etm_get_reg(etm_ctrl_reg);
+               
+               buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);
+               buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);
+               buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);
+               buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);
+               etm_store_reg(etm_ctrl_reg);
+               
+               arm7_9->etm_ctx->tracemode = tracemode;
+               
+               /* invalidate old trace data */
+               arm7_9->etm_ctx->capture_status = TRACE_IDLE;
+               if (arm7_9->etm_ctx->trace_depth > 0)
+               {
+                       free(arm7_9->etm_ctx->trace_data);
+                       arm7_9->etm_ctx->trace_data = NULL;
+               }
+               arm7_9->etm_ctx->trace_depth = 0;
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_portmode_t portmode = 0x0;
+       etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));
+       int i;
+       
+       if (argc != 5)
+       {
+               ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");
+               exit(-1);
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       switch (strtoul(args[1], NULL, 0))
+       {
+               case 4:
+                       portmode |= ETM_PORT_4BIT;
+                       break;
+               case 8:
+                       portmode |= ETM_PORT_8BIT;
+                       break;
+               case 16:
+                       portmode |= ETM_PORT_16BIT;
+                       break;
+               default:
+                       command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);
+                       return ERROR_OK;
+       }
+       
+       if (strcmp("normal", args[2]) == 0)
+       {
+               portmode |= ETM_PORT_NORMAL;
+       }
+       else if (strcmp("multiplexed", args[2]) == 0)
+       {
+               portmode |= ETM_PORT_MUXED;
+       }
+       else if (strcmp("demultiplexed", args[2]) == 0)
+       {
+               portmode |= ETM_PORT_DEMUXED;
+       }
+       else
+       {
+               command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);
+               return ERROR_OK;
+       }
+       
+       if (strcmp("half", args[3]) == 0)
+       {
+               portmode |= ETM_PORT_HALF_CLOCK;
+       }
+       else if (strcmp("full", args[3]) == 0)
+       {
+               portmode |= ETM_PORT_FULL_CLOCK;
+       }
+       else
+       {
+               command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);
+               return ERROR_OK;
+       }
+       
+       for (i=0; etm_capture_drivers[i]; i++)
+       {
+               if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)
+               {
+                       if (etm_capture_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)
+                       {
+                               free(etm_ctx);
+                               exit(-1);
+                       }
+               
+                       etm_ctx->capture_driver = etm_capture_drivers[i];
+
+                       break;
+               }
+       }
+       
+       if (!etm_capture_drivers[i])
+       {
+               /* no supported capture driver found, don't register an ETM */
+               free(etm_ctx);
+               ERROR("trace capture driver '%s' not found", args[4]);
+               return ERROR_OK;
+       }
+       
+       etm_ctx->target = target;
+       etm_ctx->trigger_percent = 50;
+       etm_ctx->trace_data = NULL;
+       etm_ctx->trace_depth = 0;
+       etm_ctx->portmode = portmode;
+       etm_ctx->tracemode = 0x0;
+       etm_ctx->core_state = ARMV4_5_STATE_ARM;
+       etm_ctx->image = NULL;
+       etm_ctx->pipe_index = 0;
+       etm_ctx->data_index = 0;
+       etm_ctx->current_pc = 0x0;
+       etm_ctx->pc_ok = 0;
+       etm_ctx->last_branch = 0x0;
+       etm_ctx->last_branch_reason = 0x0;
+       etm_ctx->last_ptr = 0x0;
+       etm_ctx->ptr_ok = 0x0;
+       etm_ctx->context_id = 0x0;
+       etm_ctx->last_instruction = 0;
+       
+       arm7_9->etm_ctx = etm_ctx;
+       
+       etm_register_user_commands(cmd_ctx);
+       
+       return ERROR_OK;
+}
+
+int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       reg_t *etm_config_reg;
+       reg_t *etm_sys_config_reg;
+       
+       int max_port_size;
+               
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!arm7_9->etm_ctx)
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];
+       etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];
+       
+       etm_get_reg(etm_config_reg);
+       command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));
+       command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));
+       command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));
+       command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));
+       command_print(cmd_ctx, "sequencer %spresent",
+                       (buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));
+       command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));
+       command_print(cmd_ctx, "FIFO full %spresent",
+                       (buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));
+       
+       etm_get_reg(etm_sys_config_reg);
+
+       switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))
+       {
+               case 0:
+                       max_port_size = 4;
+                       break;
+               case 1:
+                       max_port_size = 8;
+                       break;
+               case 2:
+                       max_port_size = 16;
+                       break;
+       }
+       command_print(cmd_ctx, "max. port size: %i", max_port_size);
+       
+       command_print(cmd_ctx, "half-rate clocking %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "full-rate clocking %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "normal trace format %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "multiplex trace format %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "demultiplex trace format %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");
+       command_print(cmd_ctx, "FIFO full %ssupported",
+                       (buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");
+       
+       return ERROR_OK;
+}
+
+int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       trace_status_t trace_status;
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!arm7_9->etm_ctx)
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);
+       
+       if (trace_status == TRACE_IDLE)
+       {
+               command_print(cmd_ctx, "tracing is idle");
+       }
+       else
+       {
+               static char *completed = " completed";
+               static char *running = " is running";
+               static char *overflowed = ", trace overflowed";
+               static char *triggered = ", trace triggered";
+               
+               command_print(cmd_ctx, "trace collection%s%s%s", 
+                       (trace_status & TRACE_RUNNING) ? running : completed,
+                       (trace_status & TRACE_OVERFLOWED) ? overflowed : "",
+                       (trace_status & TRACE_TRIGGERED) ? triggered : "");
+               
+               if (arm7_9->etm_ctx->trace_depth > 0)
+               {
+                       command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);
+               }
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");
+               return ERROR_OK;
+       }
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       if (etm_ctx->image)
+       {
+               image_close(etm_ctx->image);
+               free(etm_ctx->image);
+               command_print(cmd_ctx, "previously loaded image found and closed");
+       }
+       
+       etm_ctx->image = malloc(sizeof(image_t));
+       etm_ctx->image->base_address_set = 0;
+       etm_ctx->image->start_address_set = 0;
+       
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       if (argc >= 2)
+       {
+               etm_ctx->image->base_address_set = 1;
+               etm_ctx->image->base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               etm_ctx->image->base_address_set = 0;
+       }
+               
+       if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);
+               free(etm_ctx->image);
+               etm_ctx->image = NULL;
+               return ERROR_OK;
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       fileio_t file;
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       int i;
+       
+       if (argc != 1)
+       {
+               command_print(cmd_ctx, "usage: etm dump <file>");
+               return ERROR_OK;
+       }
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       if (etm_ctx->capture_driver->status == TRACE_IDLE)
+       {
+               command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");
+               return ERROR_OK;
+       }
+
+       if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
+       {
+               /* TODO: if on-the-fly capture is to be supported, this needs to be changed */
+               command_print(cmd_ctx, "trace capture not completed");
+               return ERROR_OK;
+       }
+       
+       /* read the trace data if it wasn't read already */
+       if (etm_ctx->trace_depth == 0)
+               etm_ctx->capture_driver->read_trace(etm_ctx);
+       
+       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "file open error: %s", file.error_str);
+               return ERROR_OK;
+       }
+       
+       fileio_write_u32(&file, etm_ctx->capture_status);
+       fileio_write_u32(&file, etm_ctx->portmode);
+       fileio_write_u32(&file, etm_ctx->tracemode);
+       fileio_write_u32(&file, etm_ctx->trace_depth);
+       
+       for (i = 0; i < etm_ctx->trace_depth; i++)
+       {
+               fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);
+               fileio_write_u32(&file, etm_ctx->trace_data[i].packet);
+               fileio_write_u32(&file, etm_ctx->trace_data[i].flags);
+       }
+       
+       fileio_close(&file);
+       
+       return ERROR_OK;        
+}
+
+int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       fileio_t file;
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       int i;
+       
+       if (argc != 1)
+       {
+               command_print(cmd_ctx, "usage: etm load <file>");
+               return ERROR_OK;
+       }
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
+       {
+               command_print(cmd_ctx, "trace capture running, stop first");
+               return ERROR_OK;
+       }
+       
+       if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "file open error: %s", file.error_str);
+               return ERROR_OK;
+       }
+       
+       if (file.size % 4)
+       {
+               command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");
+               return ERROR_OK;
+       }
+       
+       if (etm_ctx->trace_depth > 0)
+       {
+               free(etm_ctx->trace_data);
+       }
+       
+       fileio_read_u32(&file, &etm_ctx->capture_status);
+       fileio_read_u32(&file, &etm_ctx->portmode);
+       fileio_read_u32(&file, &etm_ctx->tracemode);
+       fileio_read_u32(&file, &etm_ctx->trace_depth);
+       
+       etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
+       
+       for (i = 0; i < etm_ctx->trace_depth; i++)
+       {
+               u32 pipestat, packet, flags;
+               fileio_read_u32(&file, &pipestat);
+               fileio_read_u32(&file, &packet);
+               fileio_read_u32(&file, &flags);
+               etm_ctx->trace_data[i].pipestat = pipestat & 0xff;
+               etm_ctx->trace_data[i].packet = packet & 0xffff;
+               etm_ctx->trace_data[i].flags = flags;
+       }
+       
+       fileio_close(&file);
+       
+       return ERROR_OK;        
+}
+
+int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       if (argc > 0)
+       {
+               u32 new_value = strtoul(args[0], NULL, 0);
+               
+               if ((new_value < 2) || (new_value > 100))
+               {
+                       command_print(cmd_ctx, "valid settings are 2% to 100%");
+               }
+               else
+               {
+                       etm_ctx->trigger_percent = new_value;
+               }
+       }
+       
+       command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);
+
+       return ERROR_OK;
+}
+
+int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       reg_t *etm_ctrl_reg;
+
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       /* invalidate old tracing data */
+       arm7_9->etm_ctx->capture_status = TRACE_IDLE;
+       if (arm7_9->etm_ctx->trace_depth > 0)
+       {
+               free(arm7_9->etm_ctx->trace_data);
+               arm7_9->etm_ctx->trace_data = NULL;
+       }
+       arm7_9->etm_ctx->trace_depth = 0;
+               
+       etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+       etm_get_reg(etm_ctrl_reg);
+               
+       /* Clear programming bit (10), set port selection bit (11) */
+       buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);
+
+       etm_store_reg(etm_ctrl_reg);
+       jtag_execute_queue();
+
+       etm_ctx->capture_driver->start_capture(etm_ctx);
+
+       return ERROR_OK;
+}
+
+int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       reg_t *etm_ctrl_reg;
+
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+       etm_get_reg(etm_ctrl_reg);
+               
+       /* Set programming bit (10), clear port selection bit (11) */
+       buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);
+
+       etm_store_reg(etm_ctrl_reg);    
+       jtag_execute_queue();
+       
+       etm_ctx->capture_driver->stop_capture(etm_ctx);
+       
+       return ERROR_OK;
+}
+
+int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       arm7_9_common_t *arm7_9;
+       etm_context_t *etm_ctx;
+       int retval;
+
+       target = get_current_target(cmd_ctx);
+       
+       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+               return ERROR_OK;
+       }
+       
+       if (!(etm_ctx = arm7_9->etm_ctx))
+       {
+               command_print(cmd_ctx, "current target doesn't have an ETM configured");
+               return ERROR_OK;
+       }
+       
+       if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)
+       {
+               switch(retval)
+               {
+                       case ERROR_ETM_ANALYSIS_FAILED:
+                               command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");
+                               break;
+                       case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
+                               command_print(cmd_ctx, "no instruction for current address available, analysis aborted");
+                               break;
+                       case ERROR_TRACE_IMAGE_UNAVAILABLE:
+                               command_print(cmd_ctx, "no image available for trace analysis");
+                               break;
+                       default:
+                               command_print(cmd_ctx, "unknown error: %i", retval);
+               }
+       }
+       
+       return ERROR_OK;
+}
+
+int etm_register_commands(struct command_context_s *cmd_ctx)
+{
+       etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");
+
+       register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, NULL);
+
+       return ERROR_OK;
+}
+
+int etm_register_user_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
+               COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");
+
+       register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,
+               COMMAND_EXEC, "display info about the current target's ETM");
+
+       register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,
+               COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");
+       register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,
+               COMMAND_EXEC, "display current target's ETM status");
+       register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,
+               COMMAND_EXEC, "start ETM trace collection");
+       register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
+               COMMAND_EXEC, "stop ETM trace collection");
+
+       register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,
+               COMMAND_EXEC, "anaylze collected ETM trace");
+
+       register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,
+               COMMAND_EXEC, "load image from <file> [base address]");
+
+       register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
+               COMMAND_EXEC, "dump captured trace data <file>");
+       register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
+               COMMAND_EXEC, "load trace data for analysis <file>");
+
+       return ERROR_OK;
+}
index bfa1252b761ca4284da449754785a326c1d0b73e..da47ff13ab9f67b559b6f9f5ec79ba7d81ab783b 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005, 2007 by Dominic Rath                              *\r
- *   Dominic.Rath@gmx.de                                                   *\r
- *                                                                         *\r
- *   Copyright (C) 2007 by Vincent Palatin                                 *\r
- *   vincent.palatin_openocd@m4x.org                                       *\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
-#ifndef ETM_H\r
-#define ETM_H\r
-\r
-#include "image.h"\r
-#include "trace.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "arm_jtag.h"\r
-\r
-#include "armv4_5.h"\r
-\r
-/* ETM registers (V1.3 protocol) */\r
-enum\r
-{\r
-       ETM_CTRL = 0x00,\r
-       ETM_CONFIG = 0x01,\r
-       ETM_TRIG_EVENT = 0x02,\r
-       ETM_MMD_CTRL = 0x03,\r
-       ETM_STATUS = 0x04,\r
-       ETM_SYS_CONFIG = 0x05,\r
-       ETM_TRACE_RESOURCE_CTRL = 0x06,\r
-       ETM_TRACE_EN_CTRL2 = 0x07,\r
-       ETM_TRACE_EN_EVENT = 0x08,\r
-       ETM_TRACE_EN_CTRL1 = 0x09,\r
-       ETM_FIFOFULL_REGION = 0x0a,\r
-       ETM_FIFOFULL_LEVEL = 0x0b,\r
-       ETM_VIEWDATA_EVENT = 0x0c,\r
-       ETM_VIEWDATA_CTRL1 = 0x0d,\r
-       ETM_VIEWDATA_CTRL2 = 0x0e,\r
-       ETM_VIEWDATA_CTRL3 = 0x0f,\r
-       ETM_ADDR_COMPARATOR_VALUE = 0x10,\r
-       ETM_ADDR_ACCESS_TYPE = 0x20,\r
-       ETM_DATA_COMPARATOR_VALUE = 0x30,\r
-       ETM_DATA_COMPARATOR_MASK = 0x40,\r
-       ETM_COUNTER_INITAL_VALUE = 0x50,\r
-       ETM_COUNTER_ENABLE = 0x54,\r
-       ETM_COUNTER_RELOAD_VALUE = 0x58,\r
-       ETM_COUNTER_VALUE = 0x5c,\r
-       ETM_SEQUENCER_CTRL = 0x60,\r
-       ETM_SEQUENCER_STATE = 0x67,\r
-       ETM_EXTERNAL_OUTPUT = 0x68,\r
-       ETM_CONTEXTID_COMPARATOR_VALUE = 0x6c,\r
-       ETM_CONTEXTID_COMPARATOR_MASK = 0x6f,   \r
-};\r
-\r
-typedef struct etm_reg_s\r
-{\r
-       int addr;\r
-       arm_jtag_t *jtag_info;\r
-} etm_reg_t;\r
-\r
-typedef enum\r
-{\r
-       /* Port width */\r
-       ETM_PORT_4BIT           = 0x00,\r
-       ETM_PORT_8BIT           = 0x10,\r
-       ETM_PORT_16BIT          = 0x20,\r
-       ETM_PORT_WIDTH_MASK     = 0x70, \r
-       /* Port modes */\r
-       ETM_PORT_NORMAL    = 0x00000,\r
-       ETM_PORT_MUXED     = 0x10000,\r
-       ETM_PORT_DEMUXED   = 0x20000,\r
-       ETM_PORT_MODE_MASK = 0x30000,\r
-       /* Clocking modes */\r
-       ETM_PORT_FULL_CLOCK = 0x0000,\r
-       ETM_PORT_HALF_CLOCK = 0x1000,\r
-       ETM_PORT_CLOCK_MASK = 0x1000,\r
-} etm_portmode_t;\r
-\r
-typedef enum\r
-{\r
-       /* Data trace */\r
-       ETMV1_TRACE_NONE         = 0x00,\r
-       ETMV1_TRACE_DATA     = 0x01,\r
-       ETMV1_TRACE_ADDR     = 0x02,\r
-       ETMV1_TRACE_MASK     = 0x03,\r
-       /* ContextID */\r
-       ETMV1_CONTEXTID_NONE = 0x00,\r
-       ETMV1_CONTEXTID_8    = 0x10,\r
-       ETMV1_CONTEXTID_16   = 0x20,\r
-       ETMV1_CONTEXTID_32   = 0x30,\r
-       ETMV1_CONTEXTID_MASK = 0x30,\r
-       /* Misc */\r
-       ETMV1_CYCLE_ACCURATE = 0x100,\r
-       ETMV1_BRANCH_OUTPUT = 0x200\r
-} etmv1_tracemode_t;\r
-\r
-/* forward-declare ETM context */\r
-struct etm_context_s;\r
-\r
-typedef struct etm_capture_driver_s\r
-{\r
-       char *name;\r
-       int (*register_commands)(struct command_context_s *cmd_ctx);\r
-       int (*init)(struct etm_context_s *etm_ctx);\r
-       trace_status_t (*status)(struct etm_context_s *etm_ctx);\r
-       int (*read_trace)(struct etm_context_s *etm_ctx);\r
-       int (*start_capture)(struct etm_context_s *etm_ctx);\r
-       int (*stop_capture)(struct etm_context_s *etm_ctx);\r
-} etm_capture_driver_t;\r
-\r
-enum\r
-{\r
-       ETMV1_TRACESYNC_CYCLE = 0x1,\r
-       ETMV1_TRIGGER_CYCLE = 0x2,\r
-};\r
-\r
-typedef struct etmv1_trace_data_s\r
-{\r
-       u8 pipestat;    /* bits 0-2 pipeline status */\r
-       u16 packet;             /* packet data (4, 8 or 16 bit) */\r
-       int flags;              /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */\r
-} etmv1_trace_data_t;\r
-\r
-/* describe a trace context\r
- * if support for ETMv2 or ETMv3 is to be implemented,\r
- * this will have to be split into version independent elements\r
- * and a version specific part\r
- */\r
-typedef struct etm_context_s\r
-{\r
-       target_t *target;                               /* target this ETM is connected to */\r
-       reg_cache_t *reg_cache;                 /* ETM register cache */\r
-       etm_capture_driver_t *capture_driver;   /* driver used to access ETM data */\r
-       void *capture_driver_priv;              /* capture driver private data */\r
-       u32 trigger_percent;                    /* percent of trace buffer to be filled after the trigger */\r
-       trace_status_t capture_status;  /* current state of capture run */ \r
-       etmv1_trace_data_t *trace_data; /* trace data */\r
-       u32 trace_depth;                                /* number of trace cycles to be analyzed, 0 if no trace data available */\r
-       etm_portmode_t portmode;                /* normal, multiplexed or demultiplexed */\r
-       etmv1_tracemode_t tracemode;    /* type of information the trace contains (data, addres, contextID, ...) */ \r
-       armv4_5_state_t core_state;             /* current core state (ARM, Thumb, Jazelle) */\r
-       image_t *image;                                 /* source for target opcodes */\r
-       u32 pipe_index;                                 /* current trace cycle */\r
-       u32 data_index;                                 /* cycle holding next data packet */\r
-       int data_half;                                  /* port half on a 16 bit port */\r
-       u32 current_pc;                                 /* current program counter */\r
-       u32 pc_ok;                                              /* full PC has been acquired */\r
-       u32 last_branch;                                /* last branch address output */ \r
-       u32 last_branch_reason;                 /* branch reason code for the last branch encountered */\r
-       u32 last_ptr;                                   /* address of the last data access */\r
-       u32 ptr_ok;                                             /* whether last_ptr is valid */ \r
-       u32 context_id;                                 /* context ID of the code being traced */\r
-       u32 last_instruction;                   /* index of last instruction executed (to calculate cycle timings) */\r
-} etm_context_t;\r
-\r
-/* PIPESTAT values */\r
-typedef enum\r
-{\r
-       STAT_IE = 0x0,\r
-       STAT_ID = 0x1,\r
-       STAT_IN = 0x2,\r
-       STAT_WT = 0x3,\r
-       STAT_BE = 0x4,\r
-       STAT_BD = 0x5,\r
-       STAT_TR = 0x6,\r
-       STAT_TD = 0x7\r
-} etmv1_pipestat_t;\r
-\r
-/* branch reason values */\r
-typedef enum\r
-{\r
-       BR_NORMAL  = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */\r
-       BR_ENABLE  = 0x1, /* Trace has been enabled */\r
-       BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */\r
-       BR_NODEBUG = 0x3, /* ARM has exited for debug state */\r
-       BR_PERIOD  = 0x4, /* Peridioc synchronization point (ETM>=v1.2)*/\r
-       BR_RSVD5   = 0x5, /* reserved */\r
-       BR_RSVD6   = 0x6, /* reserved */\r
-       BR_RSVD7   = 0x7, /* reserved */\r
-} etmv1_branch_reason_t;\r
-\r
-extern char *etmv1v1_branch_reason_strings[];\r
-\r
-extern reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx);\r
-extern int etm_read_reg(reg_t *reg);\r
-extern int etm_write_reg(reg_t *reg, u32 value);\r
-extern int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);\r
-extern int etm_store_reg(reg_t *reg);\r
-extern int etm_set_reg(reg_t *reg, u32 value);\r
-extern int etm_set_reg_w_exec(reg_t *reg, u8 *buf);\r
-\r
-int etm_register_commands(struct command_context_s *cmd_ctx);\r
-int etm_register_user_commands(struct command_context_s *cmd_ctx);\r
-extern etm_context_t* etm_create_context(etm_portmode_t portmode, char *capture_driver_name);\r
-\r
-#define ERROR_ETM_INVALID_DRIVER       (-1300)\r
-#define ERROR_ETM_PORTMODE_NOT_SUPPORTED       (-1301)\r
-#define ERROR_ETM_CAPTURE_INIT_FAILED  (-1302)\r
-#define ERROR_ETM_ANALYSIS_FAILED      (-1303)\r
-\r
-#endif /* ETM_H */\r
+/***************************************************************************
+ *   Copyright (C) 2005, 2007 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   Copyright (C) 2007 by Vincent Palatin                                 *
+ *   vincent.palatin_openocd@m4x.org                                       *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef ETM_H
+#define ETM_H
+
+#include "image.h"
+#include "trace.h"
+#include "target.h"
+#include "register.h"
+#include "arm_jtag.h"
+
+#include "armv4_5.h"
+
+/* ETM registers (V1.3 protocol) */
+enum
+{
+       ETM_CTRL = 0x00,
+       ETM_CONFIG = 0x01,
+       ETM_TRIG_EVENT = 0x02,
+       ETM_MMD_CTRL = 0x03,
+       ETM_STATUS = 0x04,
+       ETM_SYS_CONFIG = 0x05,
+       ETM_TRACE_RESOURCE_CTRL = 0x06,
+       ETM_TRACE_EN_CTRL2 = 0x07,
+       ETM_TRACE_EN_EVENT = 0x08,
+       ETM_TRACE_EN_CTRL1 = 0x09,
+       ETM_FIFOFULL_REGION = 0x0a,
+       ETM_FIFOFULL_LEVEL = 0x0b,
+       ETM_VIEWDATA_EVENT = 0x0c,
+       ETM_VIEWDATA_CTRL1 = 0x0d,
+       ETM_VIEWDATA_CTRL2 = 0x0e,
+       ETM_VIEWDATA_CTRL3 = 0x0f,
+       ETM_ADDR_COMPARATOR_VALUE = 0x10,
+       ETM_ADDR_ACCESS_TYPE = 0x20,
+       ETM_DATA_COMPARATOR_VALUE = 0x30,
+       ETM_DATA_COMPARATOR_MASK = 0x40,
+       ETM_COUNTER_INITAL_VALUE = 0x50,
+       ETM_COUNTER_ENABLE = 0x54,
+       ETM_COUNTER_RELOAD_VALUE = 0x58,
+       ETM_COUNTER_VALUE = 0x5c,
+       ETM_SEQUENCER_CTRL = 0x60,
+       ETM_SEQUENCER_STATE = 0x67,
+       ETM_EXTERNAL_OUTPUT = 0x68,
+       ETM_CONTEXTID_COMPARATOR_VALUE = 0x6c,
+       ETM_CONTEXTID_COMPARATOR_MASK = 0x6f,   
+};
+
+typedef struct etm_reg_s
+{
+       int addr;
+       arm_jtag_t *jtag_info;
+} etm_reg_t;
+
+typedef enum
+{
+       /* Port width */
+       ETM_PORT_4BIT           = 0x00,
+       ETM_PORT_8BIT           = 0x10,
+       ETM_PORT_16BIT          = 0x20,
+       ETM_PORT_WIDTH_MASK     = 0x70, 
+       /* Port modes */
+       ETM_PORT_NORMAL    = 0x00000,
+       ETM_PORT_MUXED     = 0x10000,
+       ETM_PORT_DEMUXED   = 0x20000,
+       ETM_PORT_MODE_MASK = 0x30000,
+       /* Clocking modes */
+       ETM_PORT_FULL_CLOCK = 0x0000,
+       ETM_PORT_HALF_CLOCK = 0x1000,
+       ETM_PORT_CLOCK_MASK = 0x1000,
+} etm_portmode_t;
+
+typedef enum
+{
+       /* Data trace */
+       ETMV1_TRACE_NONE         = 0x00,
+       ETMV1_TRACE_DATA     = 0x01,
+       ETMV1_TRACE_ADDR     = 0x02,
+       ETMV1_TRACE_MASK     = 0x03,
+       /* ContextID */
+       ETMV1_CONTEXTID_NONE = 0x00,
+       ETMV1_CONTEXTID_8    = 0x10,
+       ETMV1_CONTEXTID_16   = 0x20,
+       ETMV1_CONTEXTID_32   = 0x30,
+       ETMV1_CONTEXTID_MASK = 0x30,
+       /* Misc */
+       ETMV1_CYCLE_ACCURATE = 0x100,
+       ETMV1_BRANCH_OUTPUT = 0x200
+} etmv1_tracemode_t;
+
+/* forward-declare ETM context */
+struct etm_context_s;
+
+typedef struct etm_capture_driver_s
+{
+       char *name;
+       int (*register_commands)(struct command_context_s *cmd_ctx);
+       int (*init)(struct etm_context_s *etm_ctx);
+       trace_status_t (*status)(struct etm_context_s *etm_ctx);
+       int (*read_trace)(struct etm_context_s *etm_ctx);
+       int (*start_capture)(struct etm_context_s *etm_ctx);
+       int (*stop_capture)(struct etm_context_s *etm_ctx);
+} etm_capture_driver_t;
+
+enum
+{
+       ETMV1_TRACESYNC_CYCLE = 0x1,
+       ETMV1_TRIGGER_CYCLE = 0x2,
+};
+
+typedef struct etmv1_trace_data_s
+{
+       u8 pipestat;    /* bits 0-2 pipeline status */
+       u16 packet;             /* packet data (4, 8 or 16 bit) */
+       int flags;              /* ETMV1_TRACESYNC_CYCLE, ETMV1_TRIGGER_CYCLE */
+} etmv1_trace_data_t;
+
+/* describe a trace context
+ * if support for ETMv2 or ETMv3 is to be implemented,
+ * this will have to be split into version independent elements
+ * and a version specific part
+ */
+typedef struct etm_context_s
+{
+       target_t *target;                               /* target this ETM is connected to */
+       reg_cache_t *reg_cache;                 /* ETM register cache */
+       etm_capture_driver_t *capture_driver;   /* driver used to access ETM data */
+       void *capture_driver_priv;              /* capture driver private data */
+       u32 trigger_percent;                    /* percent of trace buffer to be filled after the trigger */
+       trace_status_t capture_status;  /* current state of capture run */ 
+       etmv1_trace_data_t *trace_data; /* trace data */
+       u32 trace_depth;                                /* number of trace cycles to be analyzed, 0 if no trace data available */
+       etm_portmode_t portmode;                /* normal, multiplexed or demultiplexed */
+       etmv1_tracemode_t tracemode;    /* type of information the trace contains (data, addres, contextID, ...) */ 
+       armv4_5_state_t core_state;             /* current core state (ARM, Thumb, Jazelle) */
+       image_t *image;                                 /* source for target opcodes */
+       u32 pipe_index;                                 /* current trace cycle */
+       u32 data_index;                                 /* cycle holding next data packet */
+       int data_half;                                  /* port half on a 16 bit port */
+       u32 current_pc;                                 /* current program counter */
+       u32 pc_ok;                                              /* full PC has been acquired */
+       u32 last_branch;                                /* last branch address output */ 
+       u32 last_branch_reason;                 /* branch reason code for the last branch encountered */
+       u32 last_ptr;                                   /* address of the last data access */
+       u32 ptr_ok;                                             /* whether last_ptr is valid */ 
+       u32 context_id;                                 /* context ID of the code being traced */
+       u32 last_instruction;                   /* index of last instruction executed (to calculate cycle timings) */
+} etm_context_t;
+
+/* PIPESTAT values */
+typedef enum
+{
+       STAT_IE = 0x0,
+       STAT_ID = 0x1,
+       STAT_IN = 0x2,
+       STAT_WT = 0x3,
+       STAT_BE = 0x4,
+       STAT_BD = 0x5,
+       STAT_TR = 0x6,
+       STAT_TD = 0x7
+} etmv1_pipestat_t;
+
+/* branch reason values */
+typedef enum
+{
+       BR_NORMAL  = 0x0, /* Normal PC change : periodic synchro (ETMv1.1) */
+       BR_ENABLE  = 0x1, /* Trace has been enabled */
+       BR_RESTART = 0x2, /* Trace restarted after a FIFO overflow */
+       BR_NODEBUG = 0x3, /* ARM has exited for debug state */
+       BR_PERIOD  = 0x4, /* Peridioc synchronization point (ETM>=v1.2)*/
+       BR_RSVD5   = 0x5, /* reserved */
+       BR_RSVD6   = 0x6, /* reserved */
+       BR_RSVD7   = 0x7, /* reserved */
+} etmv1_branch_reason_t;
+
+extern char *etmv1v1_branch_reason_strings[];
+
+extern reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx);
+extern int etm_read_reg(reg_t *reg);
+extern int etm_write_reg(reg_t *reg, u32 value);
+extern int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
+extern int etm_store_reg(reg_t *reg);
+extern int etm_set_reg(reg_t *reg, u32 value);
+extern int etm_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int etm_register_commands(struct command_context_s *cmd_ctx);
+int etm_register_user_commands(struct command_context_s *cmd_ctx);
+extern etm_context_t* etm_create_context(etm_portmode_t portmode, char *capture_driver_name);
+
+#define ERROR_ETM_INVALID_DRIVER       (-1300)
+#define ERROR_ETM_PORTMODE_NOT_SUPPORTED       (-1301)
+#define ERROR_ETM_CAPTURE_INIT_FAILED  (-1302)
+#define ERROR_ETM_ANALYSIS_FAILED      (-1303)
+
+#endif /* ETM_H */
index 31afeffb61a7812d2d3a8525d120c724e89a39ff..006db012290d615dd61d5823a6e235acbc83837a 100644 (file)
@@ -1,33 +1,33 @@
-/***************************************************************************\r
- *   Copyright (C) 2007 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-#ifndef ETM_DUMMY_H\r
-#define ETM_DUMMY_H\r
-\r
-#include "command.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "arm_jtag.h"\r
-\r
-#include "etm.h"\r
-\r
-extern etm_capture_driver_t etm_dummy_capture_driver;\r
-extern int etm_dummy_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-#endif /* ETB_H */\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef ETM_DUMMY_H
+#define ETM_DUMMY_H
+
+#include "command.h"
+#include "target.h"
+#include "register.h"
+#include "arm_jtag.h"
+
+#include "etm.h"
+
+extern etm_capture_driver_t etm_dummy_capture_driver;
+extern int etm_dummy_register_commands(struct command_context_s *cmd_ctx);
+
+#endif /* ETB_H */
index c80a7cede6e63e9fb6a22e2ee281335d53fed688..77e985fbb612f86b79437261093e83b56f60514c 100644 (file)
@@ -1,64 +1,64 @@
-/***************************************************************************\r
- *   Copyright (C) 2007 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-#ifndef OOCD_TRACE_H\r
-#define OOCD_TRACE_H\r
-\r
-#include "command.h"\r
-\r
-#include "etm.h"\r
-\r
-#include <termios.h>\r
-#include <unistd.h>\r
-\r
-/* registers */\r
-enum\r
-{\r
-    OOCD_TRACE_ID = 0x7,\r
-    OOCD_TRACE_ADDRESS = 0x0,\r
-    OOCD_TRACE_TRIGGER_COUNTER = 0x01,\r
-    OOCD_TRACE_CONTROL = 0x2,\r
-    OOCD_TRACE_STATUS = 0x3,\r
-    OOCD_TRACE_SDRAM_COUNTER = 0x4,\r
-};\r
-\r
-/* commands */\r
-enum\r
-{\r
-       OOCD_TRACE_NOP = 0x0,\r
-       OOCD_TRACE_READ_REG = 0x10,\r
-       OOCD_TRACE_WRITE_REG = 0x18,\r
-       OOCD_TRACE_READ_RAM = 0x20,\r
-/*     OOCD_TRACE_WRITE_RAM = 0x28, */\r
-       OOCD_TRACE_RESYNC = 0xf0,\r
-};\r
-\r
-typedef struct oocd_trace_s\r
-{\r
-       etm_context_t *etm_ctx;\r
-       char *tty;\r
-       int tty_fd;\r
-       struct termios oldtio, newtio;\r
-} oocd_trace_t;\r
-\r
-extern etm_capture_driver_t oocd_trace_capture_driver;\r
-\r
-extern int oocd_trace_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-#endif /* OOCD_TRACE_TRACE_H */\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef OOCD_TRACE_H
+#define OOCD_TRACE_H
+
+#include "command.h"
+
+#include "etm.h"
+
+#include <termios.h>
+#include <unistd.h>
+
+/* registers */
+enum
+{
+    OOCD_TRACE_ID = 0x7,
+    OOCD_TRACE_ADDRESS = 0x0,
+    OOCD_TRACE_TRIGGER_COUNTER = 0x01,
+    OOCD_TRACE_CONTROL = 0x2,
+    OOCD_TRACE_STATUS = 0x3,
+    OOCD_TRACE_SDRAM_COUNTER = 0x4,
+};
+
+/* commands */
+enum
+{
+       OOCD_TRACE_NOP = 0x0,
+       OOCD_TRACE_READ_REG = 0x10,
+       OOCD_TRACE_WRITE_REG = 0x18,
+       OOCD_TRACE_READ_RAM = 0x20,
+/*     OOCD_TRACE_WRITE_RAM = 0x28, */
+       OOCD_TRACE_RESYNC = 0xf0,
+};
+
+typedef struct oocd_trace_s
+{
+       etm_context_t *etm_ctx;
+       char *tty;
+       int tty_fd;
+       struct termios oldtio, newtio;
+} oocd_trace_t;
+
+extern etm_capture_driver_t oocd_trace_capture_driver;
+
+extern int oocd_trace_register_commands(struct command_context_s *cmd_ctx);
+
+#endif /* OOCD_TRACE_TRACE_H */
index a9f7c1034b893b2e9f557b120e0fcb2ee3eed643..27df12fc33f42d34466c6f5ea6ad300ce90f822a 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\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
-int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);\r
-\r
-\r
-int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-/* targets\r
- */\r
-extern target_type_t arm7tdmi_target;\r
-extern target_type_t arm720t_target;\r
-extern target_type_t arm9tdmi_target;\r
-extern target_type_t arm920t_target;\r
-extern target_type_t arm966e_target;\r
-extern target_type_t arm926ejs_target;\r
-extern target_type_t feroceon_target;\r
-extern target_type_t xscale_target;\r
-extern target_type_t cortexm3_target;\r
-\r
-target_type_t *target_types[] =\r
-{\r
-       &arm7tdmi_target,\r
-       &arm9tdmi_target,\r
-       &arm920t_target,\r
-       &arm720t_target,\r
-       &arm966e_target,\r
-       &arm926ejs_target,\r
-       &feroceon_target,\r
-       &xscale_target,\r
-       &cortexm3_target,\r
-       NULL,\r
-};\r
-\r
-target_t *targets = NULL;\r
-target_event_callback_t *target_event_callbacks = NULL;\r
-target_timer_callback_t *target_timer_callbacks = NULL;\r
-\r
-char *target_state_strings[] =\r
-{\r
-       "unknown",\r
-       "running",\r
-       "halted",\r
-       "reset",\r
-       "debug_running",\r
-};\r
-\r
-char *target_debug_reason_strings[] =\r
-{\r
-       "debug request", "breakpoint", "watchpoint",\r
-       "watchpoint and breakpoint", "single step",\r
-       "target not halted"\r
-};\r
-\r
-char *target_endianess_strings[] =\r
-{\r
-       "big endian",\r
-       "little endian",\r
-};\r
-\r
-enum daemon_startup_mode startup_mode = DAEMON_ATTACH;\r
-\r
-static int target_continous_poll = 1;\r
-\r
-/* read a u32 from a buffer in target memory endianness */\r
-u32 target_buffer_get_u32(target_t *target, u8 *buffer)\r
-{\r
-       if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-               return le_to_h_u32(buffer);\r
-       else\r
-               return be_to_h_u32(buffer);\r
-}\r
-\r
-/* read a u16 from a buffer in target memory endianness */\r
-u16 target_buffer_get_u16(target_t *target, u8 *buffer)\r
-{\r
-       if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-               return le_to_h_u16(buffer);\r
-       else\r
-               return be_to_h_u16(buffer);\r
-}\r
-\r
-/* write a u32 to a buffer in target memory endianness */\r
-void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)\r
-{\r
-       if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-               h_u32_to_le(buffer, value);\r
-       else\r
-               h_u32_to_be(buffer, value);\r
-}\r
-\r
-/* write a u16 to a buffer in target memory endianness */\r
-void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)\r
-{\r
-       if (target->endianness == TARGET_LITTLE_ENDIAN)\r
-               h_u16_to_le(buffer, value);\r
-       else\r
-               h_u16_to_be(buffer, value);\r
-}\r
-\r
-/* returns a pointer to the n-th configured target */\r
-target_t* get_target_by_num(int num)\r
-{\r
-       target_t *target = targets;\r
-       int i = 0;\r
-\r
-       while (target)\r
-       {\r
-               if (num == i)\r
-                       return target;\r
-               target = target->next;\r
-               i++;\r
-       }\r
-\r
-       return NULL;\r
-}\r
-\r
-int get_num_by_target(target_t *query_target)\r
-{\r
-       target_t *target = targets;\r
-       int i = 0;      \r
-       \r
-       while (target)\r
-       {\r
-               if (target == query_target)\r
-                       return i;\r
-               target = target->next;\r
-               i++;\r
-       }\r
-       \r
-       return -1;\r
-}\r
-\r
-target_t* get_current_target(command_context_t *cmd_ctx)\r
-{\r
-       target_t *target = get_target_by_num(cmd_ctx->current_target);\r
-       \r
-       if (target == NULL)\r
-       {\r
-               ERROR("BUG: current_target out of bounds");\r
-               exit(-1);\r
-       }\r
-       \r
-       return target;\r
-}\r
-\r
-/* Process target initialization, when target entered debug out of reset\r
- * the handler is unregistered at the end of this function, so it's only called once\r
- */\r
-int target_init_handler(struct target_s *target, enum target_event event, void *priv)\r
-{\r
-       FILE *script;\r
-       struct command_context_s *cmd_ctx = priv;\r
-       \r
-       if ((event == TARGET_EVENT_HALTED) && (target->reset_script))\r
-       {\r
-               target_unregister_event_callback(target_init_handler, priv);\r
-\r
-               script = open_file_from_path(cmd_ctx, target->reset_script, "r");\r
-               if (!script)\r
-               {\r
-                       ERROR("couldn't open script file %s", target->reset_script);\r
-                               return ERROR_OK;\r
-               }\r
-\r
-               INFO("executing reset script '%s'", target->reset_script);\r
-               command_run_file(cmd_ctx, script, COMMAND_EXEC);\r
-               fclose(script);\r
-\r
-               jtag_execute_queue();\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_run_and_halt_handler(void *priv)\r
-{\r
-       target_t *target = priv;\r
-       \r
-       target->type->halt(target);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_process_reset(struct command_context_s *cmd_ctx)\r
-{\r
-       int retval = ERROR_OK;\r
-       target_t *target;\r
-       struct timeval timeout, now;\r
-       \r
-       /* prepare reset_halt where necessary */\r
-       target = targets;\r
-       while (target)\r
-       {\r
-               if (jtag_reset_config & RESET_SRST_PULLS_TRST)\r
-               {\r
-                       switch (target->reset_mode)\r
-                       {\r
-                               case RESET_HALT:\r
-                                       command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_HALT");\r
-                                       target->reset_mode = RESET_RUN_AND_HALT;\r
-                                       break;\r
-                               case RESET_INIT:\r
-                                       command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_INIT");\r
-                                       target->reset_mode = RESET_RUN_AND_INIT;\r
-                                       break;\r
-                               default:\r
-                                       break;\r
-                       } \r
-               }\r
-               switch (target->reset_mode)\r
-               {\r
-                       case RESET_HALT:\r
-                       case RESET_INIT:\r
-                               target->type->prepare_reset_halt(target);\r
-                               break;\r
-                       default:\r
-                               break;\r
-               }\r
-               target = target->next;\r
-       }\r
-       \r
-       target = targets;\r
-       while (target)\r
-       {\r
-               target->type->assert_reset(target);\r
-               target = target->next;\r
-       }\r
-       jtag_execute_queue();\r
-       \r
-       /* request target halt if necessary, and schedule further action */\r
-       target = targets;\r
-       while (target)\r
-       {\r
-               switch (target->reset_mode)\r
-               {\r
-                       case RESET_RUN:\r
-                               /* nothing to do if target just wants to be run */\r
-                               break;\r
-                       case RESET_RUN_AND_HALT:\r
-                               /* schedule halt */\r
-                               target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);\r
-                               break;\r
-                       case RESET_RUN_AND_INIT:\r
-                               /* schedule halt */\r
-                               target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);\r
-                               target_register_event_callback(target_init_handler, cmd_ctx);\r
-                               break;\r
-                       case RESET_HALT:\r
-                               target->type->halt(target);\r
-                               break;\r
-                       case RESET_INIT:\r
-                               target->type->halt(target);\r
-                               target_register_event_callback(target_init_handler, cmd_ctx);\r
-                               break;\r
-                       default:\r
-                               ERROR("BUG: unknown target->reset_mode");\r
-               }\r
-               target = target->next;\r
-       }\r
-       \r
-       target = targets;\r
-       while (target)\r
-       {\r
-               target->type->deassert_reset(target);\r
-               target = target->next;\r
-       }\r
-       jtag_execute_queue();\r
-\r
-       /* Wait for reset to complete, maximum 5 seconds. */    \r
-       gettimeofday(&timeout, NULL);\r
-       timeval_add_time(&timeout, 5, 0);\r
-       for(;;)\r
-       {\r
-               gettimeofday(&now, NULL);\r
-               \r
-               target_call_timer_callbacks();\r
-               \r
-               target = targets;\r
-               while (target)\r
-               {\r
-                       target->type->poll(target);\r
-                       if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT))\r
-                       {\r
-                               if (target->state != TARGET_HALTED)\r
-                               {\r
-                                       if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))\r
-                                       {\r
-                                               command_print(cmd_ctx, "Timed out waiting for reset");\r
-                                               goto done;\r
-                                       }\r
-                                       usleep(100*1000); /* Do not eat all cpu */\r
-                                       goto again;\r
-                               }\r
-                       }\r
-                       target = target->next;\r
-               }\r
-               /* All targets we're waiting for are halted */\r
-               break;\r
-               \r
-               again:;\r
-       }\r
-       done:\r
-       \r
-       \r
-       /* We want any events to be processed before the prompt */\r
-       target_call_timer_callbacks();\r
-       \r
-       return retval;\r
-}\r
-\r
-static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)\r
-{\r
-       *physical = virtual;\r
-       return ERROR_OK;\r
-}\r
-\r
-static int default_mmu(struct target_s *target, int *enabled)\r
-{\r
-       *enabled = 0;\r
-       return ERROR_OK;\r
-}\r
-\r
-int target_init(struct command_context_s *cmd_ctx)\r
-{\r
-       target_t *target = targets;\r
-       \r
-       while (target)\r
-       {\r
-               if (target->type->init_target(cmd_ctx, target) != ERROR_OK)\r
-               {\r
-                       ERROR("target '%s' init failed", target->type->name);\r
-                       exit(-1);\r
-               }\r
-               \r
-               /* Set up default functions if none are provided by target */\r
-               if (target->type->virt2phys == NULL)\r
-               {\r
-                       target->type->virt2phys = default_virt2phys;\r
-               }\r
-               if (target->type->mmu == NULL)\r
-               {\r
-                       target->type->mmu = default_mmu;\r
-               }\r
-               target = target->next;\r
-       }\r
-       \r
-       if (targets)\r
-       {\r
-               target_register_user_commands(cmd_ctx);\r
-               target_register_timer_callback(handle_target, 100, 1, NULL);\r
-       }\r
-               \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_init_reset(struct command_context_s *cmd_ctx)\r
-{\r
-       if (startup_mode == DAEMON_RESET)\r
-               target_process_reset(cmd_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)\r
-{\r
-       target_event_callback_t **callbacks_p = &target_event_callbacks;\r
-       \r
-       if (callback == NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-       \r
-       if (*callbacks_p)\r
-       {\r
-               while ((*callbacks_p)->next)\r
-                       callbacks_p = &((*callbacks_p)->next);\r
-               callbacks_p = &((*callbacks_p)->next);\r
-       }\r
-       \r
-       (*callbacks_p) = malloc(sizeof(target_event_callback_t));\r
-       (*callbacks_p)->callback = callback;\r
-       (*callbacks_p)->priv = priv;\r
-       (*callbacks_p)->next = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)\r
-{\r
-       target_timer_callback_t **callbacks_p = &target_timer_callbacks;\r
-       struct timeval now;\r
-       \r
-       if (callback == NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-       \r
-       if (*callbacks_p)\r
-       {\r
-               while ((*callbacks_p)->next)\r
-                       callbacks_p = &((*callbacks_p)->next);\r
-               callbacks_p = &((*callbacks_p)->next);\r
-       }\r
-       \r
-       (*callbacks_p) = malloc(sizeof(target_timer_callback_t));\r
-       (*callbacks_p)->callback = callback;\r
-       (*callbacks_p)->periodic = periodic;\r
-       (*callbacks_p)->time_ms = time_ms;\r
-       \r
-       gettimeofday(&now, NULL);\r
-       (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;\r
-       time_ms -= (time_ms % 1000);\r
-       (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);\r
-       if ((*callbacks_p)->when.tv_usec > 1000000)\r
-       {\r
-               (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;\r
-               (*callbacks_p)->when.tv_sec += 1;\r
-       }\r
-       \r
-       (*callbacks_p)->priv = priv;\r
-       (*callbacks_p)->next = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)\r
-{\r
-       target_event_callback_t **p = &target_event_callbacks;\r
-       target_event_callback_t *c = target_event_callbacks;\r
-       \r
-       if (callback == NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-               \r
-       while (c)\r
-       {\r
-               target_event_callback_t *next = c->next;\r
-               if ((c->callback == callback) && (c->priv == priv))\r
-               {\r
-                       *p = next;\r
-                       free(c);\r
-                       return ERROR_OK;\r
-               }\r
-               else\r
-                       p = &(c->next);\r
-               c = next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)\r
-{\r
-       target_timer_callback_t **p = &target_timer_callbacks;\r
-       target_timer_callback_t *c = target_timer_callbacks;\r
-       \r
-       if (callback == NULL)\r
-       {\r
-               return ERROR_INVALID_ARGUMENTS;\r
-       }\r
-               \r
-       while (c)\r
-       {\r
-               target_timer_callback_t *next = c->next;\r
-               if ((c->callback == callback) && (c->priv == priv))\r
-               {\r
-                       *p = next;\r
-                       free(c);\r
-                       return ERROR_OK;\r
-               }\r
-               else\r
-                       p = &(c->next);\r
-               c = next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_call_event_callbacks(target_t *target, enum target_event event)\r
-{\r
-       target_event_callback_t *callback = target_event_callbacks;\r
-       target_event_callback_t *next_callback;\r
-       \r
-       DEBUG("target event %i", event);\r
-       \r
-       while (callback)\r
-       {\r
-               next_callback = callback->next;\r
-               callback->callback(target, event, callback->priv);\r
-               callback = next_callback;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_call_timer_callbacks()\r
-{\r
-       target_timer_callback_t *callback = target_timer_callbacks;\r
-       target_timer_callback_t *next_callback;\r
-       struct timeval now;\r
-\r
-       gettimeofday(&now, NULL);\r
-       \r
-       while (callback)\r
-       {\r
-               next_callback = callback->next;\r
-               \r
-               if (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec))\r
-                       || (now.tv_sec > callback->when.tv_sec))\r
-               {\r
-                       callback->callback(callback->priv);\r
-                       if (callback->periodic)\r
-                       {\r
-                               int time_ms = callback->time_ms;\r
-                               callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;\r
-                               time_ms -= (time_ms % 1000);\r
-                               callback->when.tv_sec = now.tv_sec + time_ms / 1000;\r
-                               if (callback->when.tv_usec > 1000000)\r
-                               {\r
-                                       callback->when.tv_usec = callback->when.tv_usec - 1000000;\r
-                                       callback->when.tv_sec += 1;\r
-                               }\r
-                       }\r
-                       else\r
-                               target_unregister_timer_callback(callback->callback, callback->priv);\r
-               }\r
-                       \r
-               callback = next_callback;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)\r
-{\r
-       working_area_t *c = target->working_areas;\r
-       working_area_t *new_wa = NULL;\r
-       \r
-       /* Reevaluate working area address based on MMU state*/\r
-       if (target->working_areas == NULL)\r
-       {\r
-               int retval;\r
-               int enabled;\r
-               retval = target->type->mmu(target, &enabled);\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       return retval;\r
-               }\r
-               if (enabled)\r
-               {\r
-                       target->working_area = target->working_area_virt;\r
-               }\r
-               else\r
-               {\r
-                       target->working_area = target->working_area_phys;\r
-               }\r
-       }\r
-       \r
-       /* only allocate multiples of 4 byte */\r
-       if (size % 4)\r
-       {\r
-               ERROR("BUG: code tried to allocate unaligned number of bytes, padding");\r
-               size = CEIL(size, 4);\r
-       }\r
-       \r
-       /* see if there's already a matching working area */\r
-       while (c)\r
-       {\r
-               if ((c->free) && (c->size == size))\r
-               {\r
-                       new_wa = c;\r
-                       break;\r
-               }\r
-               c = c->next;\r
-       }\r
-       \r
-       /* if not, allocate a new one */\r
-       if (!new_wa)\r
-       {\r
-               working_area_t **p = &target->working_areas;\r
-               u32 first_free = target->working_area;\r
-               u32 free_size = target->working_area_size;\r
-               \r
-               DEBUG("allocating new working area");\r
-               \r
-               c = target->working_areas;\r
-               while (c)\r
-               {\r
-                       first_free += c->size;\r
-                       free_size -= c->size;\r
-                       p = &c->next;\r
-                       c = c->next;\r
-               }\r
-               \r
-               if (free_size < size)\r
-               {\r
-                       WARNING("not enough working area available(requested %d, free %d)", size, free_size);\r
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-               }\r
-               \r
-               new_wa = malloc(sizeof(working_area_t));\r
-               new_wa->next = NULL;\r
-               new_wa->size = size;\r
-               new_wa->address = first_free;\r
-               \r
-               if (target->backup_working_area)\r
-               {\r
-                       new_wa->backup = malloc(new_wa->size);\r
-                       target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup);\r
-               }\r
-               else\r
-               {\r
-                       new_wa->backup = NULL;\r
-               }\r
-               \r
-               /* put new entry in list */\r
-               *p = new_wa;\r
-       }\r
-       \r
-       /* mark as used, and return the new (reused) area */\r
-       new_wa->free = 0;\r
-       *area = new_wa;\r
-       \r
-       /* user pointer */\r
-       new_wa->user = area;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_free_working_area(struct target_s *target, working_area_t *area)\r
-{\r
-       if (area->free)\r
-               return ERROR_OK;\r
-       \r
-       if (target->backup_working_area)\r
-               target->type->write_memory(target, area->address, 4, area->size / 4, area->backup);\r
-       \r
-       area->free = 1;\r
-       \r
-       /* mark user pointer invalid */\r
-       *area->user = NULL;\r
-       area->user = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_free_all_working_areas(struct target_s *target)\r
-{\r
-       working_area_t *c = target->working_areas;\r
-\r
-       while (c)\r
-       {\r
-               working_area_t *next = c->next;\r
-               target_free_working_area(target, c);\r
-               \r
-               if (c->backup)\r
-                       free(c->backup);\r
-               \r
-               free(c);\r
-               \r
-               c = next;\r
-       }\r
-       \r
-       target->working_areas = NULL;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL);\r
-       register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, NULL);\r
-       register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");\r
-       register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int target_arch_state(struct target_s *target)\r
-{\r
-       int retval;\r
-       if (target==NULL)\r
-       {\r
-               USER("No target has been configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       USER("target state: %s", target_state_strings[target->state]);\r
-       \r
-       if (target->state!=TARGET_HALTED)\r
-               return ERROR_OK;\r
-       \r
-       retval=target->type->arch_state(target);\r
-       return retval;\r
-}\r
-\r
-/* Single aligned words are guaranteed to use 16 or 32 bit access \r
- * mode respectively, otherwise data is handled as quickly as \r
- * possible\r
- */\r
-int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)\r
-{\r
-       int retval;\r
-       \r
-       DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);\r
-       \r
-       if (((address % 2) == 0) && (size == 2))\r
-       {\r
-               return target->type->write_memory(target, address, 2, 1, buffer);\r
-       }\r
-       \r
-       /* handle unaligned head bytes */\r
-       if (address % 4)\r
-       {\r
-               int unaligned = 4 - (address % 4);\r
-               \r
-               if (unaligned > size)\r
-                       unaligned = size;\r
-\r
-               if ((retval = target->type->write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)\r
-                       return retval;\r
-               \r
-               buffer += unaligned;\r
-               address += unaligned;\r
-               size -= unaligned;\r
-       }\r
-               \r
-       /* handle aligned words */\r
-       if (size >= 4)\r
-       {\r
-               int aligned = size - (size % 4);\r
-       \r
-               /* use bulk writes above a certain limit. This may have to be changed */\r
-               if (aligned > 128)\r
-               {\r
-                       if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)\r
-                               return retval;\r
-               }\r
-               else\r
-               {\r
-                       if ((retval = target->type->write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)\r
-                               return retval;\r
-               }\r
-               \r
-               buffer += aligned;\r
-               address += aligned;\r
-               size -= aligned;\r
-       }\r
-       \r
-       /* handle tail writes of less than 4 bytes */\r
-       if (size > 0)\r
-       {\r
-               if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)\r
-                       return retval;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-/* Single aligned words are guaranteed to use 16 or 32 bit access \r
- * mode respectively, otherwise data is handled as quickly as \r
- * possible\r
- */\r
-int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)\r
-{\r
-       int retval;\r
-       \r
-       DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);\r
-       \r
-       if (((address % 2) == 0) && (size == 2))\r
-       {\r
-               return target->type->read_memory(target, address, 2, 1, buffer);\r
-       }\r
-       \r
-       /* handle unaligned head bytes */\r
-       if (address % 4)\r
-       {\r
-               int unaligned = 4 - (address % 4);\r
-               \r
-               if (unaligned > size)\r
-                       unaligned = size;\r
-\r
-               if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)\r
-                       return retval;\r
-               \r
-               buffer += unaligned;\r
-               address += unaligned;\r
-               size -= unaligned;\r
-       }\r
-               \r
-       /* handle aligned words */\r
-       if (size >= 4)\r
-       {\r
-               int aligned = size - (size % 4);\r
-       \r
-               if ((retval = target->type->read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)\r
-                       return retval;\r
-               \r
-               buffer += aligned;\r
-               address += aligned;\r
-               size -= aligned;\r
-       }\r
-       \r
-       /* handle tail writes of less than 4 bytes */\r
-       if (size > 0)\r
-       {\r
-               if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)\r
-                       return retval;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)\r
-{\r
-       u8 *buffer;\r
-       int retval;\r
-       int i;\r
-       u32 checksum = 0;\r
-       \r
-       if ((retval = target->type->checksum_memory(target, address,\r
-               size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)\r
-       {\r
-               buffer = malloc(size);\r
-               if (buffer == NULL)\r
-               {\r
-                       ERROR("error allocating buffer for section (%d bytes)", size);\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-               retval = target_read_buffer(target, address, size, buffer);\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       free(buffer);\r
-                       return retval;\r
-               }\r
-\r
-               /* convert to target endianess */\r
-               for (i = 0; i < (size/sizeof(u32)); i++)\r
-               {\r
-                       u32 target_data;\r
-                       target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);\r
-                       target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);\r
-               }\r
-\r
-               retval = image_calculate_checksum( buffer, size, &checksum );\r
-               free(buffer);\r
-       }\r
-       \r
-       *crc = checksum;\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_read_u32(struct target_s *target, u32 address, u32 *value)\r
-{\r
-       u8 value_buf[4];\r
-\r
-       int retval = target->type->read_memory(target, address, 4, 1, value_buf);\r
-       \r
-       if (retval == ERROR_OK)\r
-       {\r
-               *value = target_buffer_get_u32(target, value_buf);\r
-               DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);\r
-       }\r
-       else\r
-       {\r
-               *value = 0x0;\r
-               DEBUG("address: 0x%8.8x failed", address);\r
-       }\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_read_u16(struct target_s *target, u32 address, u16 *value)\r
-{\r
-       u8 value_buf[2];\r
-       \r
-       int retval = target->type->read_memory(target, address, 2, 1, value_buf);\r
-       \r
-       if (retval == ERROR_OK)\r
-       {\r
-               *value = target_buffer_get_u16(target, value_buf);\r
-               DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);\r
-       }\r
-       else\r
-       {\r
-               *value = 0x0;\r
-               DEBUG("address: 0x%8.8x failed", address);\r
-       }\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_read_u8(struct target_s *target, u32 address, u8 *value)\r
-{\r
-       int retval = target->type->read_memory(target, address, 1, 1, value);\r
-\r
-       if (retval == ERROR_OK)\r
-       {\r
-               DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);\r
-       }\r
-       else\r
-       {\r
-               *value = 0x0;\r
-               DEBUG("address: 0x%8.8x failed", address);\r
-       }\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_write_u32(struct target_s *target, u32 address, u32 value)\r
-{\r
-       int retval;\r
-       u8 value_buf[4];\r
-\r
-       DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);\r
-\r
-       target_buffer_set_u32(target, value_buf, value);        \r
-       if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)\r
-       {\r
-               DEBUG("failed: %i", retval);\r
-       }\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_write_u16(struct target_s *target, u32 address, u16 value)\r
-{\r
-       int retval;\r
-       u8 value_buf[2];\r
-       \r
-       DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);\r
-\r
-       target_buffer_set_u16(target, value_buf, value);        \r
-       if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)\r
-       {\r
-               DEBUG("failed: %i", retval);\r
-       }\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_write_u8(struct target_s *target, u32 address, u8 value)\r
-{\r
-       int retval;\r
-       \r
-       DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);\r
-\r
-       if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)\r
-       {\r
-               DEBUG("failed: %i", retval);\r
-       }\r
-       \r
-       return retval;\r
-}\r
-\r
-int target_register_user_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx,  NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL);\r
-       register_command(cmd_ctx,  NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");\r
-       register_command(cmd_ctx,  NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");\r
-       register_command(cmd_ctx,  NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");\r
-       register_command(cmd_ctx,  NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");\r
-       register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");\r
-       register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init|run_and_halt|run_and_init]");\r
-       register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");\r
-\r
-       register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");\r
-       register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");\r
-       register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");\r
-       \r
-       register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value>");\r
-       register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value>");\r
-       register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value>");\r
-       \r
-       register_command(cmd_ctx,  NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");      \r
-       register_command(cmd_ctx,  NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");\r
-       register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");    \r
-       register_command(cmd_ctx,  NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");\r
-       \r
-       register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");\r
-       register_command(cmd_ctx,  NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");\r
-       register_command(cmd_ctx,  NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");\r
-       register_command(cmd_ctx,  NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");\r
-       register_command(cmd_ctx,  NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");\r
-       \r
-       target_request_register_commands(cmd_ctx);\r
-       trace_register_commands(cmd_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = targets;\r
-       int count = 0;\r
-       \r
-       if (argc == 1)\r
-       {\r
-               int num = strtoul(args[0], NULL, 0);\r
-               \r
-               while (target)\r
-               {\r
-                       count++;\r
-                       target = target->next;\r
-               }\r
-               \r
-               if (num < count)\r
-                       cmd_ctx->current_target = num;\r
-               else\r
-                       command_print(cmd_ctx, "%i is out of bounds, only %i targets are configured", num, count);\r
-                       \r
-               return ERROR_OK;\r
-       }\r
-               \r
-       while (target)\r
-       {\r
-               command_print(cmd_ctx, "%i: %s (%s), state: %s", count++, target->type->name, target_endianess_strings[target->endianness], target_state_strings[target->state]);\r
-               target = target->next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int i;\r
-       int found = 0;\r
-       \r
-       if (argc < 3)\r
-       {\r
-               ERROR("target command requires at least three arguments: <type> <endianess> <reset_mode>");\r
-               exit(-1);\r
-       }\r
-       \r
-       /* search for the specified target */\r
-       if (args[0] && (args[0][0] != 0))\r
-       {\r
-               for (i = 0; target_types[i]; i++)\r
-               {\r
-                       if (strcmp(args[0], target_types[i]->name) == 0)\r
-                       {\r
-                               target_t **last_target_p = &targets;\r
-                               \r
-                               /* register target specific commands */\r
-                               if (target_types[i]->register_commands(cmd_ctx) != ERROR_OK)\r
-                               {\r
-                                       ERROR("couldn't register '%s' commands", args[0]);\r
-                                       exit(-1);\r
-                               }\r
-\r
-                               if (*last_target_p)\r
-                               {\r
-                                       while ((*last_target_p)->next)\r
-                                               last_target_p = &((*last_target_p)->next);\r
-                                       last_target_p = &((*last_target_p)->next);\r
-                               }\r
-\r
-                               *last_target_p = malloc(sizeof(target_t));\r
-                               \r
-                               (*last_target_p)->type = target_types[i];\r
-                               \r
-                               if (strcmp(args[1], "big") == 0)\r
-                                       (*last_target_p)->endianness = TARGET_BIG_ENDIAN;\r
-                               else if (strcmp(args[1], "little") == 0)\r
-                                       (*last_target_p)->endianness = TARGET_LITTLE_ENDIAN;\r
-                               else\r
-                               {\r
-                                       ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]);\r
-                                       exit(-1);\r
-                               }\r
-                               \r
-                               /* what to do on a target reset */\r
-                               if (strcmp(args[2], "reset_halt") == 0)\r
-                                       (*last_target_p)->reset_mode = RESET_HALT;\r
-                               else if (strcmp(args[2], "reset_run") == 0)\r
-                                       (*last_target_p)->reset_mode = RESET_RUN;\r
-                               else if (strcmp(args[2], "reset_init") == 0)\r
-                                       (*last_target_p)->reset_mode = RESET_INIT;\r
-                               else if (strcmp(args[2], "run_and_halt") == 0)\r
-                                       (*last_target_p)->reset_mode = RESET_RUN_AND_HALT;\r
-                               else if (strcmp(args[2], "run_and_init") == 0)\r
-                                       (*last_target_p)->reset_mode = RESET_RUN_AND_INIT;\r
-                               else\r
-                               {\r
-                                       ERROR("unknown target startup mode %s", args[2]);\r
-                                       exit(-1);\r
-                               }\r
-                               (*last_target_p)->run_and_halt_time = 1000; /* default 1s */\r
-                               \r
-                               (*last_target_p)->reset_script = NULL;\r
-                               (*last_target_p)->post_halt_script = NULL;\r
-                               (*last_target_p)->pre_resume_script = NULL;\r
-                               (*last_target_p)->gdb_program_script = NULL;\r
-                               \r
-                               (*last_target_p)->working_area = 0x0;\r
-                               (*last_target_p)->working_area_size = 0x0;\r
-                               (*last_target_p)->working_areas = NULL;\r
-                               (*last_target_p)->backup_working_area = 0;\r
-                               \r
-                               (*last_target_p)->state = TARGET_UNKNOWN;\r
-                               (*last_target_p)->reg_cache = NULL;\r
-                               (*last_target_p)->breakpoints = NULL;\r
-                               (*last_target_p)->watchpoints = NULL;\r
-                               (*last_target_p)->next = NULL;\r
-                               (*last_target_p)->arch_info = NULL;\r
-                               \r
-                               /* initialize trace information */\r
-                               (*last_target_p)->trace_info = malloc(sizeof(trace_t));\r
-                               (*last_target_p)->trace_info->num_trace_points = 0;\r
-                               (*last_target_p)->trace_info->trace_points_size = 0;\r
-                               (*last_target_p)->trace_info->trace_points = NULL;\r
-                               (*last_target_p)->trace_info->trace_history_size = 0;\r
-                               (*last_target_p)->trace_info->trace_history = NULL;\r
-                               (*last_target_p)->trace_info->trace_history_pos = 0;\r
-                               (*last_target_p)->trace_info->trace_history_overflowed = 0;\r
-                               \r
-                               (*last_target_p)->dbgmsg = NULL;\r
-                               (*last_target_p)->dbg_msg_enabled = 0;\r
-                                                               \r
-                               (*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);\r
-                               \r
-                               found = 1;\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-       \r
-       /* no matching target found */\r
-       if (!found)\r
-       {\r
-               ERROR("target '%s' not found", args[0]);\r
-               exit(-1);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* usage: target_script <target#> <event> <script_file> */\r
-int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = NULL;\r
-       \r
-       if (argc < 3)\r
-       {\r
-               ERROR("incomplete target_script command");\r
-               exit(-1);\r
-       }\r
-       \r
-       target = get_target_by_num(strtoul(args[0], NULL, 0));\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("target number '%s' not defined", args[0]);\r
-               exit(-1);\r
-       }\r
-       \r
-       if (strcmp(args[1], "reset") == 0)\r
-       {\r
-               if (target->reset_script)\r
-                       free(target->reset_script);\r
-               target->reset_script = strdup(args[2]);\r
-       }\r
-       else if (strcmp(args[1], "post_halt") == 0)\r
-       {\r
-               if (target->post_halt_script)\r
-                       free(target->post_halt_script);\r
-               target->post_halt_script = strdup(args[2]);\r
-       }\r
-       else if (strcmp(args[1], "pre_resume") == 0)\r
-       {\r
-               if (target->pre_resume_script)\r
-                       free(target->pre_resume_script);\r
-               target->pre_resume_script = strdup(args[2]);\r
-       }\r
-       else if (strcmp(args[1], "gdb_program_config") == 0)\r
-       {\r
-               if (target->gdb_program_script)\r
-                       free(target->gdb_program_script);\r
-               target->gdb_program_script = strdup(args[2]);\r
-       }\r
-       else\r
-       {\r
-               ERROR("unknown event type: '%s", args[1]);\r
-               exit(-1);       \r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = NULL;\r
-       \r
-       if (argc < 2)\r
-       {\r
-               ERROR("incomplete run_and_halt_time command");\r
-               exit(-1);\r
-       }\r
-       \r
-       target = get_target_by_num(strtoul(args[0], NULL, 0));\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("target number '%s' not defined", args[0]);\r
-               exit(-1);\r
-       }\r
-       \r
-       target->run_and_halt_time = strtoul(args[1], NULL, 0);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = NULL;\r
-       \r
-       if ((argc < 4) || (argc > 5))\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       \r
-       target = get_target_by_num(strtoul(args[0], NULL, 0));\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("target number '%s' not defined", args[0]);\r
-               exit(-1);\r
-       }\r
-       target_free_all_working_areas(target);\r
-       \r
-       target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);\r
-       if (argc == 5)\r
-       {\r
-               target->working_area_virt = strtoul(args[4], NULL, 0);\r
-       }\r
-       target->working_area_size = strtoul(args[2], NULL, 0);\r
-       \r
-       if (strcmp(args[3], "backup") == 0)\r
-       {\r
-               target->backup_working_area = 1;\r
-       }\r
-       else if (strcmp(args[3], "nobackup") == 0)\r
-       {\r
-               target->backup_working_area = 0;\r
-       }\r
-       else\r
-       {\r
-               ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-\r
-/* process target state changes */\r
-int handle_target(void *priv)\r
-{\r
-       int retval;\r
-       target_t *target = targets;\r
-       \r
-       while (target)\r
-       {\r
-               /* only poll if target isn't already halted */\r
-               if (target->state != TARGET_HALTED)\r
-               {\r
-                       if (target_continous_poll)\r
-                               if ((retval = target->type->poll(target)) != ERROR_OK)\r
-                               {\r
-                                       ERROR("couldn't poll target(%d). It's due for a reset.", retval);\r
-                               }\r
-               }\r
-       \r
-               target = target->next;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       reg_t *reg = NULL;\r
-       int count = 0;\r
-       char *value;\r
-       \r
-       DEBUG("-");\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       /* list all available registers for the current target */\r
-       if (argc == 0)\r
-       {\r
-               reg_cache_t *cache = target->reg_cache;\r
-               \r
-               count = 0;\r
-               while(cache)\r
-               {\r
-                       int i;\r
-                       for (i = 0; i < cache->num_regs; i++)\r
-                       {\r
-                               value = buf_to_str(cache->reg_list[i].value, cache->reg_list[i].size, 16);\r
-                               command_print(cmd_ctx, "(%i) %s (/%i): 0x%s (dirty: %i, valid: %i)", count++, cache->reg_list[i].name, cache->reg_list[i].size, value, cache->reg_list[i].dirty, cache->reg_list[i].valid);\r
-                               free(value);\r
-                       }\r
-                       cache = cache->next;\r
-               }\r
-               \r
-               return ERROR_OK;\r
-       }\r
-       \r
-       /* access a single register by its ordinal number */\r
-       if ((args[0][0] >= '0') && (args[0][0] <= '9'))\r
-       {\r
-               int num = strtoul(args[0], NULL, 0);\r
-               reg_cache_t *cache = target->reg_cache;\r
-               \r
-               count = 0;\r
-               while(cache)\r
-               {\r
-                       int i;\r
-                       for (i = 0; i < cache->num_regs; i++)\r
-                       {\r
-                               if (count++ == num)\r
-                               {\r
-                                       reg = &cache->reg_list[i];\r
-                                       break;\r
-                               }\r
-                       }\r
-                       if (reg)\r
-                               break;\r
-                       cache = cache->next;\r
-               }\r
-               \r
-               if (!reg)\r
-               {\r
-                       command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);\r
-                       return ERROR_OK;\r
-               }\r
-       } else /* access a single register by its name */\r
-       {\r
-               reg = register_get_by_name(target->reg_cache, args[0], 1);\r
-               \r
-               if (!reg)\r
-               {\r
-                       command_print(cmd_ctx, "register %s not found in current target", args[0]);\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-\r
-       /* display a register */\r
-       if ((argc == 1) || ((argc == 2) && !((args[1][0] >= '0') && (args[1][0] <= '9'))))\r
-       {\r
-               if ((argc == 2) && (strcmp(args[1], "force") == 0))\r
-                       reg->valid = 0;\r
-               \r
-               if (reg->valid == 0)\r
-               {\r
-                       reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);\r
-                       if (arch_type == NULL)\r
-                       {\r
-                               ERROR("BUG: encountered unregistered arch type");\r
-                               return ERROR_OK;\r
-                       }\r
-                       arch_type->get(reg);\r
-               }\r
-               value = buf_to_str(reg->value, reg->size, 16);\r
-               command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);\r
-               free(value);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       /* set register value */\r
-       if (argc == 2)\r
-       {\r
-               u8 *buf = malloc(CEIL(reg->size, 8));\r
-               str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);\r
-\r
-               reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);\r
-               if (arch_type == NULL)\r
-               {\r
-                       ERROR("BUG: encountered unregistered arch type");\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               arch_type->set(reg, buf);\r
-               \r
-               value = buf_to_str(reg->value, reg->size, 16);\r
-               command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);\r
-               free(value);\r
-               \r
-               free(buf);\r
-               \r
-               return ERROR_OK;\r
-       }\r
-       \r
-       command_print(cmd_ctx, "usage: reg <#|name> [value]");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms);\r
-\r
-int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc == 0)\r
-       {\r
-               target->type->poll(target);\r
-                       target_arch_state(target);\r
-       }\r
-       else\r
-       {\r
-               if (strcmp(args[0], "on") == 0)\r
-               {\r
-                       target_continous_poll = 1;\r
-               }\r
-               else if (strcmp(args[0], "off") == 0)\r
-               {\r
-                       target_continous_poll = 0;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "arg is \"on\" or \"off\"");\r
-               }\r
-       }\r
-       \r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int ms = 5000;\r
-       \r
-       if (argc > 0)\r
-       {\r
-               char *end;\r
-\r
-               ms = strtoul(args[0], &end, 0) * 1000;\r
-               if (*end)\r
-               {\r
-                       command_print(cmd_ctx, "usage: %s [seconds]", cmd);\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-\r
-       return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); \r
-}\r
-\r
-static void target_process_events(struct command_context_s *cmd_ctx)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       target->type->poll(target);\r
-       target_call_timer_callbacks();\r
-}\r
-\r
-static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms)\r
-{\r
-       int retval;\r
-       struct timeval timeout, now;\r
-       \r
-       gettimeofday(&timeout, NULL);\r
-       timeval_add_time(&timeout, 0, ms * 1000);\r
-       \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       for (;;)\r
-       {\r
-               if ((retval=target->type->poll(target))!=ERROR_OK)\r
-                       return retval;\r
-               target_call_timer_callbacks();\r
-               if (target->state == state)\r
-               {\r
-                       break;\r
-               }\r
-               command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]);\r
-               \r
-               gettimeofday(&now, NULL);\r
-               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))\r
-               {\r
-                       command_print(cmd_ctx, "timed out while waiting for target %s", target_state_strings[state]);\r
-                       ERROR("timed out while waiting for target %s", target_state_strings[state]);\r
-                       break;\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       DEBUG("-");\r
-       \r
-       command_print(cmd_ctx, "requesting target halt...");\r
-\r
-       if ((retval = target->type->halt(target)) != ERROR_OK)\r
-       {       \r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_ALREADY_HALTED:\r
-                               command_print(cmd_ctx, "target already halted");\r
-                               break;\r
-                       case ERROR_TARGET_TIMEOUT:\r
-                               command_print(cmd_ctx, "target timed out... shutting down");\r
-                               return retval;\r
-                       default:\r
-                               command_print(cmd_ctx, "unknown error... shutting down");\r
-                               return retval;\r
-               }\r
-       }\r
-       \r
-       return handle_wait_halt_command(cmd_ctx, cmd, args, argc);\r
-}\r
-\r
-/* what to do on daemon startup */\r
-int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       if (argc == 1)\r
-       {\r
-               if (strcmp(args[0], "attach") == 0)\r
-               {\r
-                       startup_mode = DAEMON_ATTACH;\r
-                       return ERROR_OK;\r
-               }\r
-               else if (strcmp(args[0], "reset") == 0)\r
-               {\r
-                       startup_mode = DAEMON_RESET;\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       \r
-       WARNING("invalid daemon_startup configuration directive: %s", args[0]);\r
-       return ERROR_OK;\r
-\r
-}\r
-               \r
-int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       int retval;\r
-       \r
-       command_print(cmd_ctx, "requesting target halt and executing a soft reset");\r
-       \r
-       if ((retval = target->type->soft_reset_halt(target)) != ERROR_OK)\r
-       {       \r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_TIMEOUT:\r
-                               command_print(cmd_ctx, "target timed out... shutting down");\r
-                               exit(-1);\r
-                       default:\r
-                               command_print(cmd_ctx, "unknown error... shutting down");\r
-                               exit(-1);\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       enum target_reset_mode reset_mode = target->reset_mode;\r
-       enum target_reset_mode save = target->reset_mode;\r
-       \r
-       DEBUG("-");\r
-       \r
-       if (argc >= 1)\r
-       {\r
-               if (strcmp("run", args[0]) == 0)\r
-                       reset_mode = RESET_RUN;\r
-               else if (strcmp("halt", args[0]) == 0)\r
-                       reset_mode = RESET_HALT;\r
-               else if (strcmp("init", args[0]) == 0)\r
-                       reset_mode = RESET_INIT;\r
-               else if (strcmp("run_and_halt", args[0]) == 0)\r
-               {\r
-                       reset_mode = RESET_RUN_AND_HALT;\r
-                       if (argc >= 2)\r
-                       {\r
-                               target->run_and_halt_time = strtoul(args[1], NULL, 0);\r
-                       }\r
-               }\r
-               else if (strcmp("run_and_init", args[0]) == 0)\r
-               {\r
-                       reset_mode = RESET_RUN_AND_INIT;\r
-                       if (argc >= 2)\r
-                       {\r
-                               target->run_and_halt_time = strtoul(args[1], NULL, 0);\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]");\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       \r
-       /* temporarily modify mode of current reset target */\r
-       target->reset_mode = reset_mode;\r
-\r
-       /* reset *all* targets */\r
-       target_process_reset(cmd_ctx);\r
-       \r
-       /* Restore default reset mode for this target */\r
-    target->reset_mode = save;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       \r
-       if (argc == 0)\r
-               retval = target->type->resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */\r
-       else if (argc == 1)\r
-               retval = target->type->resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */\r
-       else\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-\r
-       target_process_events(cmd_ctx);\r
-       \r
-       target_arch_state(target);\r
-       \r
-       return retval;\r
-}\r
-\r
-int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       \r
-       DEBUG("-");\r
-       \r
-       if (argc == 0)\r
-               target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */\r
-\r
-       if (argc == 1)\r
-               target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       const int line_bytecnt = 32;\r
-       int count = 1;\r
-       int size = 4;\r
-       u32 address = 0;\r
-       int line_modulo;\r
-       int i;\r
-\r
-       char output[128];\r
-       int output_len;\r
-\r
-       int retval;\r
-\r
-       u8 *buffer;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc < 1)\r
-               return ERROR_OK;\r
-\r
-       if (argc == 2)\r
-               count = strtoul(args[1], NULL, 0);\r
-\r
-       address = strtoul(args[0], NULL, 0);\r
-       \r
-\r
-       switch (cmd[2])\r
-       {\r
-               case 'w':\r
-                       size = 4; line_modulo = line_bytecnt / 4;\r
-                       break;\r
-               case 'h':\r
-                       size = 2; line_modulo = line_bytecnt / 2;\r
-                       break;\r
-               case 'b':\r
-                       size = 1; line_modulo = line_bytecnt / 1;\r
-                       break;\r
-               default:\r
-                       return ERROR_OK;\r
-       }\r
-\r
-       buffer = calloc(count, size);\r
-       retval  = target->type->read_memory(target, address, size, count, buffer);\r
-       if (retval != ERROR_OK)\r
-       {\r
-               switch (retval)\r
-               {\r
-                       case ERROR_TARGET_UNALIGNED_ACCESS:\r
-                               command_print(cmd_ctx, "error: address not aligned");\r
-                               break;\r
-                       case ERROR_TARGET_NOT_HALTED:\r
-                               command_print(cmd_ctx, "error: target must be halted for memory accesses");\r
-                               break;                  \r
-                       case ERROR_TARGET_DATA_ABORT:\r
-                               command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");\r
-                               break;\r
-                       default:\r
-                               command_print(cmd_ctx, "error: unknown error");\r
-                               break;\r
-               }\r
-               return ERROR_OK;\r
-       }\r
-\r
-       output_len = 0;\r
-\r
-       for (i = 0; i < count; i++)\r
-       {\r
-               if (i%line_modulo == 0)\r
-                       output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));\r
-               \r
-               switch (size)\r
-               {\r
-                       case 4:\r
-                               output_len += snprintf(output + output_len, 128 - output_len, "%8.8x ", target_buffer_get_u32(target, &buffer[i*4]));\r
-                               break;\r
-                       case 2:\r
-                               output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));\r
-                               break;\r
-                       case 1:\r
-                               output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);\r
-                               break;\r
-               }\r
-\r
-               if ((i%line_modulo == line_modulo-1) || (i == count - 1))\r
-               {\r
-                       command_print(cmd_ctx, output);\r
-                       output_len = 0;\r
-               }\r
-       }\r
-\r
-       free(buffer);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       u32 address = 0;\r
-       u32 value = 0;\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       u8 value_buf[4];\r
-\r
-       if (argc < 2)\r
-               return ERROR_OK;\r
-\r
-       address = strtoul(args[0], NULL, 0);\r
-       value = strtoul(args[1], NULL, 0);\r
-\r
-       switch (cmd[2])\r
-       {\r
-               case 'w':\r
-                       target_buffer_set_u32(target, value_buf, value);\r
-                       retval = target->type->write_memory(target, address, 4, 1, value_buf);\r
-                       break;\r
-               case 'h':\r
-                       target_buffer_set_u16(target, value_buf, value);\r
-                       retval = target->type->write_memory(target, address, 2, 1, value_buf);\r
-                       break;\r
-               case 'b':\r
-                       value_buf[0] = value;\r
-                       retval = target->type->write_memory(target, address, 1, 1, value_buf);\r
-                       break;\r
-               default:\r
-                       return ERROR_OK;\r
-       }\r
-\r
-       switch (retval)\r
-       {\r
-               case ERROR_TARGET_UNALIGNED_ACCESS:\r
-                       command_print(cmd_ctx, "error: address not aligned");\r
-                       break;\r
-               case ERROR_TARGET_DATA_ABORT:\r
-                       command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");\r
-                       break;\r
-               case ERROR_TARGET_NOT_HALTED:\r
-                       command_print(cmd_ctx, "error: target must be halted for memory accesses");\r
-                       break;\r
-               case ERROR_OK:\r
-                       break;\r
-               default:\r
-                       command_print(cmd_ctx, "error: unknown error");\r
-                       break;\r
-       }\r
-\r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int handle_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
-       int i;\r
-       int retval;\r
-\r
-       image_t image;  \r
-       \r
-       duration_t duration;\r
-       char *duration_text;\r
-       \r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");\r
-               return ERROR_OK;\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
-       image.start_address_set = 0;\r
-\r
-       duration_start_measure(&duration);\r
-       \r
-       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "load_image error: %s", image.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       image_size = 0x0;\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
-                       ERROR("image_read_section failed with error code: %i", retval);\r
-                       command_print(cmd_ctx, "image reading failed, download aborted");\r
-                       free(buffer);\r
-                       image_close(&image);\r
-                       return ERROR_OK;\r
-               }\r
-               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);\r
-               image_size += buf_cnt;\r
-               command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);\r
-               \r
-               free(buffer);\r
-       }\r
-\r
-       duration_stop_measure(&duration, &duration_text);\r
-       command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);\r
-       free(duration_text);\r
-       \r
-       image_close(&image);\r
-\r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       fileio_t fileio;\r
-       \r
-       u32 address;\r
-       u32 size;\r
-       u8 buffer[560];\r
-       int retval;\r
-       \r
-       duration_t duration;\r
-       char *duration_text;\r
-       \r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc != 3)\r
-       {\r
-               command_print(cmd_ctx, "usage: dump_image <filename> <address> <size>");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       address = strtoul(args[1], NULL, 0);\r
-       size = strtoul(args[2], NULL, 0);\r
-\r
-       if ((address & 3) || (size & 3))\r
-       {\r
-               command_print(cmd_ctx, "only 32-bit aligned address and size are supported");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "dump_image error: %s", fileio.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       duration_start_measure(&duration);\r
-       \r
-       while (size > 0)\r
-       {\r
-               u32 size_written;\r
-               u32 this_run_size = (size > 560) ? 560 : size;\r
-               \r
-               retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);\r
-               if (retval != ERROR_OK)\r
-               {\r
-                       command_print(cmd_ctx, "Reading memory failed %d", retval);\r
-                       break;\r
-               }\r
-               \r
-               fileio_write(&fileio, this_run_size, buffer, &size_written);\r
-               \r
-               size -= this_run_size;\r
-               address += this_run_size;\r
-       }\r
-\r
-       fileio_close(&fileio);\r
-\r
-       duration_stop_measure(&duration, &duration_text);\r
-       command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);\r
-       free(duration_text);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_verify_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
-       int i;\r
-       int retval;\r
-       u32 checksum = 0;\r
-       u32 mem_checksum = 0;\r
-\r
-       image_t image;  \r
-       \r
-       duration_t duration;\r
-       char *duration_text;\r
-       \r
-       target_t *target = get_current_target(cmd_ctx);\r
-       \r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: verify_image <file> [offset] [type]");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("no target selected");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       duration_start_measure(&duration);\r
-       \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
-               image.base_address = 0x0;\r
-       }\r
-\r
-       image.start_address_set = 0;\r
-\r
-       if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "verify_image error: %s", image.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       image_size = 0x0;\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
-               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)\r
-               {\r
-                       ERROR("image_read_section failed with error code: %i", retval);\r
-                       command_print(cmd_ctx, "image reading failed, verify aborted");\r
-                       free(buffer);\r
-                       image_close(&image);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               /* calculate checksum of image */\r
-               image_calculate_checksum( buffer, buf_cnt, &checksum );\r
-               \r
-               retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);\r
-               \r
-               if( retval != ERROR_OK )\r
-               {\r
-                       command_print(cmd_ctx, "could not calculate checksum, verify aborted");\r
-                       free(buffer);\r
-                       image_close(&image);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               if( checksum != mem_checksum )\r
-               {\r
-                       /* failed crc checksum, fall back to a binary compare */\r
-                       u8 *data;\r
-                       \r
-                       command_print(cmd_ctx, "checksum mismatch - attempting binary compare");\r
-                       \r
-                       data = (u8*)malloc(buf_cnt);\r
-                       \r
-                       /* Can we use 32bit word accesses? */\r
-                       int size = 1;\r
-                       int count = buf_cnt;\r
-                       if ((count % 4) == 0)\r
-                       {\r
-                               size *= 4;\r
-                               count /= 4;\r
-                       }\r
-                       retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);\r
-       \r
-                       if (retval == ERROR_OK)\r
-                       {\r
-                               int t;\r
-                               for (t = 0; t < buf_cnt; t++)\r
-                               {\r
-                                       if (data[t] != buffer[t])\r
-                                       {\r
-                                               command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);\r
-                                               free(data);\r
-                                               free(buffer);\r
-                                               image_close(&image);\r
-                                               return ERROR_OK;\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       free(data);\r
-               }\r
-               \r
-               free(buffer);\r
-               image_size += buf_cnt;\r
-       }\r
-       \r
-       duration_stop_measure(&duration, &duration_text);\r
-       command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);\r
-       free(duration_text);\r
-       \r
-       image_close(&image);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc == 0)\r
-       {\r
-               breakpoint_t *breakpoint = target->breakpoints;\r
-\r
-               while (breakpoint)\r
-               {\r
-                       if (breakpoint->type == BKPT_SOFT)\r
-                       {\r
-                               char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16);\r
-                               command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf);\r
-                               free(buf);\r
-                       }\r
-                       else\r
-                       {\r
-                               command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);\r
-                       }\r
-                       breakpoint = breakpoint->next;\r
-               }\r
-       }\r
-       else if (argc >= 2)\r
-       {\r
-               int hw = BKPT_SOFT;\r
-               u32 length = 0;\r
-\r
-               length = strtoul(args[1], NULL, 0);\r
-               \r
-               if (argc >= 3)\r
-                       if (strcmp(args[2], "hw") == 0)\r
-                               hw = BKPT_HARD;\r
-\r
-               if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)\r
-               {\r
-                       switch (retval)\r
-                       {\r
-                               case ERROR_TARGET_NOT_HALTED:\r
-                                       command_print(cmd_ctx, "target must be halted to set breakpoints");\r
-                                       break;\r
-                               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:\r
-                                       command_print(cmd_ctx, "no more breakpoints available");\r
-                                       break;\r
-                               default:\r
-                                       command_print(cmd_ctx, "unknown error, breakpoint not set");\r
-                                       break;\r
-                       }\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "breakpoint added at address 0x%8.8x", strtoul(args[0], NULL, 0));\r
-               }\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc > 0)\r
-               breakpoint_remove(target, strtoul(args[0], NULL, 0));\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       int retval;\r
-\r
-       if (argc == 0)\r
-       {\r
-               watchpoint_t *watchpoint = target->watchpoints;\r
-\r
-               while (watchpoint)\r
-               {\r
-                       command_print(cmd_ctx, "address: 0x%8.8x, mask: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);\r
-                       watchpoint = watchpoint->next;\r
-               }\r
-       } \r
-       else if (argc >= 2)\r
-       {\r
-               enum watchpoint_rw type = WPT_ACCESS;\r
-               u32 data_value = 0x0;\r
-               u32 data_mask = 0xffffffff;\r
-               \r
-               if (argc >= 3)\r
-               {\r
-                       switch(args[2][0])\r
-                       {\r
-                               case 'r':\r
-                                       type = WPT_READ;\r
-                                       break;\r
-                               case 'w':\r
-                                       type = WPT_WRITE;\r
-                                       break;\r
-                               case 'a':\r
-                                       type = WPT_ACCESS;\r
-                                       break;\r
-                               default:\r
-                                       command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");\r
-                                       return ERROR_OK;\r
-                       }\r
-               }\r
-               if (argc >= 4)\r
-               {\r
-                       data_value = strtoul(args[3], NULL, 0);\r
-               }\r
-               if (argc >= 5)\r
-               {\r
-                       data_mask = strtoul(args[4], NULL, 0);\r
-               }\r
-               \r
-               if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),\r
-                               strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)\r
-               {\r
-                       switch (retval)\r
-                       {\r
-                               case ERROR_TARGET_NOT_HALTED:\r
-                                       command_print(cmd_ctx, "target must be halted to set watchpoints");\r
-                                       break;\r
-                               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:\r
-                                       command_print(cmd_ctx, "no more watchpoints available");\r
-                                       break;\r
-                               default:\r
-                                       command_print(cmd_ctx, "unknown error, watchpoint not set");\r
-                                       break;\r
-                       }       \r
-               }\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");\r
-       }\r
-               \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-\r
-       if (argc > 0)\r
-               watchpoint_remove(target, strtoul(args[0], NULL, 0));\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       int retval;\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       u32 va;\r
-       u32 pa;\r
-\r
-       if (argc != 1)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-       va = strtoul(args[0], NULL, 0);\r
-\r
-       retval = target->type->virt2phys(target, va, &pa);\r
-       if (retval == ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "Physical address 0x%08x", pa);\r
-       }\r
-       else\r
-       {\r
-               /* lower levels will have logged a detailed error which is \r
-                * forwarded to telnet/GDB session.  \r
-                */\r
-       }\r
-       return retval;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 <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>
+
+int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);
+
+
+int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
+
+/* targets
+ */
+extern target_type_t arm7tdmi_target;
+extern target_type_t arm720t_target;
+extern target_type_t arm9tdmi_target;
+extern target_type_t arm920t_target;
+extern target_type_t arm966e_target;
+extern target_type_t arm926ejs_target;
+extern target_type_t feroceon_target;
+extern target_type_t xscale_target;
+extern target_type_t cortexm3_target;
+
+target_type_t *target_types[] =
+{
+       &arm7tdmi_target,
+       &arm9tdmi_target,
+       &arm920t_target,
+       &arm720t_target,
+       &arm966e_target,
+       &arm926ejs_target,
+       &feroceon_target,
+       &xscale_target,
+       &cortexm3_target,
+       NULL,
+};
+
+target_t *targets = NULL;
+target_event_callback_t *target_event_callbacks = NULL;
+target_timer_callback_t *target_timer_callbacks = NULL;
+
+char *target_state_strings[] =
+{
+       "unknown",
+       "running",
+       "halted",
+       "reset",
+       "debug_running",
+};
+
+char *target_debug_reason_strings[] =
+{
+       "debug request", "breakpoint", "watchpoint",
+       "watchpoint and breakpoint", "single step",
+       "target not halted"
+};
+
+char *target_endianess_strings[] =
+{
+       "big endian",
+       "little endian",
+};
+
+enum daemon_startup_mode startup_mode = DAEMON_ATTACH;
+
+static int target_continous_poll = 1;
+
+/* read a u32 from a buffer in target memory endianness */
+u32 target_buffer_get_u32(target_t *target, u8 *buffer)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               return le_to_h_u32(buffer);
+       else
+               return be_to_h_u32(buffer);
+}
+
+/* read a u16 from a buffer in target memory endianness */
+u16 target_buffer_get_u16(target_t *target, u8 *buffer)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               return le_to_h_u16(buffer);
+       else
+               return be_to_h_u16(buffer);
+}
+
+/* write a u32 to a buffer in target memory endianness */
+void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               h_u32_to_le(buffer, value);
+       else
+               h_u32_to_be(buffer, value);
+}
+
+/* write a u16 to a buffer in target memory endianness */
+void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               h_u16_to_le(buffer, value);
+       else
+               h_u16_to_be(buffer, value);
+}
+
+/* returns a pointer to the n-th configured target */
+target_t* get_target_by_num(int num)
+{
+       target_t *target = targets;
+       int i = 0;
+
+       while (target)
+       {
+               if (num == i)
+                       return target;
+               target = target->next;
+               i++;
+       }
+
+       return NULL;
+}
+
+int get_num_by_target(target_t *query_target)
+{
+       target_t *target = targets;
+       int i = 0;      
+       
+       while (target)
+       {
+               if (target == query_target)
+                       return i;
+               target = target->next;
+               i++;
+       }
+       
+       return -1;
+}
+
+target_t* get_current_target(command_context_t *cmd_ctx)
+{
+       target_t *target = get_target_by_num(cmd_ctx->current_target);
+       
+       if (target == NULL)
+       {
+               ERROR("BUG: current_target out of bounds");
+               exit(-1);
+       }
+       
+       return target;
+}
+
+/* Process target initialization, when target entered debug out of reset
+ * the handler is unregistered at the end of this function, so it's only called once
+ */
+int target_init_handler(struct target_s *target, enum target_event event, void *priv)
+{
+       FILE *script;
+       struct command_context_s *cmd_ctx = priv;
+       
+       if ((event == TARGET_EVENT_HALTED) && (target->reset_script))
+       {
+               target_unregister_event_callback(target_init_handler, priv);
+
+               script = open_file_from_path(cmd_ctx, target->reset_script, "r");
+               if (!script)
+               {
+                       ERROR("couldn't open script file %s", target->reset_script);
+                               return ERROR_OK;
+               }
+
+               INFO("executing reset script '%s'", target->reset_script);
+               command_run_file(cmd_ctx, script, COMMAND_EXEC);
+               fclose(script);
+
+               jtag_execute_queue();
+       }
+       
+       return ERROR_OK;
+}
+
+int target_run_and_halt_handler(void *priv)
+{
+       target_t *target = priv;
+       
+       target->type->halt(target);
+       
+       return ERROR_OK;
+}
+
+int target_process_reset(struct command_context_s *cmd_ctx)
+{
+       int retval = ERROR_OK;
+       target_t *target;
+       struct timeval timeout, now;
+       
+       /* prepare reset_halt where necessary */
+       target = targets;
+       while (target)
+       {
+               if (jtag_reset_config & RESET_SRST_PULLS_TRST)
+               {
+                       switch (target->reset_mode)
+                       {
+                               case RESET_HALT:
+                                       command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_HALT");
+                                       target->reset_mode = RESET_RUN_AND_HALT;
+                                       break;
+                               case RESET_INIT:
+                                       command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_INIT");
+                                       target->reset_mode = RESET_RUN_AND_INIT;
+                                       break;
+                               default:
+                                       break;
+                       } 
+               }
+               switch (target->reset_mode)
+               {
+                       case RESET_HALT:
+                       case RESET_INIT:
+                               target->type->prepare_reset_halt(target);
+                               break;
+                       default:
+                               break;
+               }
+               target = target->next;
+       }
+       
+       target = targets;
+       while (target)
+       {
+               target->type->assert_reset(target);
+               target = target->next;
+       }
+       jtag_execute_queue();
+       
+       /* request target halt if necessary, and schedule further action */
+       target = targets;
+       while (target)
+       {
+               switch (target->reset_mode)
+               {
+                       case RESET_RUN:
+                               /* nothing to do if target just wants to be run */
+                               break;
+                       case RESET_RUN_AND_HALT:
+                               /* schedule halt */
+                               target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
+                               break;
+                       case RESET_RUN_AND_INIT:
+                               /* schedule halt */
+                               target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
+                               target_register_event_callback(target_init_handler, cmd_ctx);
+                               break;
+                       case RESET_HALT:
+                               target->type->halt(target);
+                               break;
+                       case RESET_INIT:
+                               target->type->halt(target);
+                               target_register_event_callback(target_init_handler, cmd_ctx);
+                               break;
+                       default:
+                               ERROR("BUG: unknown target->reset_mode");
+               }
+               target = target->next;
+       }
+       
+       target = targets;
+       while (target)
+       {
+               target->type->deassert_reset(target);
+               target = target->next;
+       }
+       jtag_execute_queue();
+
+       /* Wait for reset to complete, maximum 5 seconds. */    
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, 5, 0);
+       for(;;)
+       {
+               gettimeofday(&now, NULL);
+               
+               target_call_timer_callbacks();
+               
+               target = targets;
+               while (target)
+               {
+                       target->type->poll(target);
+                       if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT))
+                       {
+                               if (target->state != TARGET_HALTED)
+                               {
+                                       if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
+                                       {
+                                               command_print(cmd_ctx, "Timed out waiting for reset");
+                                               goto done;
+                                       }
+                                       usleep(100*1000); /* Do not eat all cpu */
+                                       goto again;
+                               }
+                       }
+                       target = target->next;
+               }
+               /* All targets we're waiting for are halted */
+               break;
+               
+               again:;
+       }
+       done:
+       
+       
+       /* We want any events to be processed before the prompt */
+       target_call_timer_callbacks();
+       
+       return retval;
+}
+
+static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+       *physical = virtual;
+       return ERROR_OK;
+}
+
+static int default_mmu(struct target_s *target, int *enabled)
+{
+       *enabled = 0;
+       return ERROR_OK;
+}
+
+int target_init(struct command_context_s *cmd_ctx)
+{
+       target_t *target = targets;
+       
+       while (target)
+       {
+               if (target->type->init_target(cmd_ctx, target) != ERROR_OK)
+               {
+                       ERROR("target '%s' init failed", target->type->name);
+                       exit(-1);
+               }
+               
+               /* Set up default functions if none are provided by target */
+               if (target->type->virt2phys == NULL)
+               {
+                       target->type->virt2phys = default_virt2phys;
+               }
+               if (target->type->mmu == NULL)
+               {
+                       target->type->mmu = default_mmu;
+               }
+               target = target->next;
+       }
+       
+       if (targets)
+       {
+               target_register_user_commands(cmd_ctx);
+               target_register_timer_callback(handle_target, 100, 1, NULL);
+       }
+               
+       return ERROR_OK;
+}
+
+int target_init_reset(struct command_context_s *cmd_ctx)
+{
+       if (startup_mode == DAEMON_RESET)
+               target_process_reset(cmd_ctx);
+       
+       return ERROR_OK;
+}
+
+int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
+{
+       target_event_callback_t **callbacks_p = &target_event_callbacks;
+       
+       if (callback == NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       
+       if (*callbacks_p)
+       {
+               while ((*callbacks_p)->next)
+                       callbacks_p = &((*callbacks_p)->next);
+               callbacks_p = &((*callbacks_p)->next);
+       }
+       
+       (*callbacks_p) = malloc(sizeof(target_event_callback_t));
+       (*callbacks_p)->callback = callback;
+       (*callbacks_p)->priv = priv;
+       (*callbacks_p)->next = NULL;
+       
+       return ERROR_OK;
+}
+
+int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
+{
+       target_timer_callback_t **callbacks_p = &target_timer_callbacks;
+       struct timeval now;
+       
+       if (callback == NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       
+       if (*callbacks_p)
+       {
+               while ((*callbacks_p)->next)
+                       callbacks_p = &((*callbacks_p)->next);
+               callbacks_p = &((*callbacks_p)->next);
+       }
+       
+       (*callbacks_p) = malloc(sizeof(target_timer_callback_t));
+       (*callbacks_p)->callback = callback;
+       (*callbacks_p)->periodic = periodic;
+       (*callbacks_p)->time_ms = time_ms;
+       
+       gettimeofday(&now, NULL);
+       (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
+       time_ms -= (time_ms % 1000);
+       (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
+       if ((*callbacks_p)->when.tv_usec > 1000000)
+       {
+               (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
+               (*callbacks_p)->when.tv_sec += 1;
+       }
+       
+       (*callbacks_p)->priv = priv;
+       (*callbacks_p)->next = NULL;
+       
+       return ERROR_OK;
+}
+
+int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
+{
+       target_event_callback_t **p = &target_event_callbacks;
+       target_event_callback_t *c = target_event_callbacks;
+       
+       if (callback == NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+               
+       while (c)
+       {
+               target_event_callback_t *next = c->next;
+               if ((c->callback == callback) && (c->priv == priv))
+               {
+                       *p = next;
+                       free(c);
+                       return ERROR_OK;
+               }
+               else
+                       p = &(c->next);
+               c = next;
+       }
+       
+       return ERROR_OK;
+}
+
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+{
+       target_timer_callback_t **p = &target_timer_callbacks;
+       target_timer_callback_t *c = target_timer_callbacks;
+       
+       if (callback == NULL)
+       {
+               return ERROR_INVALID_ARGUMENTS;
+       }
+               
+       while (c)
+       {
+               target_timer_callback_t *next = c->next;
+               if ((c->callback == callback) && (c->priv == priv))
+               {
+                       *p = next;
+                       free(c);
+                       return ERROR_OK;
+               }
+               else
+                       p = &(c->next);
+               c = next;
+       }
+       
+       return ERROR_OK;
+}
+
+int target_call_event_callbacks(target_t *target, enum target_event event)
+{
+       target_event_callback_t *callback = target_event_callbacks;
+       target_event_callback_t *next_callback;
+       
+       DEBUG("target event %i", event);
+       
+       while (callback)
+       {
+               next_callback = callback->next;
+               callback->callback(target, event, callback->priv);
+               callback = next_callback;
+       }
+       
+       return ERROR_OK;
+}
+
+int target_call_timer_callbacks()
+{
+       target_timer_callback_t *callback = target_timer_callbacks;
+       target_timer_callback_t *next_callback;
+       struct timeval now;
+
+       gettimeofday(&now, NULL);
+       
+       while (callback)
+       {
+               next_callback = callback->next;
+               
+               if (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec))
+                       || (now.tv_sec > callback->when.tv_sec))
+               {
+                       callback->callback(callback->priv);
+                       if (callback->periodic)
+                       {
+                               int time_ms = callback->time_ms;
+                               callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
+                               time_ms -= (time_ms % 1000);
+                               callback->when.tv_sec = now.tv_sec + time_ms / 1000;
+                               if (callback->when.tv_usec > 1000000)
+                               {
+                                       callback->when.tv_usec = callback->when.tv_usec - 1000000;
+                                       callback->when.tv_sec += 1;
+                               }
+                       }
+                       else
+                               target_unregister_timer_callback(callback->callback, callback->priv);
+               }
+                       
+               callback = next_callback;
+       }
+       
+       return ERROR_OK;
+}
+
+int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)
+{
+       working_area_t *c = target->working_areas;
+       working_area_t *new_wa = NULL;
+       
+       /* Reevaluate working area address based on MMU state*/
+       if (target->working_areas == NULL)
+       {
+               int retval;
+               int enabled;
+               retval = target->type->mmu(target, &enabled);
+               if (retval != ERROR_OK)
+               {
+                       return retval;
+               }
+               if (enabled)
+               {
+                       target->working_area = target->working_area_virt;
+               }
+               else
+               {
+                       target->working_area = target->working_area_phys;
+               }
+       }
+       
+       /* only allocate multiples of 4 byte */
+       if (size % 4)
+       {
+               ERROR("BUG: code tried to allocate unaligned number of bytes, padding");
+               size = CEIL(size, 4);
+       }
+       
+       /* see if there's already a matching working area */
+       while (c)
+       {
+               if ((c->free) && (c->size == size))
+               {
+                       new_wa = c;
+                       break;
+               }
+               c = c->next;
+       }
+       
+       /* if not, allocate a new one */
+       if (!new_wa)
+       {
+               working_area_t **p = &target->working_areas;
+               u32 first_free = target->working_area;
+               u32 free_size = target->working_area_size;
+               
+               DEBUG("allocating new working area");
+               
+               c = target->working_areas;
+               while (c)
+               {
+                       first_free += c->size;
+                       free_size -= c->size;
+                       p = &c->next;
+                       c = c->next;
+               }
+               
+               if (free_size < size)
+               {
+                       WARNING("not enough working area available(requested %d, free %d)", size, free_size);
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+               }
+               
+               new_wa = malloc(sizeof(working_area_t));
+               new_wa->next = NULL;
+               new_wa->size = size;
+               new_wa->address = first_free;
+               
+               if (target->backup_working_area)
+               {
+                       new_wa->backup = malloc(new_wa->size);
+                       target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup);
+               }
+               else
+               {
+                       new_wa->backup = NULL;
+               }
+               
+               /* put new entry in list */
+               *p = new_wa;
+       }
+       
+       /* mark as used, and return the new (reused) area */
+       new_wa->free = 0;
+       *area = new_wa;
+       
+       /* user pointer */
+       new_wa->user = area;
+       
+       return ERROR_OK;
+}
+
+int target_free_working_area(struct target_s *target, working_area_t *area)
+{
+       if (area->free)
+               return ERROR_OK;
+       
+       if (target->backup_working_area)
+               target->type->write_memory(target, area->address, 4, area->size / 4, area->backup);
+       
+       area->free = 1;
+       
+       /* mark user pointer invalid */
+       *area->user = NULL;
+       area->user = NULL;
+       
+       return ERROR_OK;
+}
+
+int target_free_all_working_areas(struct target_s *target)
+{
+       working_area_t *c = target->working_areas;
+
+       while (c)
+       {
+               working_area_t *next = c->next;
+               target_free_working_area(target, c);
+               
+               if (c->backup)
+                       free(c->backup);
+               
+               free(c);
+               
+               c = next;
+       }
+       
+       target->working_areas = NULL;
+       
+       return ERROR_OK;
+}
+
+int target_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL);
+       register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, NULL);
+       register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");
+       register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");
+
+       return ERROR_OK;
+}
+
+int target_arch_state(struct target_s *target)
+{
+       int retval;
+       if (target==NULL)
+       {
+               USER("No target has been configured");
+               return ERROR_OK;
+       }
+       
+       USER("target state: %s", target_state_strings[target->state]);
+       
+       if (target->state!=TARGET_HALTED)
+               return ERROR_OK;
+       
+       retval=target->type->arch_state(target);
+       return retval;
+}
+
+/* Single aligned words are guaranteed to use 16 or 32 bit access 
+ * mode respectively, otherwise data is handled as quickly as 
+ * possible
+ */
+int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
+{
+       int retval;
+       
+       DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);
+       
+       if (((address % 2) == 0) && (size == 2))
+       {
+               return target->type->write_memory(target, address, 2, 1, buffer);
+       }
+       
+       /* handle unaligned head bytes */
+       if (address % 4)
+       {
+               int unaligned = 4 - (address % 4);
+               
+               if (unaligned > size)
+                       unaligned = size;
+
+               if ((retval = target->type->write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
+                       return retval;
+               
+               buffer += unaligned;
+               address += unaligned;
+               size -= unaligned;
+       }
+               
+       /* handle aligned words */
+       if (size >= 4)
+       {
+               int aligned = size - (size % 4);
+       
+               /* use bulk writes above a certain limit. This may have to be changed */
+               if (aligned > 128)
+               {
+                       if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)
+                               return retval;
+               }
+               else
+               {
+                       if ((retval = target->type->write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+                               return retval;
+               }
+               
+               buffer += aligned;
+               address += aligned;
+               size -= aligned;
+       }
+       
+       /* handle tail writes of less than 4 bytes */
+       if (size > 0)
+       {
+               if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)
+                       return retval;
+       }
+       
+       return ERROR_OK;
+}
+
+
+/* Single aligned words are guaranteed to use 16 or 32 bit access 
+ * mode respectively, otherwise data is handled as quickly as 
+ * possible
+ */
+int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
+{
+       int retval;
+       
+       DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);
+       
+       if (((address % 2) == 0) && (size == 2))
+       {
+               return target->type->read_memory(target, address, 2, 1, buffer);
+       }
+       
+       /* handle unaligned head bytes */
+       if (address % 4)
+       {
+               int unaligned = 4 - (address % 4);
+               
+               if (unaligned > size)
+                       unaligned = size;
+
+               if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
+                       return retval;
+               
+               buffer += unaligned;
+               address += unaligned;
+               size -= unaligned;
+       }
+               
+       /* handle aligned words */
+       if (size >= 4)
+       {
+               int aligned = size - (size % 4);
+       
+               if ((retval = target->type->read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+                       return retval;
+               
+               buffer += aligned;
+               address += aligned;
+               size -= aligned;
+       }
+       
+       /* handle tail writes of less than 4 bytes */
+       if (size > 0)
+       {
+               if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)
+                       return retval;
+       }
+       
+       return ERROR_OK;
+}
+
+int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
+{
+       u8 *buffer;
+       int retval;
+       int i;
+       u32 checksum = 0;
+       
+       if ((retval = target->type->checksum_memory(target, address,
+               size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+       {
+               buffer = malloc(size);
+               if (buffer == NULL)
+               {
+                       ERROR("error allocating buffer for section (%d bytes)", size);
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+               retval = target_read_buffer(target, address, size, buffer);
+               if (retval != ERROR_OK)
+               {
+                       free(buffer);
+                       return retval;
+               }
+
+               /* convert to target endianess */
+               for (i = 0; i < (size/sizeof(u32)); i++)
+               {
+                       u32 target_data;
+                       target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);
+                       target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);
+               }
+
+               retval = image_calculate_checksum( buffer, size, &checksum );
+               free(buffer);
+       }
+       
+       *crc = checksum;
+       
+       return retval;
+}
+
+int target_read_u32(struct target_s *target, u32 address, u32 *value)
+{
+       u8 value_buf[4];
+
+       int retval = target->type->read_memory(target, address, 4, 1, value_buf);
+       
+       if (retval == ERROR_OK)
+       {
+               *value = target_buffer_get_u32(target, value_buf);
+               DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
+}
+
+int target_read_u16(struct target_s *target, u32 address, u16 *value)
+{
+       u8 value_buf[2];
+       
+       int retval = target->type->read_memory(target, address, 2, 1, value_buf);
+       
+       if (retval == ERROR_OK)
+       {
+               *value = target_buffer_get_u16(target, value_buf);
+               DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
+}
+
+int target_read_u8(struct target_s *target, u32 address, u8 *value)
+{
+       int retval = target->type->read_memory(target, address, 1, 1, value);
+
+       if (retval == ERROR_OK)
+       {
+               DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
+}
+
+int target_write_u32(struct target_s *target, u32 address, u32 value)
+{
+       int retval;
+       u8 value_buf[4];
+
+       DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
+
+       target_buffer_set_u32(target, value_buf, value);        
+       if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
+}
+
+int target_write_u16(struct target_s *target, u32 address, u16 value)
+{
+       int retval;
+       u8 value_buf[2];
+       
+       DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
+
+       target_buffer_set_u16(target, value_buf, value);        
+       if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
+}
+
+int target_write_u8(struct target_s *target, u32 address, u8 value)
+{
+       int retval;
+       
+       DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
+
+       if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
+}
+
+int target_register_user_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx,  NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL);
+       register_command(cmd_ctx,  NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");
+       register_command(cmd_ctx,  NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
+       register_command(cmd_ctx,  NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
+       register_command(cmd_ctx,  NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
+       register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
+       register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init|run_and_halt|run_and_init]");
+       register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
+
+       register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
+       register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
+       register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
+       
+       register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value>");
+       register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value>");
+       register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value>");
+       
+       register_command(cmd_ctx,  NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");      
+       register_command(cmd_ctx,  NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");
+       register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");    
+       register_command(cmd_ctx,  NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
+       
+       register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");
+       register_command(cmd_ctx,  NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
+       register_command(cmd_ctx,  NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");
+       register_command(cmd_ctx,  NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
+       register_command(cmd_ctx,  NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
+       
+       target_request_register_commands(cmd_ctx);
+       trace_register_commands(cmd_ctx);
+       
+       return ERROR_OK;
+}
+
+int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = targets;
+       int count = 0;
+       
+       if (argc == 1)
+       {
+               int num = strtoul(args[0], NULL, 0);
+               
+               while (target)
+               {
+                       count++;
+                       target = target->next;
+               }
+               
+               if (num < count)
+                       cmd_ctx->current_target = num;
+               else
+                       command_print(cmd_ctx, "%i is out of bounds, only %i targets are configured", num, count);
+                       
+               return ERROR_OK;
+       }
+               
+       while (target)
+       {
+               command_print(cmd_ctx, "%i: %s (%s), state: %s", count++, target->type->name, target_endianess_strings[target->endianness], target_state_strings[target->state]);
+               target = target->next;
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int i;
+       int found = 0;
+       
+       if (argc < 3)
+       {
+               ERROR("target command requires at least three arguments: <type> <endianess> <reset_mode>");
+               exit(-1);
+       }
+       
+       /* search for the specified target */
+       if (args[0] && (args[0][0] != 0))
+       {
+               for (i = 0; target_types[i]; i++)
+               {
+                       if (strcmp(args[0], target_types[i]->name) == 0)
+                       {
+                               target_t **last_target_p = &targets;
+                               
+                               /* register target specific commands */
+                               if (target_types[i]->register_commands(cmd_ctx) != ERROR_OK)
+                               {
+                                       ERROR("couldn't register '%s' commands", args[0]);
+                                       exit(-1);
+                               }
+
+                               if (*last_target_p)
+                               {
+                                       while ((*last_target_p)->next)
+                                               last_target_p = &((*last_target_p)->next);
+                                       last_target_p = &((*last_target_p)->next);
+                               }
+
+                               *last_target_p = malloc(sizeof(target_t));
+                               
+                               (*last_target_p)->type = target_types[i];
+                               
+                               if (strcmp(args[1], "big") == 0)
+                                       (*last_target_p)->endianness = TARGET_BIG_ENDIAN;
+                               else if (strcmp(args[1], "little") == 0)
+                                       (*last_target_p)->endianness = TARGET_LITTLE_ENDIAN;
+                               else
+                               {
+                                       ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]);
+                                       exit(-1);
+                               }
+                               
+                               /* what to do on a target reset */
+                               if (strcmp(args[2], "reset_halt") == 0)
+                                       (*last_target_p)->reset_mode = RESET_HALT;
+                               else if (strcmp(args[2], "reset_run") == 0)
+                                       (*last_target_p)->reset_mode = RESET_RUN;
+                               else if (strcmp(args[2], "reset_init") == 0)
+                                       (*last_target_p)->reset_mode = RESET_INIT;
+                               else if (strcmp(args[2], "run_and_halt") == 0)
+                                       (*last_target_p)->reset_mode = RESET_RUN_AND_HALT;
+                               else if (strcmp(args[2], "run_and_init") == 0)
+                                       (*last_target_p)->reset_mode = RESET_RUN_AND_INIT;
+                               else
+                               {
+                                       ERROR("unknown target startup mode %s", args[2]);
+                                       exit(-1);
+                               }
+                               (*last_target_p)->run_and_halt_time = 1000; /* default 1s */
+                               
+                               (*last_target_p)->reset_script = NULL;
+                               (*last_target_p)->post_halt_script = NULL;
+                               (*last_target_p)->pre_resume_script = NULL;
+                               (*last_target_p)->gdb_program_script = NULL;
+                               
+                               (*last_target_p)->working_area = 0x0;
+                               (*last_target_p)->working_area_size = 0x0;
+                               (*last_target_p)->working_areas = NULL;
+                               (*last_target_p)->backup_working_area = 0;
+                               
+                               (*last_target_p)->state = TARGET_UNKNOWN;
+                               (*last_target_p)->reg_cache = NULL;
+                               (*last_target_p)->breakpoints = NULL;
+                               (*last_target_p)->watchpoints = NULL;
+                               (*last_target_p)->next = NULL;
+                               (*last_target_p)->arch_info = NULL;
+                               
+                               /* initialize trace information */
+                               (*last_target_p)->trace_info = malloc(sizeof(trace_t));
+                               (*last_target_p)->trace_info->num_trace_points = 0;
+                               (*last_target_p)->trace_info->trace_points_size = 0;
+                               (*last_target_p)->trace_info->trace_points = NULL;
+                               (*last_target_p)->trace_info->trace_history_size = 0;
+                               (*last_target_p)->trace_info->trace_history = NULL;
+                               (*last_target_p)->trace_info->trace_history_pos = 0;
+                               (*last_target_p)->trace_info->trace_history_overflowed = 0;
+                               
+                               (*last_target_p)->dbgmsg = NULL;
+                               (*last_target_p)->dbg_msg_enabled = 0;
+                                                               
+                               (*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);
+                               
+                               found = 1;
+                               break;
+                       }
+               }
+       }
+       
+       /* no matching target found */
+       if (!found)
+       {
+               ERROR("target '%s' not found", args[0]);
+               exit(-1);
+       }
+
+       return ERROR_OK;
+}
+
+/* usage: target_script <target#> <event> <script_file> */
+int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = NULL;
+       
+       if (argc < 3)
+       {
+               ERROR("incomplete target_script command");
+               exit(-1);
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       
+       if (strcmp(args[1], "reset") == 0)
+       {
+               if (target->reset_script)
+                       free(target->reset_script);
+               target->reset_script = strdup(args[2]);
+       }
+       else if (strcmp(args[1], "post_halt") == 0)
+       {
+               if (target->post_halt_script)
+                       free(target->post_halt_script);
+               target->post_halt_script = strdup(args[2]);
+       }
+       else if (strcmp(args[1], "pre_resume") == 0)
+       {
+               if (target->pre_resume_script)
+                       free(target->pre_resume_script);
+               target->pre_resume_script = strdup(args[2]);
+       }
+       else if (strcmp(args[1], "gdb_program_config") == 0)
+       {
+               if (target->gdb_program_script)
+                       free(target->gdb_program_script);
+               target->gdb_program_script = strdup(args[2]);
+       }
+       else
+       {
+               ERROR("unknown event type: '%s", args[1]);
+               exit(-1);       
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = NULL;
+       
+       if (argc < 2)
+       {
+               ERROR("incomplete run_and_halt_time command");
+               exit(-1);
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       
+       target->run_and_halt_time = strtoul(args[1], NULL, 0);
+       
+       return ERROR_OK;
+}
+
+int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = NULL;
+       
+       if ((argc < 4) || (argc > 5))
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       
+       target = get_target_by_num(strtoul(args[0], NULL, 0));
+       
+       if (!target)
+       {
+               ERROR("target number '%s' not defined", args[0]);
+               exit(-1);
+       }
+       target_free_all_working_areas(target);
+       
+       target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
+       if (argc == 5)
+       {
+               target->working_area_virt = strtoul(args[4], NULL, 0);
+       }
+       target->working_area_size = strtoul(args[2], NULL, 0);
+       
+       if (strcmp(args[3], "backup") == 0)
+       {
+               target->backup_working_area = 1;
+       }
+       else if (strcmp(args[3], "nobackup") == 0)
+       {
+               target->backup_working_area = 0;
+       }
+       else
+       {
+               ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       
+       return ERROR_OK;
+}
+
+
+/* process target state changes */
+int handle_target(void *priv)
+{
+       int retval;
+       target_t *target = targets;
+       
+       while (target)
+       {
+               /* only poll if target isn't already halted */
+               if (target->state != TARGET_HALTED)
+               {
+                       if (target_continous_poll)
+                               if ((retval = target->type->poll(target)) != ERROR_OK)
+                               {
+                                       ERROR("couldn't poll target(%d). It's due for a reset.", retval);
+                               }
+               }
+       
+               target = target->next;
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       reg_t *reg = NULL;
+       int count = 0;
+       char *value;
+       
+       DEBUG("-");
+       
+       target = get_current_target(cmd_ctx);
+       
+       /* list all available registers for the current target */
+       if (argc == 0)
+       {
+               reg_cache_t *cache = target->reg_cache;
+               
+               count = 0;
+               while(cache)
+               {
+                       int i;
+                       for (i = 0; i < cache->num_regs; i++)
+                       {
+                               value = buf_to_str(cache->reg_list[i].value, cache->reg_list[i].size, 16);
+                               command_print(cmd_ctx, "(%i) %s (/%i): 0x%s (dirty: %i, valid: %i)", count++, cache->reg_list[i].name, cache->reg_list[i].size, value, cache->reg_list[i].dirty, cache->reg_list[i].valid);
+                               free(value);
+                       }
+                       cache = cache->next;
+               }
+               
+               return ERROR_OK;
+       }
+       
+       /* access a single register by its ordinal number */
+       if ((args[0][0] >= '0') && (args[0][0] <= '9'))
+       {
+               int num = strtoul(args[0], NULL, 0);
+               reg_cache_t *cache = target->reg_cache;
+               
+               count = 0;
+               while(cache)
+               {
+                       int i;
+                       for (i = 0; i < cache->num_regs; i++)
+                       {
+                               if (count++ == num)
+                               {
+                                       reg = &cache->reg_list[i];
+                                       break;
+                               }
+                       }
+                       if (reg)
+                               break;
+                       cache = cache->next;
+               }
+               
+               if (!reg)
+               {
+                       command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
+                       return ERROR_OK;
+               }
+       } else /* access a single register by its name */
+       {
+               reg = register_get_by_name(target->reg_cache, args[0], 1);
+               
+               if (!reg)
+               {
+                       command_print(cmd_ctx, "register %s not found in current target", args[0]);
+                       return ERROR_OK;
+               }
+       }
+
+       /* display a register */
+       if ((argc == 1) || ((argc == 2) && !((args[1][0] >= '0') && (args[1][0] <= '9'))))
+       {
+               if ((argc == 2) && (strcmp(args[1], "force") == 0))
+                       reg->valid = 0;
+               
+               if (reg->valid == 0)
+               {
+                       reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
+                       if (arch_type == NULL)
+                       {
+                               ERROR("BUG: encountered unregistered arch type");
+                               return ERROR_OK;
+                       }
+                       arch_type->get(reg);
+               }
+               value = buf_to_str(reg->value, reg->size, 16);
+               command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
+               free(value);
+               return ERROR_OK;
+       }
+       
+       /* set register value */
+       if (argc == 2)
+       {
+               u8 *buf = malloc(CEIL(reg->size, 8));
+               str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);
+
+               reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
+               if (arch_type == NULL)
+               {
+                       ERROR("BUG: encountered unregistered arch type");
+                       return ERROR_OK;
+               }
+               
+               arch_type->set(reg, buf);
+               
+               value = buf_to_str(reg->value, reg->size, 16);
+               command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
+               free(value);
+               
+               free(buf);
+               
+               return ERROR_OK;
+       }
+       
+       command_print(cmd_ctx, "usage: reg <#|name> [value]");
+       
+       return ERROR_OK;
+}
+
+static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms);
+
+int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc == 0)
+       {
+               target->type->poll(target);
+                       target_arch_state(target);
+       }
+       else
+       {
+               if (strcmp(args[0], "on") == 0)
+               {
+                       target_continous_poll = 1;
+               }
+               else if (strcmp(args[0], "off") == 0)
+               {
+                       target_continous_poll = 0;
+               }
+               else
+               {
+                       command_print(cmd_ctx, "arg is \"on\" or \"off\"");
+               }
+       }
+       
+       
+       return ERROR_OK;
+}
+
+int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int ms = 5000;
+       
+       if (argc > 0)
+       {
+               char *end;
+
+               ms = strtoul(args[0], &end, 0) * 1000;
+               if (*end)
+               {
+                       command_print(cmd_ctx, "usage: %s [seconds]", cmd);
+                       return ERROR_OK;
+               }
+       }
+
+       return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); 
+}
+
+static void target_process_events(struct command_context_s *cmd_ctx)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       target->type->poll(target);
+       target_call_timer_callbacks();
+}
+
+static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms)
+{
+       int retval;
+       struct timeval timeout, now;
+       
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, 0, ms * 1000);
+       
+       target_t *target = get_current_target(cmd_ctx);
+       for (;;)
+       {
+               if ((retval=target->type->poll(target))!=ERROR_OK)
+                       return retval;
+               target_call_timer_callbacks();
+               if (target->state == state)
+               {
+                       break;
+               }
+               command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]);
+               
+               gettimeofday(&now, NULL);
+               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
+               {
+                       command_print(cmd_ctx, "timed out while waiting for target %s", target_state_strings[state]);
+                       ERROR("timed out while waiting for target %s", target_state_strings[state]);
+                       break;
+               }
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+
+       DEBUG("-");
+       
+       command_print(cmd_ctx, "requesting target halt...");
+
+       if ((retval = target->type->halt(target)) != ERROR_OK)
+       {       
+               switch (retval)
+               {
+                       case ERROR_TARGET_ALREADY_HALTED:
+                               command_print(cmd_ctx, "target already halted");
+                               break;
+                       case ERROR_TARGET_TIMEOUT:
+                               command_print(cmd_ctx, "target timed out... shutting down");
+                               return retval;
+                       default:
+                               command_print(cmd_ctx, "unknown error... shutting down");
+                               return retval;
+               }
+       }
+       
+       return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
+}
+
+/* what to do on daemon startup */
+int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 1)
+       {
+               if (strcmp(args[0], "attach") == 0)
+               {
+                       startup_mode = DAEMON_ATTACH;
+                       return ERROR_OK;
+               }
+               else if (strcmp(args[0], "reset") == 0)
+               {
+                       startup_mode = DAEMON_RESET;
+                       return ERROR_OK;
+               }
+       }
+       
+       WARNING("invalid daemon_startup configuration directive: %s", args[0]);
+       return ERROR_OK;
+
+}
+               
+int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       int retval;
+       
+       command_print(cmd_ctx, "requesting target halt and executing a soft reset");
+       
+       if ((retval = target->type->soft_reset_halt(target)) != ERROR_OK)
+       {       
+               switch (retval)
+               {
+                       case ERROR_TARGET_TIMEOUT:
+                               command_print(cmd_ctx, "target timed out... shutting down");
+                               exit(-1);
+                       default:
+                               command_print(cmd_ctx, "unknown error... shutting down");
+                               exit(-1);
+               }
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       enum target_reset_mode reset_mode = target->reset_mode;
+       enum target_reset_mode save = target->reset_mode;
+       
+       DEBUG("-");
+       
+       if (argc >= 1)
+       {
+               if (strcmp("run", args[0]) == 0)
+                       reset_mode = RESET_RUN;
+               else if (strcmp("halt", args[0]) == 0)
+                       reset_mode = RESET_HALT;
+               else if (strcmp("init", args[0]) == 0)
+                       reset_mode = RESET_INIT;
+               else if (strcmp("run_and_halt", args[0]) == 0)
+               {
+                       reset_mode = RESET_RUN_AND_HALT;
+                       if (argc >= 2)
+                       {
+                               target->run_and_halt_time = strtoul(args[1], NULL, 0);
+                       }
+               }
+               else if (strcmp("run_and_init", args[0]) == 0)
+               {
+                       reset_mode = RESET_RUN_AND_INIT;
+                       if (argc >= 2)
+                       {
+                               target->run_and_halt_time = strtoul(args[1], NULL, 0);
+                       }
+               }
+               else
+               {
+                       command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]");
+                       return ERROR_OK;
+               }
+       }
+       
+       /* temporarily modify mode of current reset target */
+       target->reset_mode = reset_mode;
+
+       /* reset *all* targets */
+       target_process_reset(cmd_ctx);
+       
+       /* Restore default reset mode for this target */
+    target->reset_mode = save;
+       
+       return ERROR_OK;
+}
+
+int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       
+       if (argc == 0)
+               retval = target->type->resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */
+       else if (argc == 1)
+               retval = target->type->resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */
+       else
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       target_process_events(cmd_ctx);
+       
+       target_arch_state(target);
+       
+       return retval;
+}
+
+int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       
+       DEBUG("-");
+       
+       if (argc == 0)
+               target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
+
+       if (argc == 1)
+               target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
+       
+       return ERROR_OK;
+}
+
+int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       const int line_bytecnt = 32;
+       int count = 1;
+       int size = 4;
+       u32 address = 0;
+       int line_modulo;
+       int i;
+
+       char output[128];
+       int output_len;
+
+       int retval;
+
+       u8 *buffer;
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc < 1)
+               return ERROR_OK;
+
+       if (argc == 2)
+               count = strtoul(args[1], NULL, 0);
+
+       address = strtoul(args[0], NULL, 0);
+       
+
+       switch (cmd[2])
+       {
+               case 'w':
+                       size = 4; line_modulo = line_bytecnt / 4;
+                       break;
+               case 'h':
+                       size = 2; line_modulo = line_bytecnt / 2;
+                       break;
+               case 'b':
+                       size = 1; line_modulo = line_bytecnt / 1;
+                       break;
+               default:
+                       return ERROR_OK;
+       }
+
+       buffer = calloc(count, size);
+       retval  = target->type->read_memory(target, address, size, count, buffer);
+       if (retval != ERROR_OK)
+       {
+               switch (retval)
+               {
+                       case ERROR_TARGET_UNALIGNED_ACCESS:
+                               command_print(cmd_ctx, "error: address not aligned");
+                               break;
+                       case ERROR_TARGET_NOT_HALTED:
+                               command_print(cmd_ctx, "error: target must be halted for memory accesses");
+                               break;                  
+                       case ERROR_TARGET_DATA_ABORT:
+                               command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
+                               break;
+                       default:
+                               command_print(cmd_ctx, "error: unknown error");
+                               break;
+               }
+               return ERROR_OK;
+       }
+
+       output_len = 0;
+
+       for (i = 0; i < count; i++)
+       {
+               if (i%line_modulo == 0)
+                       output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));
+               
+               switch (size)
+               {
+                       case 4:
+                               output_len += snprintf(output + output_len, 128 - output_len, "%8.8x ", target_buffer_get_u32(target, &buffer[i*4]));
+                               break;
+                       case 2:
+                               output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));
+                               break;
+                       case 1:
+                               output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);
+                               break;
+               }
+
+               if ((i%line_modulo == line_modulo-1) || (i == count - 1))
+               {
+                       command_print(cmd_ctx, output);
+                       output_len = 0;
+               }
+       }
+
+       free(buffer);
+       
+       return ERROR_OK;
+}
+
+int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u32 address = 0;
+       u32 value = 0;
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       u8 value_buf[4];
+
+       if (argc < 2)
+               return ERROR_OK;
+
+       address = strtoul(args[0], NULL, 0);
+       value = strtoul(args[1], NULL, 0);
+
+       switch (cmd[2])
+       {
+               case 'w':
+                       target_buffer_set_u32(target, value_buf, value);
+                       retval = target->type->write_memory(target, address, 4, 1, value_buf);
+                       break;
+               case 'h':
+                       target_buffer_set_u16(target, value_buf, value);
+                       retval = target->type->write_memory(target, address, 2, 1, value_buf);
+                       break;
+               case 'b':
+                       value_buf[0] = value;
+                       retval = target->type->write_memory(target, address, 1, 1, value_buf);
+                       break;
+               default:
+                       return ERROR_OK;
+       }
+
+       switch (retval)
+       {
+               case ERROR_TARGET_UNALIGNED_ACCESS:
+                       command_print(cmd_ctx, "error: address not aligned");
+                       break;
+               case ERROR_TARGET_DATA_ABORT:
+                       command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
+                       break;
+               case ERROR_TARGET_NOT_HALTED:
+                       command_print(cmd_ctx, "error: target must be halted for memory accesses");
+                       break;
+               case ERROR_OK:
+                       break;
+               default:
+                       command_print(cmd_ctx, "error: unknown error");
+                       break;
+       }
+
+       return ERROR_OK;
+
+}
+
+int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u8 *buffer;
+       u32 buf_cnt;
+       u32 image_size;
+       int i;
+       int retval;
+
+       image_t image;  
+       
+       duration_t duration;
+       char *duration_text;
+       
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
+               return ERROR_OK;
+       }
+       
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       if (argc >= 2)
+       {
+               image.base_address_set = 1;
+               image.base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               image.base_address_set = 0;
+       }
+       
+       image.start_address_set = 0;
+
+       duration_start_measure(&duration);
+       
+       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "load_image error: %s", image.error_str);
+               return ERROR_OK;
+       }
+       
+       image_size = 0x0;
+       for (i = 0; i < image.num_sections; i++)
+       {
+               buffer = malloc(image.sections[i].size);
+               if (buffer == NULL)
+               {
+                       command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
+                       break;
+               }
+               
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+               {
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, download aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
+               image_size += buf_cnt;
+               command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
+               
+               free(buffer);
+       }
+
+       duration_stop_measure(&duration, &duration_text);
+       command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
+       free(duration_text);
+       
+       image_close(&image);
+
+       return ERROR_OK;
+
+}
+
+int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       fileio_t fileio;
+       
+       u32 address;
+       u32 size;
+       u8 buffer[560];
+       int retval;
+       
+       duration_t duration;
+       char *duration_text;
+       
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc != 3)
+       {
+               command_print(cmd_ctx, "usage: dump_image <filename> <address> <size>");
+               return ERROR_OK;
+       }
+
+       address = strtoul(args[1], NULL, 0);
+       size = strtoul(args[2], NULL, 0);
+
+       if ((address & 3) || (size & 3))
+       {
+               command_print(cmd_ctx, "only 32-bit aligned address and size are supported");
+               return ERROR_OK;
+       }
+       
+       if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "dump_image error: %s", fileio.error_str);
+               return ERROR_OK;
+       }
+       
+       duration_start_measure(&duration);
+       
+       while (size > 0)
+       {
+               u32 size_written;
+               u32 this_run_size = (size > 560) ? 560 : size;
+               
+               retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
+               if (retval != ERROR_OK)
+               {
+                       command_print(cmd_ctx, "Reading memory failed %d", retval);
+                       break;
+               }
+               
+               fileio_write(&fileio, this_run_size, buffer, &size_written);
+               
+               size -= this_run_size;
+               address += this_run_size;
+       }
+
+       fileio_close(&fileio);
+
+       duration_stop_measure(&duration, &duration_text);
+       command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
+       free(duration_text);
+       
+       return ERROR_OK;
+}
+
+int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u8 *buffer;
+       u32 buf_cnt;
+       u32 image_size;
+       int i;
+       int retval;
+       u32 checksum = 0;
+       u32 mem_checksum = 0;
+
+       image_t image;  
+       
+       duration_t duration;
+       char *duration_text;
+       
+       target_t *target = get_current_target(cmd_ctx);
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: verify_image <file> [offset] [type]");
+               return ERROR_OK;
+       }
+       
+       if (!target)
+       {
+               ERROR("no target selected");
+               return ERROR_OK;
+       }
+       
+       duration_start_measure(&duration);
+       
+       if (argc >= 2)
+       {
+               image.base_address_set = 1;
+               image.base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               image.base_address_set = 0;
+               image.base_address = 0x0;
+       }
+
+       image.start_address_set = 0;
+
+       if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "verify_image error: %s", image.error_str);
+               return ERROR_OK;
+       }
+       
+       image_size = 0x0;
+       for (i = 0; i < image.num_sections; i++)
+       {
+               buffer = malloc(image.sections[i].size);
+               if (buffer == NULL)
+               {
+                       command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
+                       break;
+               }
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+               {
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, verify aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               
+               /* calculate checksum of image */
+               image_calculate_checksum( buffer, buf_cnt, &checksum );
+               
+               retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
+               
+               if( retval != ERROR_OK )
+               {
+                       command_print(cmd_ctx, "could not calculate checksum, verify aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               
+               if( checksum != mem_checksum )
+               {
+                       /* failed crc checksum, fall back to a binary compare */
+                       u8 *data;
+                       
+                       command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
+                       
+                       data = (u8*)malloc(buf_cnt);
+                       
+                       /* Can we use 32bit word accesses? */
+                       int size = 1;
+                       int count = buf_cnt;
+                       if ((count % 4) == 0)
+                       {
+                               size *= 4;
+                               count /= 4;
+                       }
+                       retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
+       
+                       if (retval == ERROR_OK)
+                       {
+                               int t;
+                               for (t = 0; t < buf_cnt; t++)
+                               {
+                                       if (data[t] != buffer[t])
+                                       {
+                                               command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
+                                               free(data);
+                                               free(buffer);
+                                               image_close(&image);
+                                               return ERROR_OK;
+                                       }
+                               }
+                       }
+                       
+                       free(data);
+               }
+               
+               free(buffer);
+               image_size += buf_cnt;
+       }
+       
+       duration_stop_measure(&duration, &duration_text);
+       command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
+       free(duration_text);
+       
+       image_close(&image);
+       
+       return ERROR_OK;
+}
+
+int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc == 0)
+       {
+               breakpoint_t *breakpoint = target->breakpoints;
+
+               while (breakpoint)
+               {
+                       if (breakpoint->type == BKPT_SOFT)
+                       {
+                               char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16);
+                               command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf);
+                               free(buf);
+                       }
+                       else
+                       {
+                               command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);
+                       }
+                       breakpoint = breakpoint->next;
+               }
+       }
+       else if (argc >= 2)
+       {
+               int hw = BKPT_SOFT;
+               u32 length = 0;
+
+               length = strtoul(args[1], NULL, 0);
+               
+               if (argc >= 3)
+                       if (strcmp(args[2], "hw") == 0)
+                               hw = BKPT_HARD;
+
+               if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)
+               {
+                       switch (retval)
+                       {
+                               case ERROR_TARGET_NOT_HALTED:
+                                       command_print(cmd_ctx, "target must be halted to set breakpoints");
+                                       break;
+                               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+                                       command_print(cmd_ctx, "no more breakpoints available");
+                                       break;
+                               default:
+                                       command_print(cmd_ctx, "unknown error, breakpoint not set");
+                                       break;
+                       }
+               }
+               else
+               {
+                       command_print(cmd_ctx, "breakpoint added at address 0x%8.8x", strtoul(args[0], NULL, 0));
+               }
+       }
+       else
+       {
+               command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
+       }
+
+       return ERROR_OK;
+}
+
+int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc > 0)
+               breakpoint_remove(target, strtoul(args[0], NULL, 0));
+
+       return ERROR_OK;
+}
+
+int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       int retval;
+
+       if (argc == 0)
+       {
+               watchpoint_t *watchpoint = target->watchpoints;
+
+               while (watchpoint)
+               {
+                       command_print(cmd_ctx, "address: 0x%8.8x, mask: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
+                       watchpoint = watchpoint->next;
+               }
+       } 
+       else if (argc >= 2)
+       {
+               enum watchpoint_rw type = WPT_ACCESS;
+               u32 data_value = 0x0;
+               u32 data_mask = 0xffffffff;
+               
+               if (argc >= 3)
+               {
+                       switch(args[2][0])
+                       {
+                               case 'r':
+                                       type = WPT_READ;
+                                       break;
+                               case 'w':
+                                       type = WPT_WRITE;
+                                       break;
+                               case 'a':
+                                       type = WPT_ACCESS;
+                                       break;
+                               default:
+                                       command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
+                                       return ERROR_OK;
+                       }
+               }
+               if (argc >= 4)
+               {
+                       data_value = strtoul(args[3], NULL, 0);
+               }
+               if (argc >= 5)
+               {
+                       data_mask = strtoul(args[4], NULL, 0);
+               }
+               
+               if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
+                               strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
+               {
+                       switch (retval)
+                       {
+                               case ERROR_TARGET_NOT_HALTED:
+                                       command_print(cmd_ctx, "target must be halted to set watchpoints");
+                                       break;
+                               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+                                       command_print(cmd_ctx, "no more watchpoints available");
+                                       break;
+                               default:
+                                       command_print(cmd_ctx, "unknown error, watchpoint not set");
+                                       break;
+                       }       
+               }
+       }
+       else
+       {
+               command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
+       }
+               
+       return ERROR_OK;
+}
+
+int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+
+       if (argc > 0)
+               watchpoint_remove(target, strtoul(args[0], NULL, 0));
+       
+       return ERROR_OK;
+}
+
+int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       u32 va;
+       u32 pa;
+
+       if (argc != 1)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       va = strtoul(args[0], NULL, 0);
+
+       retval = target->type->virt2phys(target, va, &pa);
+       if (retval == ERROR_OK)
+       {
+               command_print(cmd_ctx, "Physical address 0x%08x", pa);
+       }
+       else
+       {
+               /* lower levels will have logged a detailed error which is 
+                * forwarded to telnet/GDB session.  
+                */
+       }
+       return retval;
+}
index 11ae5eedf4149679ee104c3d54b0a84b115263fa..b156e227cd7e684835d9f8568addd60140625c03 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2006, 2007 by Dominic Rath                              *\r
- *   Dominic.Rath@gmx.de                                                   *\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
-\r
-#include "xscale.h"\r
-\r
-#include "register.h"\r
-#include "target.h"\r
-#include "armv4_5.h"\r
-#include "arm_simulator.h"\r
-#include "arm_disassembler.h"\r
-#include "log.h"\r
-#include "jtag.h"\r
-#include "binarybuffer.h"\r
-#include "time_support.h"\r
-#include "breakpoints.h"\r
-#include "fileio.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-\r
-#include <sys/types.h>\r
-#include <unistd.h>\r
-#include <errno.h>\r
-\r
-\r
-/* cli handling */\r
-int xscale_register_commands(struct command_context_s *cmd_ctx);\r
-\r
-/* forward declarations */\r
-int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);\r
-int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target);\r
-int xscale_quit();\r
-\r
-int xscale_arch_state(struct target_s *target);\r
-int xscale_poll(target_t *target);\r
-int xscale_halt(target_t *target);\r
-int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);\r
-int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints);\r
-int xscale_debug_entry(target_t *target);\r
-int xscale_restore_context(target_t *target);\r
-\r
-int xscale_assert_reset(target_t *target);\r
-int xscale_deassert_reset(target_t *target);\r
-int xscale_soft_reset_halt(struct target_s *target);\r
-int xscale_prepare_reset_halt(struct target_s *target);\r
-\r
-int xscale_set_reg_u32(reg_t *reg, u32 value);\r
-\r
-int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode);\r
-int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value);\r
-\r
-int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);\r
-int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);\r
-int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);\r
-\r
-int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);\r
-int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);\r
-int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);\r
-int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);\r
-int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);\r
-int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);\r
-void xscale_enable_watchpoints(struct target_s *target);\r
-void xscale_enable_breakpoints(struct target_s *target);\r
-static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);\r
-static int xscale_mmu(struct target_s *target, int *enabled);\r
-\r
-int xscale_read_trace(target_t *target);\r
-\r
-target_type_t xscale_target =\r
-{\r
-       .name = "xscale",\r
-\r
-       .poll = xscale_poll,\r
-       .arch_state = xscale_arch_state,\r
-\r
-       .target_request_data = NULL,\r
-\r
-       .halt = xscale_halt,\r
-       .resume = xscale_resume,\r
-       .step = xscale_step,\r
-\r
-       .assert_reset = xscale_assert_reset,\r
-       .deassert_reset = xscale_deassert_reset,\r
-       .soft_reset_halt = xscale_soft_reset_halt,\r
-       .prepare_reset_halt = xscale_prepare_reset_halt,\r
-\r
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,\r
-\r
-       .read_memory = xscale_read_memory,\r
-       .write_memory = xscale_write_memory,\r
-       .bulk_write_memory = xscale_bulk_write_memory,\r
-       .checksum_memory = xscale_checksum_memory,\r
-\r
-       .run_algorithm = armv4_5_run_algorithm,\r
-\r
-       .add_breakpoint = xscale_add_breakpoint,\r
-       .remove_breakpoint = xscale_remove_breakpoint,\r
-       .add_watchpoint = xscale_add_watchpoint,\r
-       .remove_watchpoint = xscale_remove_watchpoint,\r
-\r
-       .register_commands = xscale_register_commands,\r
-       .target_command = xscale_target_command,\r
-       .init_target = xscale_init_target,\r
-       .quit = xscale_quit,\r
-       \r
-       .virt2phys = xscale_virt2phys,\r
-       .mmu = xscale_mmu\r
-};\r
-\r
-char* xscale_reg_list[] =\r
-{\r
-       "XSCALE_MAINID",                /* 0 */\r
-       "XSCALE_CACHETYPE",\r
-       "XSCALE_CTRL",\r
-       "XSCALE_AUXCTRL",\r
-       "XSCALE_TTB",\r
-       "XSCALE_DAC",\r
-       "XSCALE_FSR",\r
-       "XSCALE_FAR",\r
-       "XSCALE_PID",\r
-       "XSCALE_CPACCESS",\r
-       "XSCALE_IBCR0",                 /* 10 */\r
-       "XSCALE_IBCR1",\r
-       "XSCALE_DBR0",\r
-       "XSCALE_DBR1",\r
-       "XSCALE_DBCON",\r
-       "XSCALE_TBREG",\r
-       "XSCALE_CHKPT0",\r
-       "XSCALE_CHKPT1",\r
-       "XSCALE_DCSR",\r
-       "XSCALE_TX",\r
-       "XSCALE_RX",                    /* 20 */\r
-       "XSCALE_TXRXCTRL",\r
-};\r
-\r
-xscale_reg_t xscale_reg_arch_info[] =\r
-{\r
-       {XSCALE_MAINID, NULL},\r
-       {XSCALE_CACHETYPE, NULL},\r
-       {XSCALE_CTRL, NULL},\r
-       {XSCALE_AUXCTRL, NULL},\r
-       {XSCALE_TTB, NULL},\r
-       {XSCALE_DAC, NULL},\r
-       {XSCALE_FSR, NULL},\r
-       {XSCALE_FAR, NULL},\r
-       {XSCALE_PID, NULL},\r
-       {XSCALE_CPACCESS, NULL},\r
-       {XSCALE_IBCR0, NULL},\r
-       {XSCALE_IBCR1, NULL},\r
-       {XSCALE_DBR0, NULL},\r
-       {XSCALE_DBR1, NULL},\r
-       {XSCALE_DBCON, NULL},\r
-       {XSCALE_TBREG, NULL},\r
-       {XSCALE_CHKPT0, NULL},\r
-       {XSCALE_CHKPT1, NULL},\r
-       {XSCALE_DCSR, NULL}, /* DCSR accessed via JTAG or SW */\r
-       {-1, NULL}, /* TX accessed via JTAG */\r
-       {-1, NULL}, /* RX accessed via JTAG */\r
-       {-1, NULL}, /* TXRXCTRL implicit access via JTAG */\r
-};\r
-\r
-int xscale_reg_arch_type = -1;\r
-\r
-int xscale_get_reg(reg_t *reg);\r
-int xscale_set_reg(reg_t *reg, u8 *buf);\r
-\r
-int xscale_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, xscale_common_t **xscale_p)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               ERROR("target isn't an XScale target");\r
-               return -1;\r
-       }\r
-\r
-       if (xscale->common_magic != XSCALE_COMMON_MAGIC)\r
-       {\r
-               ERROR("target isn't an XScale target");\r
-               return -1;\r
-       }\r
-\r
-       *armv4_5_p = armv4_5;\r
-       *xscale_p = xscale;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_jtag_set_instr(int chain_pos, u32 new_instr)\r
-{\r
-       jtag_device_t *device = jtag_get_device(chain_pos);\r
-\r
-       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)\r
-       {\r
-               scan_field_t field;\r
-\r
-               field.device = chain_pos;\r
-               field.num_bits = device->ir_length;\r
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);\r
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);\r
-               field.out_mask = NULL;\r
-               field.in_value = NULL;\r
-               jtag_set_check_value(&field, device->expected, device->expected_mask, NULL);\r
-\r
-               jtag_add_ir_scan(1, &field, -1);\r
-\r
-               free(field.out_value);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_jtag_callback(enum jtag_event event, void *priv)\r
-{\r
-       switch (event)\r
-       {\r
-               case JTAG_TRST_ASSERTED:\r
-                       break;\r
-               case JTAG_TRST_RELEASED:\r
-                       break;\r
-               case JTAG_SRST_ASSERTED:\r
-                       break;\r
-               case JTAG_SRST_RELEASED:\r
-                       break;\r
-               default:\r
-                       WARNING("unhandled JTAG event");\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_read_dcsr(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       int retval;\r
-\r
-       scan_field_t fields[3];\r
-       u8 field0 = 0x0;\r
-       u8 field0_check_value = 0x2;\r
-       u8 field0_check_mask = 0x7;\r
-       u8 field2 = 0x0;\r
-       u8 field2_check_value = 0x0;\r
-       u8 field2_check_mask = 0x1;\r
-\r
-       jtag_add_end_state(TAP_PD);\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);\r
-\r
-       buf_set_u32(&field0, 1, 1, xscale->hold_rst);\r
-       buf_set_u32(&field0, 2, 1, xscale->external_debug_break);\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 3;\r
-       fields[0].out_value = &field0;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-\r
-\r
-       fields[2].device = xscale->jtag_info.chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = &field2;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);\r
-\r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-       {\r
-               ERROR("JTAG error while reading DCSR");\r
-               return retval;\r
-       }\r
-\r
-       xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;\r
-       xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;\r
-\r
-       /* write the register with the value we just read\r
-        * on this second pass, only the first bit of field0 is guaranteed to be 0)\r
-        */\r
-       field0_check_mask = 0x1;\r
-       fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;\r
-       fields[1].in_value = NULL;\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-\r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_receive(target_t *target, u32 *buffer, int num_words)\r
-{\r
-       int retval = ERROR_OK;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       enum tap_state path[3];\r
-       scan_field_t fields[3];\r
-\r
-       u8 *field0 = malloc(num_words * 1);\r
-       u8 field0_check_value = 0x2;\r
-       u8 field0_check_mask = 0x6;\r
-       u32 *field1 = malloc(num_words * 4);\r
-       u8 field2_check_value = 0x0;\r
-       u8 field2_check_mask = 0x1;\r
-       int words_done = 0;\r
-       int words_scheduled = 0;\r
-\r
-       int i;\r
-\r
-       path[0] = TAP_SDS;\r
-       path[1] = TAP_CD;\r
-       path[2] = TAP_SD;\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 3;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       /* fields[0].in_value = field0; */\r
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-\r
-\r
-       fields[2].device = xscale->jtag_info.chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = NULL;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);\r
-       jtag_add_runtest(1, -1);\r
-\r
-       /* repeat until all words have been collected */\r
-       int attempts = 0;\r
-       while (words_done < num_words)\r
-       {\r
-               /* schedule reads */\r
-               words_scheduled = 0;\r
-               for (i = words_done; i < num_words; i++)\r
-               {\r
-                       fields[0].in_value = &field0[i];\r
-                       fields[1].in_handler = buf_to_u32_handler;\r
-                       fields[1].in_handler_priv = (u8*)&field1[i];\r
-\r
-                       jtag_add_pathmove(3, path);\r
-                       jtag_add_dr_scan(3, fields, TAP_RTI);\r
-                       words_scheduled++;\r
-               }\r
-\r
-               if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-               {\r
-                       ERROR("JTAG error while receiving data from debug handler");\r
-                       break;\r
-               }\r
-\r
-               /* examine results */\r
-               for (i = words_done; i < num_words; i++)\r
-               {\r
-                       if (!(field0[0] & 1))\r
-                       {\r
-                               /* move backwards if necessary */\r
-                               int j;\r
-                               for (j = i; j < num_words - 1; j++)\r
-                               {\r
-                                       field0[j] = field0[j+1];\r
-                                       field1[j] = field1[j+1];\r
-                               }\r
-                               words_scheduled--;\r
-                       }\r
-               }\r
-               if (words_scheduled == 0)\r
-               {\r
-                       if (attempts++ == 1000)\r
-                       {\r
-                               ERROR("Failed to receiving data from debug handler after 1000 attempts");\r
-                               retval = ERROR_JTAG_QUEUE_FAILED;\r
-                               break;\r
-                       }\r
-               }\r
-               \r
-               words_done += words_scheduled;\r
-       }\r
-\r
-       for (i = 0; i < num_words; i++)\r
-               *(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);\r
-\r
-       free(field1);\r
-\r
-       return retval;\r
-}\r
-\r
-int xscale_read_tx(target_t *target, int consume)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       enum tap_state path[3];\r
-       enum tap_state noconsume_path[9];\r
-\r
-       int retval;\r
-       struct timeval timeout, now;\r
-\r
-       scan_field_t fields[3];\r
-       u8 field0_in = 0x0;\r
-       u8 field0_check_value = 0x2;\r
-       u8 field0_check_mask = 0x6;\r
-       u8 field2_check_value = 0x0;\r
-       u8 field2_check_mask = 0x1;\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);\r
-\r
-       path[0] = TAP_SDS;\r
-       path[1] = TAP_CD;\r
-       path[2] = TAP_SD;\r
-\r
-       noconsume_path[0] = TAP_SDS;\r
-       noconsume_path[1] = TAP_CD;\r
-       noconsume_path[2] = TAP_E1D;\r
-       noconsume_path[3] = TAP_PD;\r
-       noconsume_path[4] = TAP_E2D;\r
-       noconsume_path[5] = TAP_UD;\r
-       noconsume_path[6] = TAP_SDS;\r
-       noconsume_path[7] = TAP_CD;\r
-       noconsume_path[8] = TAP_SD;\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 3;\r
-       fields[0].out_value = NULL;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = &field0_in;\r
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = NULL;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-\r
-\r
-       fields[2].device = xscale->jtag_info.chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = NULL;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);\r
-\r
-       gettimeofday(&timeout, NULL);\r
-       timeval_add_time(&timeout, 5, 0);\r
-\r
-       do\r
-       {\r
-               /* if we want to consume the register content (i.e. clear TX_READY),\r
-                * we have to go straight from Capture-DR to Shift-DR\r
-                * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR\r
-               */\r
-               if (consume)\r
-                       jtag_add_pathmove(3, path);\r
-               else\r
-                       jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);\r
-\r
-               jtag_add_dr_scan(3, fields, TAP_RTI);\r
-\r
-               if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-               {\r
-                       ERROR("JTAG error while reading TX");\r
-                       return ERROR_TARGET_TIMEOUT;\r
-               }\r
-\r
-               gettimeofday(&now, NULL);\r
-               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))\r
-               {\r
-                       ERROR("time out reading TX register");\r
-                       return ERROR_TARGET_TIMEOUT;\r
-               }\r
-       } while ((!(field0_in & 1)) && consume);\r
-\r
-       if (!(field0_in & 1))\r
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_write_rx(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       int retval;\r
-       struct timeval timeout, now;\r
-\r
-       scan_field_t fields[3];\r
-       u8 field0_out = 0x0;\r
-       u8 field0_in = 0x0;\r
-       u8 field0_check_value = 0x2;\r
-       u8 field0_check_mask = 0x6;\r
-       u8 field2 = 0x0;\r
-       u8 field2_check_value = 0x0;\r
-       u8 field2_check_mask = 0x1;\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 3;\r
-       fields[0].out_value = &field0_out;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = &field0_in;\r
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-\r
-\r
-       fields[2].device = xscale->jtag_info.chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = &field2;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);\r
-\r
-       gettimeofday(&timeout, NULL);\r
-       timeval_add_time(&timeout, 5, 0);\r
-\r
-       /* poll until rx_read is low */\r
-       DEBUG("polling RX");\r
-       do\r
-       {\r
-               jtag_add_dr_scan(3, fields, TAP_RTI);\r
-\r
-               if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-               {\r
-                       ERROR("JTAG error while writing RX");\r
-                       return retval;\r
-               }\r
-\r
-               gettimeofday(&now, NULL);\r
-               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))\r
-               {\r
-                       ERROR("time out writing RX register");\r
-                       return ERROR_TARGET_TIMEOUT;\r
-               }\r
-       } while (field0_in & 1);\r
-\r
-       /* set rx_valid */\r
-       field2 = 0x1;\r
-       jtag_add_dr_scan(3, fields, TAP_RTI);\r
-\r
-       if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-       {\r
-               ERROR("JTAG error while writing RX");\r
-               return retval;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* send count elements of size byte to the debug handler */\r
-int xscale_send(target_t *target, u8 *buffer, int count, int size)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       int retval;\r
-\r
-       int done_count = 0;\r
-       u8 output[4] = {0, 0, 0, 0};\r
-\r
-       scan_field_t fields[3];\r
-       u8 field0_out = 0x0;\r
-       u8 field0_check_value = 0x2;\r
-       u8 field0_check_mask = 0x6;\r
-       u8 field2 = 0x1;\r
-       u8 field2_check_value = 0x0;\r
-       u8 field2_check_mask = 0x1;\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 3;\r
-       fields[0].out_value = &field0_out;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       if (!xscale->fast_memory_access)\r
-       {\r
-               jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);\r
-       }\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = output;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-\r
-\r
-       fields[2].device = xscale->jtag_info.chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = &field2;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_handler = NULL;\r
-       if (!xscale->fast_memory_access)\r
-       {\r
-               jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);\r
-       }\r
-\r
-       if (size==4)\r
-       {\r
-               int endianness = target->endianness;\r
-               while (done_count++ < count)\r
-               {\r
-                       if (endianness == TARGET_LITTLE_ENDIAN)\r
-                       {\r
-                               output[0]=buffer[0];\r
-                               output[1]=buffer[1];\r
-                               output[2]=buffer[2];\r
-                               output[3]=buffer[3];\r
-                       } else\r
-                       {\r
-                               output[0]=buffer[3];\r
-                               output[1]=buffer[2];\r
-                               output[2]=buffer[1];\r
-                               output[3]=buffer[0];\r
-                       }\r
-                       jtag_add_dr_scan(3, fields, TAP_RTI);\r
-                       buffer += size;\r
-               }\r
-               \r
-       } else\r
-       {\r
-               while (done_count++ < count)\r
-               {\r
-               /* extract sized element from target-endian buffer, and put it\r
-                * into little-endian output buffer\r
-                */\r
-               switch (size)\r
-               {\r
-                       case 2:\r
-                               buf_set_u32(output, 0, 32, target_buffer_get_u16(target, buffer));\r
-                               break;\r
-                       case 1:\r
-                               output[0] = *buffer;\r
-                               break;\r
-                       default:\r
-                               ERROR("BUG: size neither 4, 2 nor 1");\r
-                               exit(-1);\r
-               }\r
-\r
-               jtag_add_dr_scan(3, fields, TAP_RTI);\r
-               buffer += size;\r
-       }\r
-\r
-       }\r
-\r
-       if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-       {\r
-               ERROR("JTAG error while sending data to debug handler");\r
-               return retval;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_send_u32(target_t *target, u32 value)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);\r
-       return xscale_write_rx(target);\r
-}\r
-\r
-int xscale_write_dcsr(target_t *target, int hold_rst, int ext_dbg_brk)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       int retval;\r
-\r
-       scan_field_t fields[3];\r
-       u8 field0 = 0x0;\r
-       u8 field0_check_value = 0x2;\r
-       u8 field0_check_mask = 0x7;\r
-       u8 field2 = 0x0;\r
-       u8 field2_check_value = 0x0;\r
-       u8 field2_check_mask = 0x1;\r
-\r
-       if (hold_rst != -1)\r
-               xscale->hold_rst = hold_rst;\r
-\r
-       if (ext_dbg_brk != -1)\r
-               xscale->external_debug_break = ext_dbg_brk;\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);\r
-\r
-       buf_set_u32(&field0, 1, 1, xscale->hold_rst);\r
-       buf_set_u32(&field0, 2, 1, xscale->external_debug_break);\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 3;\r
-       fields[0].out_value = &field0;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 32;\r
-       fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-\r
-\r
-\r
-       fields[2].device = xscale->jtag_info.chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = &field2;\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);\r
-\r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       if ((retval = jtag_execute_queue()) != ERROR_OK)\r
-       {\r
-               ERROR("JTAG error while writing DCSR");\r
-               return retval;\r
-       }\r
-\r
-       xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;\r
-       xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */\r
-unsigned int parity (unsigned int v)\r
-{\r
-       unsigned int ov = v;\r
-       v ^= v >> 16;\r
-       v ^= v >> 8;\r
-       v ^= v >> 4;\r
-       v &= 0xf;\r
-       DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1);\r
-       return (0x6996 >> v) & 1;\r
-}\r
-\r
-int xscale_load_ic(target_t *target, int mini, u32 va, u32 buffer[8])\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u8 packet[4];\r
-       u8 cmd;\r
-       int word;\r
-\r
-       scan_field_t fields[2];\r
-\r
-       DEBUG("loading miniIC at 0x%8.8x", va);\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */\r
-\r
-       /* CMD is b010 for Main IC and b011 for Mini IC */\r
-       if (mini)\r
-               buf_set_u32(&cmd, 0, 3, 0x3);\r
-       else\r
-               buf_set_u32(&cmd, 0, 3, 0x2);\r
-\r
-       buf_set_u32(&cmd, 3, 3, 0x0);\r
-\r
-       /* virtual address of desired cache line */\r
-       buf_set_u32(packet, 0, 27, va >> 5);\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 6;\r
-       fields[0].out_value = &cmd;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 27;\r
-       fields[1].out_value = packet;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = packet;\r
-\r
-       fields[1].num_bits = 1;\r
-       fields[1].out_value = &cmd;\r
-\r
-       for (word = 0; word < 8; word++)\r
-       {\r
-               buf_set_u32(packet, 0, 32, buffer[word]);\r
-               cmd = parity(*((u32*)packet));\r
-               jtag_add_dr_scan(2, fields, -1);\r
-       }\r
-\r
-       jtag_execute_queue();\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_invalidate_ic_line(target_t *target, u32 va)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u8 packet[4];\r
-       u8 cmd;\r
-\r
-       scan_field_t fields[2];\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */\r
-\r
-       /* CMD for invalidate IC line b000, bits [6:4] b000 */\r
-       buf_set_u32(&cmd, 0, 6, 0x0);\r
-\r
-       /* virtual address of desired cache line */\r
-       buf_set_u32(packet, 0, 27, va >> 5);\r
-\r
-       fields[0].device = xscale->jtag_info.chain_pos;\r
-       fields[0].num_bits = 6;\r
-       fields[0].out_value = &cmd;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-\r
-       fields[1].device = xscale->jtag_info.chain_pos;\r
-       fields[1].num_bits = 27;\r
-       fields[1].out_value = packet;\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       jtag_add_dr_scan(2, fields, -1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_update_vectors(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       int i;\r
-\r
-       u32 low_reset_branch, high_reset_branch;\r
-\r
-       for (i = 1; i < 8; i++)\r
-       {\r
-               /* if there's a static vector specified for this exception, override */\r
-               if (xscale->static_high_vectors_set & (1 << i))\r
-               {\r
-                       xscale->high_vectors[i] = xscale->static_high_vectors[i];\r
-               }\r
-               else\r
-               {\r
-                       if (target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]) != ERROR_OK)\r
-                       {\r
-                               xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);\r
-                       }\r
-               }\r
-       }\r
-\r
-       for (i = 1; i < 8; i++)\r
-       {\r
-               if (xscale->static_low_vectors_set & (1 << i))\r
-               {\r
-                       xscale->low_vectors[i] = xscale->static_low_vectors[i];\r
-               }\r
-               else\r
-               {\r
-                       if (target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]) != ERROR_OK)\r
-                       {\r
-                               xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* calculate branches to debug handler */\r
-       low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;\r
-       high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;\r
-\r
-       xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);\r
-       xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);\r
-\r
-       /* invalidate and load exception vectors in mini i-cache */\r
-       xscale_invalidate_ic_line(target, 0x0);\r
-       xscale_invalidate_ic_line(target, 0xffff0000);\r
-\r
-       xscale_load_ic(target, 1, 0x0, xscale->low_vectors);\r
-       xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_arch_state(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       char *state[] =\r
-       {\r
-               "disabled", "enabled"\r
-       };\r
-\r
-       char *arch_dbg_reason[] =\r
-       {\r
-               "", "\n(processor reset)", "\n(trace buffer full)"\r
-       };\r
-\r
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)\r
-       {\r
-               ERROR("BUG: called for a non-ARMv4/5 target");\r
-               exit(-1);\r
-       }\r
-\r
-       USER("target halted in %s state due to %s, current mode: %s\n"\r
-                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"\r
-                       "MMU: %s, D-Cache: %s, I-Cache: %s"\r
-                       "%s",\r
-                        armv4_5_state_strings[armv4_5->core_state],\r
-                        target_debug_reason_strings[target->debug_reason],\r
-                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),\r
-                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),\r
-                        state[xscale->armv4_5_mmu.mmu_enabled],\r
-                        state[xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],\r
-                        state[xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled],\r
-                        arch_dbg_reason[xscale->arch_debug_reason]);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_poll(target_t *target)\r
-{\r
-       int retval=ERROR_OK;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))\r
-       {\r
-               enum target_state previous_state = target->state;\r
-               if ((retval = xscale_read_tx(target, 0)) == ERROR_OK)\r
-               {\r
-\r
-                       /* there's data to read from the tx register, we entered debug state */\r
-                       xscale->handler_running = 1;\r
-\r
-                       target->state = TARGET_HALTED;\r
-\r
-                       /* process debug entry, fetching current mode regs */\r
-                       retval = xscale_debug_entry(target);\r
-               }\r
-               else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)\r
-               {\r
-                       USER("error while polling TX register, reset CPU");\r
-                       /* here we "lie" so GDB won't get stuck and a reset can be perfomed */\r
-                       target->state = TARGET_HALTED;\r
-               }\r
-\r
-                       /* debug_entry could have overwritten target state (i.e. immediate resume)\r
-                        * don't signal event handlers in that case\r
-                        */\r
-               if (target->state != TARGET_HALTED)\r
-                       return ERROR_OK;\r
-\r
-               /* if target was running, signal that we halted\r
-                * otherwise we reentered from debug execution */\r
-               if (previous_state == TARGET_RUNNING)\r
-                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
-               else\r
-                       target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);\r
-       }\r
-       return retval;\r
-}\r
-\r
-int xscale_debug_entry(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u32 pc;\r
-       u32 buffer[10];\r
-       int i;\r
-\r
-       u32 moe;\r
-\r
-       /* clear external dbg break (will be written on next DCSR read) */\r
-       xscale->external_debug_break = 0;\r
-       xscale_read_dcsr(target);\r
-\r
-       /* get r0, pc, r1 to r7 and cpsr */\r
-       xscale_receive(target, buffer, 10);\r
-\r
-       /* move r0 from buffer to register cache */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, buffer[0]);\r
-       armv4_5->core_cache->reg_list[15].dirty = 1;\r
-       armv4_5->core_cache->reg_list[15].valid = 1;\r
-       DEBUG("r0: 0x%8.8x", buffer[0]);\r
-\r
-       /* move pc from buffer to register cache */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, buffer[1]);\r
-       armv4_5->core_cache->reg_list[15].dirty = 1;\r
-       armv4_5->core_cache->reg_list[15].valid = 1;\r
-       DEBUG("pc: 0x%8.8x", buffer[1]);\r
-\r
-       /* move data from buffer to register cache */\r
-       for (i = 1; i <= 7; i++)\r
-       {\r
-               buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, buffer[1 + i]);\r
-               armv4_5->core_cache->reg_list[i].dirty = 1;\r
-               armv4_5->core_cache->reg_list[i].valid = 1;\r
-               DEBUG("r%i: 0x%8.8x", i, buffer[i + 1]);\r
-       }\r
-\r
-       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, buffer[9]);\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;\r
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;\r
-       DEBUG("cpsr: 0x%8.8x", buffer[9]);\r
-\r
-       armv4_5->core_mode = buffer[9] & 0x1f;\r
-       if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)\r
-       {\r
-               target->state = TARGET_UNKNOWN;\r
-               ERROR("cpsr contains invalid mode value - communication failure");\r
-               return ERROR_TARGET_FAILURE;\r
-       }\r
-       DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);\r
-\r
-       if (buffer[9] & 0x20)\r
-               armv4_5->core_state = ARMV4_5_STATE_THUMB;\r
-       else\r
-               armv4_5->core_state = ARMV4_5_STATE_ARM;\r
-\r
-       /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */\r
-       if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS))\r
-       {\r
-               xscale_receive(target, buffer, 8);\r
-               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);\r
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;\r
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1;\r
-       }\r
-       else\r
-       {\r
-               /* r8 to r14, but no spsr */\r
-               xscale_receive(target, buffer, 7);\r
-       }\r
-\r
-       /* move data from buffer to register cache */\r
-       for (i = 8; i <= 14; i++)\r
-       {\r
-               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, buffer[i - 8]);\r
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;\r
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;\r
-       }\r
-\r
-       /* examine debug reason */\r
-       xscale_read_dcsr(target);\r
-       moe = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 2, 3);\r
-\r
-       /* stored PC (for calculating fixup) */\r
-       pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-\r
-       switch (moe)\r
-       {\r
-               case 0x0: /* Processor reset */\r
-                       target->debug_reason = DBG_REASON_DBGRQ;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_RESET;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x1: /* Instruction breakpoint hit */\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x2: /* Data breakpoint hit */\r
-                       target->debug_reason = DBG_REASON_WATCHPOINT;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x3: /* BKPT instruction executed */\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x4: /* Ext. debug event */\r
-                       target->debug_reason = DBG_REASON_DBGRQ;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x5: /* Vector trap occured */\r
-                       target->debug_reason = DBG_REASON_BREAKPOINT;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x6: /* Trace buffer full break */\r
-                       target->debug_reason = DBG_REASON_DBGRQ;\r
-                       xscale->arch_debug_reason = XSCALE_DBG_REASON_TB_FULL;\r
-                       pc -= 4;\r
-                       break;\r
-               case 0x7: /* Reserved */\r
-               default:\r
-                       ERROR("Method of Entry is 'Reserved'");\r
-                       exit(-1);\r
-                       break;\r
-       }\r
-\r
-       /* apply PC fixup */\r
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, pc);\r
-\r
-       /* on the first debug entry, identify cache type */\r
-       if (xscale->armv4_5_mmu.armv4_5_cache.ctype == -1)\r
-       {\r
-               u32 cache_type_reg;\r
-\r
-               /* read cp15 cache type register */\r
-               xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CACHETYPE]);\r
-               cache_type_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CACHETYPE].value, 0, 32);\r
-\r
-               armv4_5_identify_cache(cache_type_reg, &xscale->armv4_5_mmu.armv4_5_cache);\r
-       }\r
-\r
-       /* examine MMU and Cache settings */\r
-       /* read cp15 control register */\r
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);\r
-       xscale->cp15_control_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);\r
-       xscale->armv4_5_mmu.mmu_enabled = (xscale->cp15_control_reg & 0x1U) ? 1 : 0;\r
-       xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (xscale->cp15_control_reg & 0x4U) ? 1 : 0;\r
-       xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (xscale->cp15_control_reg & 0x1000U) ? 1 : 0;\r
-\r
-       /* tracing enabled, read collected trace data */\r
-       if (xscale->trace.buffer_enabled)\r
-       {\r
-               xscale_read_trace(target);\r
-               xscale->trace.buffer_fill--;\r
-\r
-               /* resume if we're still collecting trace data */\r
-               if ((xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)\r
-                       && (xscale->trace.buffer_fill > 0))\r
-               {\r
-                       xscale_resume(target, 1, 0x0, 1, 0);\r
-               }\r
-               else\r
-               {\r
-                       xscale->trace.buffer_enabled = 0;\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_halt(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       DEBUG("target->state: %s", target_state_strings[target->state]);\r
-\r
-       if (target->state == TARGET_HALTED)\r
-       {\r
-               WARNING("target was already halted");\r
-               return ERROR_TARGET_ALREADY_HALTED;\r
-       }\r
-       else if (target->state == TARGET_UNKNOWN)\r
-       {\r
-               /* this must not happen for a xscale target */\r
-               ERROR("target was in unknown state when halt was requested");\r
-               return ERROR_TARGET_INVALID;\r
-       }\r
-       else if (target->state == TARGET_RESET)\r
-       {\r
-               DEBUG("target->state == TARGET_RESET");\r
-       }\r
-       else\r
-       {\r
-               /* assert external dbg break */\r
-               xscale->external_debug_break = 1;\r
-               xscale_read_dcsr(target);\r
-\r
-               target->debug_reason = DBG_REASON_DBGRQ;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_enable_single_step(struct target_s *target, u32 next_pc)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale= armv4_5->arch_info;\r
-       reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];\r
-\r
-       if (xscale->ibcr0_used)\r
-       {\r
-               breakpoint_t *ibcr0_bp = breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe);\r
-\r
-               if (ibcr0_bp)\r
-               {\r
-                       xscale_unset_breakpoint(target, ibcr0_bp);\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: xscale->ibcr0_used is set, but no breakpoint with that address found");\r
-                       exit(-1);\r
-               }\r
-       }\r
-\r
-       xscale_set_reg_u32(ibcr0, next_pc | 0x1);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_disable_single_step(struct target_s *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale= armv4_5->arch_info;\r
-       reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];\r
-\r
-       xscale_set_reg_u32(ibcr0, 0x0);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale= armv4_5->arch_info;\r
-       breakpoint_t *breakpoint = target->breakpoints;\r
-\r
-       u32 current_pc;\r
-\r
-       int retval;\r
-       int i;\r
-\r
-       DEBUG("-");\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (!debug_execution)\r
-       {\r
-               target_free_all_working_areas(target);\r
-       }\r
-\r
-       /* update vector tables */\r
-       xscale_update_vectors(target);\r
-\r
-       /* current = 1: continue on current pc, otherwise continue at <address> */\r
-       if (!current)\r
-               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);\r
-\r
-       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-\r
-       /* if we're at the reset vector, we have to simulate the branch */\r
-       if (current_pc == 0x0)\r
-       {\r
-               arm_simulate_step(target, NULL);\r
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-       }\r
-\r
-       /* the front-end may request us not to handle breakpoints */\r
-       if (handle_breakpoints)\r
-       {\r
-               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))\r
-               {\r
-                       u32 next_pc;\r
-\r
-                       /* there's a breakpoint at the current PC, we have to step over it */\r
-                       DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);\r
-                       xscale_unset_breakpoint(target, breakpoint);\r
-\r
-                       /* calculate PC of next instruction */\r
-                       if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)\r
-                       {\r
-                               u32 current_opcode;\r
-                               target_read_u32(target, current_pc, &current_opcode);\r
-                               ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);\r
-                       }\r
-\r
-                       DEBUG("enable single-step");\r
-                       xscale_enable_single_step(target, next_pc);\r
-\r
-                       /* restore banked registers */\r
-                       xscale_restore_context(target);\r
-\r
-                       /* send resume request (command 0x30 or 0x31)\r
-                        * clean the trace buffer if it is to be enabled (0x62) */\r
-                       if (xscale->trace.buffer_enabled)\r
-                       {\r
-                               xscale_send_u32(target, 0x62);\r
-                               xscale_send_u32(target, 0x31);\r
-                       }\r
-                       else\r
-                               xscale_send_u32(target, 0x30);\r
-\r
-                       /* send CPSR */\r
-                       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));\r
-                       DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));\r
-\r
-                       for (i = 7; i >= 0; i--)\r
-                       {\r
-                               /* send register */\r
-                               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));\r
-                               DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));\r
-                       }\r
-\r
-                       /* send PC */\r
-                       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));\r
-                       DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));\r
-\r
-                       /* wait for and process debug entry */\r
-                       xscale_debug_entry(target);\r
-\r
-                       DEBUG("disable single-step");\r
-                       xscale_disable_single_step(target);\r
-\r
-                       DEBUG("set breakpoint at 0x%8.8x", breakpoint->address);\r
-                       xscale_set_breakpoint(target, breakpoint);\r
-               }\r
-       }\r
-\r
-       /* enable any pending breakpoints and watchpoints */\r
-       xscale_enable_breakpoints(target);\r
-       xscale_enable_watchpoints(target);\r
-\r
-       /* restore banked registers */\r
-       xscale_restore_context(target);\r
-\r
-       /* send resume request (command 0x30 or 0x31)\r
-        * clean the trace buffer if it is to be enabled (0x62) */\r
-       if (xscale->trace.buffer_enabled)\r
-       {\r
-               xscale_send_u32(target, 0x62);\r
-               xscale_send_u32(target, 0x31);\r
-       }\r
-       else\r
-               xscale_send_u32(target, 0x30);\r
-\r
-       /* send CPSR */\r
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));\r
-       DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));\r
-\r
-       for (i = 7; i >= 0; i--)\r
-       {\r
-               /* send register */\r
-               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));\r
-               DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));\r
-       }\r
-\r
-       /* send PC */\r
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));\r
-       DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));\r
-\r
-       target->debug_reason = DBG_REASON_NOTHALTED;\r
-\r
-       if (!debug_execution)\r
-       {\r
-               /* registers are now invalid */\r
-               armv4_5_invalidate_core_regs(target);\r
-               target->state = TARGET_RUNNING;\r
-               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);\r
-       }\r
-       else\r
-       {\r
-               target->state = TARGET_DEBUG_RUNNING;\r
-               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);\r
-       }\r
-\r
-       DEBUG("target resumed");\r
-\r
-       xscale->handler_running = 1;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       breakpoint_t *breakpoint = target->breakpoints;\r
-\r
-       u32 current_pc, next_pc;\r
-       int i;\r
-       int retval;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       /* current = 1: continue on current pc, otherwise continue at <address> */\r
-       if (!current)\r
-               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);\r
-\r
-       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-\r
-       /* if we're at the reset vector, we have to simulate the step */\r
-       if (current_pc == 0x0)\r
-       {\r
-               arm_simulate_step(target, NULL);\r
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-\r
-               target->debug_reason = DBG_REASON_SINGLESTEP;\r
-               target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
-\r
-               return ERROR_OK;\r
-       }\r
-\r
-       /* the front-end may request us not to handle breakpoints */\r
-       if (handle_breakpoints)\r
-               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))\r
-               {\r
-                       xscale_unset_breakpoint(target, breakpoint);\r
-               }\r
-\r
-       target->debug_reason = DBG_REASON_SINGLESTEP;\r
-\r
-       /* calculate PC of next instruction */\r
-       if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)\r
-       {\r
-               u32 current_opcode;\r
-               target_read_u32(target, current_pc, &current_opcode);\r
-               ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);\r
-       }\r
-\r
-       DEBUG("enable single-step");\r
-       xscale_enable_single_step(target, next_pc);\r
-\r
-       /* restore banked registers */\r
-       xscale_restore_context(target);\r
-\r
-       /* send resume request (command 0x30 or 0x31)\r
-        * clean the trace buffer if it is to be enabled (0x62) */\r
-       if (xscale->trace.buffer_enabled)\r
-       {\r
-               xscale_send_u32(target, 0x62);\r
-               xscale_send_u32(target, 0x31);\r
-       }\r
-       else\r
-               xscale_send_u32(target, 0x30);\r
-\r
-       /* send CPSR */\r
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));\r
-       DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));\r
-\r
-       for (i = 7; i >= 0; i--)\r
-       {\r
-               /* send register */\r
-               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));\r
-               DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));\r
-       }\r
-\r
-       /* send PC */\r
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));\r
-       DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));\r
-\r
-       target_call_event_callbacks(target, TARGET_EVENT_RESUMED);\r
-\r
-       /* registers are now invalid */\r
-       armv4_5_invalidate_core_regs(target);\r
-\r
-       /* wait for and process debug entry */\r
-       xscale_debug_entry(target);\r
-\r
-       DEBUG("disable single-step");\r
-       xscale_disable_single_step(target);\r
-\r
-       target_call_event_callbacks(target, TARGET_EVENT_HALTED);\r
-\r
-       if (breakpoint)\r
-       {\r
-               xscale_set_breakpoint(target, breakpoint);\r
-       }\r
-\r
-       DEBUG("target stepped");\r
-\r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int xscale_assert_reset(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       DEBUG("target->state: %s", target_state_strings[target->state]);\r
-\r
-       /* select DCSR instruction (set endstate to R-T-I to ensure we don't\r
-        * end up in T-L-R, which would reset JTAG\r
-        */\r
-       jtag_add_end_state(TAP_RTI);\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);\r
-\r
-       /* set Hold reset, Halt mode and Trap Reset */\r
-       buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);\r
-       buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);\r
-       xscale_write_dcsr(target, 1, 0);\r
-\r
-       /* select BYPASS, because having DCSR selected caused problems on the PXA27x */\r
-       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, 0x7f);\r
-       jtag_execute_queue();\r
-\r
-       /* assert reset */\r
-       jtag_add_reset(0, 1);\r
-\r
-       /* sleep 1ms, to be sure we fulfill any requirements */\r
-       jtag_add_sleep(1000);\r
-       jtag_execute_queue();\r
-\r
-       target->state = TARGET_RESET;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_deassert_reset(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       fileio_t debug_handler;\r
-       u32 address;\r
-       u32 binary_size;\r
-\r
-       u32 buf_cnt;\r
-       int i;\r
-       int retval;\r
-\r
-       breakpoint_t *breakpoint = target->breakpoints;\r
-\r
-       DEBUG("-");\r
-\r
-       xscale->ibcr_available = 2;\r
-       xscale->ibcr0_used = 0;\r
-       xscale->ibcr1_used = 0;\r
-\r
-       xscale->dbr_available = 2;\r
-       xscale->dbr0_used = 0;\r
-       xscale->dbr1_used = 0;\r
-\r
-       /* mark all hardware breakpoints as unset */\r
-       while (breakpoint)\r
-       {\r
-               if (breakpoint->type == BKPT_HARD)\r
-               {\r
-                       breakpoint->set = 0;\r
-               }\r
-               breakpoint = breakpoint->next;\r
-       }\r
-\r
-       if (!xscale->handler_installed)\r
-       {\r
-               /* release SRST */\r
-               jtag_add_reset(0, 0);\r
-\r
-               /* wait 300ms; 150 and 100ms were not enough */\r
-               jtag_add_sleep(300*1000);\r
-\r
-               jtag_add_runtest(2030, TAP_RTI);\r
-               jtag_execute_queue();\r
-\r
-               /* set Hold reset, Halt mode and Trap Reset */\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);\r
-               xscale_write_dcsr(target, 1, 0);\r
-\r
-               /* Load debug handler */\r
-               if (fileio_open(&debug_handler, PKGLIBDIR "/xscale/debug_handler.bin", FILEIO_READ, FILEIO_BINARY) != ERROR_OK)\r
-               {\r
-                       ERROR("file open error: %s", debug_handler.error_str);\r
-                       return ERROR_OK;\r
-               }\r
-\r
-               if ((binary_size = debug_handler.size) % 4)\r
-               {\r
-                       ERROR("debug_handler.bin: size not a multiple of 4");\r
-                       exit(-1);\r
-               }\r
-\r
-               if (binary_size > 0x800)\r
-               {\r
-                       ERROR("debug_handler.bin: larger than 2kb");\r
-                       exit(-1);\r
-               }\r
-\r
-               binary_size = CEIL(binary_size, 32) * 32;\r
-\r
-               address = xscale->handler_address;\r
-               while (binary_size > 0)\r
-               {\r
-                       u32 cache_line[8];\r
-                       u8 buffer[32];\r
-\r
-                       if ((retval = fileio_read(&debug_handler, 32, buffer, &buf_cnt)) != ERROR_OK)\r
-                       {\r
-                               ERROR("reading debug handler failed: %s", debug_handler.error_str);\r
-                       }\r
-\r
-                       for (i = 0; i < buf_cnt; i += 4)\r
-                       {\r
-                               /* convert LE buffer to host-endian u32 */\r
-                               cache_line[i / 4] = le_to_h_u32(&buffer[i]);\r
-                       }\r
-\r
-                       for (; buf_cnt < 32; buf_cnt += 4)\r
-                       {\r
-                                       cache_line[buf_cnt / 4] = 0xe1a08008;\r
-                       }\r
-\r
-                       /* only load addresses other than the reset vectors */\r
-                       if ((address % 0x400) != 0x0)\r
-                       {\r
-                               xscale_load_ic(target, 1, address, cache_line);\r
-                       }\r
-\r
-                       address += buf_cnt;\r
-                       binary_size -= buf_cnt;\r
-               };\r
-\r
-               xscale_load_ic(target, 1, 0x0, xscale->low_vectors);\r
-               xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);\r
-\r
-               jtag_add_runtest(30, TAP_RTI);\r
-\r
-               jtag_add_sleep(100000);\r
-\r
-               /* set Hold reset, Halt mode and Trap Reset */\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);\r
-               xscale_write_dcsr(target, 1, 0);\r
-\r
-               /* clear Hold reset to let the target run (should enter debug handler) */\r
-               xscale_write_dcsr(target, 0, 1);\r
-               target->state = TARGET_RUNNING;\r
-\r
-               if ((target->reset_mode != RESET_HALT) && (target->reset_mode != RESET_INIT))\r
-               {\r
-                       jtag_add_sleep(10000);\r
-\r
-                       /* we should have entered debug now */\r
-                       xscale_debug_entry(target);\r
-                       target->state = TARGET_HALTED;\r
-\r
-                       /* resume the target */\r
-                       xscale_resume(target, 1, 0x0, 1, 0);\r
-               }\r
-\r
-               fileio_close(&debug_handler);\r
-       }\r
-       else\r
-       {\r
-               jtag_add_reset(0, 0);\r
-       }\r
-\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_soft_reset_halt(struct target_s *target)\r
-{\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_prepare_reset_halt(struct target_s *target)\r
-{\r
-       /* nothing to be done for reset_halt on XScale targets\r
-        * we always halt after a reset to upload the debug handler\r
-        */\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)\r
-{\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value)\r
-{\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_full_context(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-\r
-       u32 *buffer;\r
-\r
-       int i, j;\r
-\r
-       DEBUG("-");\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       buffer = malloc(4 * 8);\r
-\r
-       /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)\r
-        * we can't enter User mode on an XScale (unpredictable),\r
-        * but User shares registers with SYS\r
-        */\r
-       for(i = 1; i < 7; i++)\r
-       {\r
-               int valid = 1;\r
-\r
-               /* check if there are invalid registers in the current mode\r
-                */\r
-               for (j = 0; j <= 16; j++)\r
-               {\r
-                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid == 0)\r
-                               valid = 0;\r
-               }\r
-\r
-               if (!valid)\r
-               {\r
-                       u32 tmp_cpsr;\r
-\r
-                       /* request banked registers */\r
-                       xscale_send_u32(target, 0x0);\r
-\r
-                       tmp_cpsr = 0x0;\r
-                       tmp_cpsr |= armv4_5_number_to_mode(i);\r
-                       tmp_cpsr |= 0xc0; /* I/F bits */\r
-\r
-                       /* send CPSR for desired mode */\r
-                       xscale_send_u32(target, tmp_cpsr);\r
-\r
-                       /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */\r
-                       if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))\r
-                       {\r
-                               xscale_receive(target, buffer, 8);\r
-                               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);\r
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;\r
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).valid = 1;\r
-                       }\r
-                       else\r
-                       {\r
-                               xscale_receive(target, buffer, 7);\r
-                       }\r
-\r
-                       /* move data from buffer to register cache */\r
-                       for (j = 8; j <= 14; j++)\r
-                       {\r
-                               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).value, 0, 32, buffer[j - 8]);\r
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;\r
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid = 1;\r
-                       }\r
-               }\r
-       }\r
-\r
-       free(buffer);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_restore_context(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-\r
-       int i, j;\r
-\r
-       DEBUG("-");\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)\r
-       * we can't enter User mode on an XScale (unpredictable),\r
-       * but User shares registers with SYS\r
-       */\r
-       for(i = 1; i < 7; i++)\r
-       {\r
-               int dirty = 0;\r
-\r
-               /* check if there are invalid registers in the current mode\r
-               */\r
-               for (j = 8; j <= 14; j++)\r
-               {\r
-                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty == 1)\r
-                               dirty = 1;\r
-               }\r
-\r
-               /* if not USR/SYS, check if the SPSR needs to be written */\r
-               if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))\r
-               {\r
-                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty == 1)\r
-                               dirty = 1;\r
-               }\r
-\r
-               if (dirty)\r
-               {\r
-                       u32 tmp_cpsr;\r
-\r
-                       /* send banked registers */\r
-                       xscale_send_u32(target, 0x1);\r
-\r
-                       tmp_cpsr = 0x0;\r
-                       tmp_cpsr |= armv4_5_number_to_mode(i);\r
-                       tmp_cpsr |= 0xc0; /* I/F bits */\r
-\r
-                       /* send CPSR for desired mode */\r
-                       xscale_send_u32(target, tmp_cpsr);\r
-\r
-                       /* send banked registers, r8 to r14, and spsr if not in USR/SYS mode */\r
-                       for (j = 8; j <= 14; j++)\r
-                       {\r
-                               xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, j).value, 0, 32));\r
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;\r
-                       }\r
-\r
-                       if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))\r
-                       {\r
-                               xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32));\r
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u32 *buf32;\r
-       int i;\r
-\r
-       DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       /* sanitize arguments */\r
-       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))\r
-               return ERROR_INVALID_ARGUMENTS;\r
-\r
-       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))\r
-               return ERROR_TARGET_UNALIGNED_ACCESS;\r
-\r
-       /* send memory read request (command 0x1n, n: access size) */\r
-       xscale_send_u32(target, 0x10 | size);\r
-\r
-       /* send base address for read request */\r
-       xscale_send_u32(target, address);\r
-\r
-       /* send number of requested data words */\r
-       xscale_send_u32(target, count);\r
-\r
-       /* receive data from target (count times 32-bit words in host endianness) */\r
-       buf32 = malloc(4 * count);\r
-       xscale_receive(target, buf32, count);\r
-\r
-       /* extract data from host-endian buffer into byte stream */\r
-       for (i = 0; i < count; i++)\r
-       {\r
-               switch (size)\r
-               {\r
-                       case 4:\r
-                               target_buffer_set_u32(target, buffer, buf32[i]);\r
-                               buffer += 4;\r
-                               break;\r
-                       case 2:\r
-                               target_buffer_set_u16(target, buffer, buf32[i] & 0xffff);\r
-                               buffer += 2;\r
-                               break;\r
-                       case 1:\r
-                               *buffer++ = buf32[i] & 0xff;\r
-                               break;\r
-                       default:\r
-                               ERROR("should never get here");\r
-                               exit(-1);\r
-               }\r
-       }\r
-\r
-       free(buf32);\r
-\r
-       /* examine DCSR, to see if Sticky Abort (SA) got set */\r
-       xscale_read_dcsr(target);\r
-       if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)\r
-       {\r
-               /* clear SA bit */\r
-               xscale_send_u32(target, 0x60);\r
-\r
-               return ERROR_TARGET_DATA_ABORT;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       /* sanitize arguments */\r
-       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))\r
-               return ERROR_INVALID_ARGUMENTS;\r
-\r
-       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))\r
-               return ERROR_TARGET_UNALIGNED_ACCESS;\r
-\r
-       /* send memory write request (command 0x2n, n: access size) */\r
-       xscale_send_u32(target, 0x20 | size);\r
-\r
-       /* send base address for read request */\r
-       xscale_send_u32(target, address);\r
-\r
-       /* send number of requested data words to be written*/\r
-       xscale_send_u32(target, count);\r
-\r
-       /* extract data from host-endian buffer into byte stream */\r
-#if 0\r
-       for (i = 0; i < count; i++)\r
-       {\r
-               switch (size)\r
-               {\r
-                       case 4:\r
-                               value = target_buffer_get_u32(target, buffer);\r
-                               xscale_send_u32(target, value);\r
-                               buffer += 4;\r
-                               break;\r
-                       case 2:\r
-                               value = target_buffer_get_u16(target, buffer);\r
-                               xscale_send_u32(target, value);\r
-                               buffer += 2;\r
-                               break;\r
-                       case 1:\r
-                               value = *buffer;\r
-                               xscale_send_u32(target, value);\r
-                               buffer += 1;\r
-                               break;\r
-                       default:\r
-                               ERROR("should never get here");\r
-                               exit(-1);\r
-               }\r
-       }\r
-#endif\r
-       xscale_send(target, buffer, count, size);\r
-\r
-       /* examine DCSR, to see if Sticky Abort (SA) got set */\r
-       xscale_read_dcsr(target);\r
-       if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)\r
-       {\r
-               /* clear SA bit */\r
-               xscale_send_u32(target, 0x60);\r
-\r
-               return ERROR_TARGET_DATA_ABORT;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)\r
-{\r
-       return xscale_write_memory(target, address, 4, count, buffer);\r
-}\r
-\r
-int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)\r
-{\r
-       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-}\r
-\r
-u32 xscale_get_ttb(target_t *target)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u32 ttb;\r
-\r
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]);\r
-       ttb = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_TTB].value, 0, 32);\r
-\r
-       return ttb;\r
-}\r
-\r
-void xscale_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);\r
-       cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);\r
-\r
-       if (mmu)\r
-               cp15_control &= ~0x1U;\r
-\r
-       if (d_u_cache)\r
-       {\r
-               /* clean DCache */\r
-               xscale_send_u32(target, 0x50);\r
-               xscale_send_u32(target, xscale->cache_clean_address);\r
-\r
-               /* invalidate DCache */\r
-               xscale_send_u32(target, 0x51);\r
-\r
-               cp15_control &= ~0x4U;\r
-       }\r
-\r
-       if (i_cache)\r
-       {\r
-               /* invalidate ICache */\r
-               xscale_send_u32(target, 0x52);\r
-               cp15_control &= ~0x1000U;\r
-       }\r
-\r
-       /* write new cp15 control register */\r
-       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);\r
-\r
-       /* execute cpwait to ensure outstanding operations complete */\r
-       xscale_send_u32(target, 0x53);\r
-}\r
-\r
-void xscale_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u32 cp15_control;\r
-\r
-       /* read cp15 control register */\r
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);\r
-       cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);\r
-\r
-       if (mmu)\r
-               cp15_control |= 0x1U;\r
-\r
-       if (d_u_cache)\r
-               cp15_control |= 0x4U;\r
-\r
-       if (i_cache)\r
-               cp15_control |= 0x1000U;\r
-\r
-       /* write new cp15 control register */\r
-       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);\r
-\r
-       /* execute cpwait to ensure outstanding operations complete */\r
-       xscale_send_u32(target, 0x53);\r
-}\r
-\r
-int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (xscale->force_hw_bkpts)\r
-               breakpoint->type = BKPT_HARD;\r
-\r
-       if (breakpoint->set)\r
-       {\r
-               WARNING("breakpoint already set");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (breakpoint->type == BKPT_HARD)\r
-       {\r
-               u32 value = breakpoint->address | 1;\r
-               if (!xscale->ibcr0_used)\r
-               {\r
-                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value);\r
-                       xscale->ibcr0_used = 1;\r
-                       breakpoint->set = 1;    /* breakpoint set on first breakpoint register */\r
-               }\r
-               else if (!xscale->ibcr1_used)\r
-               {\r
-                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value);\r
-                       xscale->ibcr1_used = 1;\r
-                       breakpoint->set = 2;    /* breakpoint set on second breakpoint register */\r
-               }\r
-               else\r
-               {\r
-                       ERROR("BUG: no hardware comparator available");\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       else if (breakpoint->type == BKPT_SOFT)\r
-       {\r
-               if (breakpoint->length == 4)\r
-               {\r
-                       /* keep the original instruction in target endianness */\r
-                       target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);\r
-                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */\r
-                       target_write_u32(target, breakpoint->address, xscale->arm_bkpt);\r
-               }\r
-               else\r
-               {\r
-                       /* keep the original instruction in target endianness */\r
-                       target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);\r
-                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */\r
-                       target_write_u32(target, breakpoint->address, xscale->thumb_bkpt);\r
-               }\r
-               breakpoint->set = 1;\r
-       }\r
-\r
-       return ERROR_OK;\r
-\r
-}\r
-\r
-int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (xscale->force_hw_bkpts)\r
-       {\r
-               DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);\r
-               breakpoint->type = BKPT_HARD;\r
-       }\r
-\r
-       if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1))\r
-       {\r
-               INFO("no breakpoint unit available for hardware breakpoint");\r
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-       }\r
-       else\r
-       {\r
-               xscale->ibcr_available--;\r
-       }\r
-\r
-       if ((breakpoint->length != 2) && (breakpoint->length != 4))\r
-       {\r
-               INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");\r
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (!breakpoint->set)\r
-       {\r
-               WARNING("breakpoint not set");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (breakpoint->type == BKPT_HARD)\r
-       {\r
-               if (breakpoint->set == 1)\r
-               {\r
-                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0);\r
-                       xscale->ibcr0_used = 0;\r
-               }\r
-               else if (breakpoint->set == 2)\r
-               {\r
-                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0);\r
-                       xscale->ibcr1_used = 0;\r
-               }\r
-               breakpoint->set = 0;\r
-       }\r
-       else\r
-       {\r
-               /* restore original instruction (kept in target endianness) */\r
-               if (breakpoint->length == 4)\r
-               {\r
-                       target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);\r
-               }\r
-               else\r
-               {\r
-                       target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);\r
-               }\r
-               breakpoint->set = 0;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (breakpoint->set)\r
-       {\r
-               xscale_unset_breakpoint(target, breakpoint);\r
-       }\r
-\r
-       if (breakpoint->type == BKPT_HARD)\r
-               xscale->ibcr_available++;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u8 enable = 0;\r
-       reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];\r
-       u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       xscale_get_reg(dbcon);\r
-\r
-       switch (watchpoint->rw)\r
-       {\r
-               case WPT_READ:\r
-                       enable = 0x3;\r
-                       break;\r
-               case WPT_ACCESS:\r
-                       enable = 0x2;\r
-                       break;\r
-               case WPT_WRITE:\r
-                       enable = 0x1;\r
-                       break;\r
-               default:\r
-                       ERROR("BUG: watchpoint->rw neither read, write nor access");\r
-       }\r
-\r
-       if (!xscale->dbr0_used)\r
-       {\r
-               xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address);\r
-               dbcon_value |= enable;\r
-               xscale_set_reg_u32(dbcon, dbcon_value);\r
-               watchpoint->set = 1;\r
-               xscale->dbr0_used = 1;\r
-       }\r
-       else if (!xscale->dbr1_used)\r
-       {\r
-               xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address);\r
-               dbcon_value |= enable << 2;\r
-               xscale_set_reg_u32(dbcon, dbcon_value);\r
-               watchpoint->set = 2;\r
-               xscale->dbr1_used = 1;\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: no hardware comparator available");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (xscale->dbr_available < 1)\r
-       {\r
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-       }\r
-\r
-       if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))\r
-       {\r
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;\r
-       }\r
-\r
-       xscale->dbr_available--;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];\r
-       u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (!watchpoint->set)\r
-       {\r
-               WARNING("breakpoint not set");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (watchpoint->set == 1)\r
-       {\r
-               dbcon_value &= ~0x3;\r
-               xscale_set_reg_u32(dbcon, dbcon_value);\r
-               xscale->dbr0_used = 0;\r
-       }\r
-       else if (watchpoint->set == 2)\r
-       {\r
-               dbcon_value &= ~0xc;\r
-               xscale_set_reg_u32(dbcon, dbcon_value);\r
-               xscale->dbr1_used = 0;\r
-       }\r
-       watchpoint->set = 0;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target not halted");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       if (watchpoint->set)\r
-       {\r
-               xscale_unset_watchpoint(target, watchpoint);\r
-       }\r
-\r
-       xscale->dbr_available++;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void xscale_enable_watchpoints(struct target_s *target)\r
-{\r
-       watchpoint_t *watchpoint = target->watchpoints;\r
-\r
-       while (watchpoint)\r
-       {\r
-               if (watchpoint->set == 0)\r
-                       xscale_set_watchpoint(target, watchpoint);\r
-               watchpoint = watchpoint->next;\r
-       }\r
-}\r
-\r
-void xscale_enable_breakpoints(struct target_s *target)\r
-{\r
-       breakpoint_t *breakpoint = target->breakpoints;\r
-\r
-       /* set any pending breakpoints */\r
-       while (breakpoint)\r
-       {\r
-               if (breakpoint->set == 0)\r
-                       xscale_set_breakpoint(target, breakpoint);\r
-               breakpoint = breakpoint->next;\r
-       }\r
-}\r
-\r
-int xscale_get_reg(reg_t *reg)\r
-{\r
-       xscale_reg_t *arch_info = reg->arch_info;\r
-       target_t *target = arch_info->target;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       /* DCSR, TX and RX are accessible via JTAG */\r
-       if (strcmp(reg->name, "XSCALE_DCSR") == 0)\r
-       {\r
-               return xscale_read_dcsr(arch_info->target);\r
-       }\r
-       else if (strcmp(reg->name, "XSCALE_TX") == 0)\r
-       {\r
-               /* 1 = consume register content */\r
-               return xscale_read_tx(arch_info->target, 1);\r
-       }\r
-       else if (strcmp(reg->name, "XSCALE_RX") == 0)\r
-       {\r
-               /* can't read from RX register (host -> debug handler) */\r
-               return ERROR_OK;\r
-       }\r
-       else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0)\r
-       {\r
-               /* can't (explicitly) read from TXRXCTRL register */\r
-               return ERROR_OK;\r
-       }\r
-       else /* Other DBG registers have to be transfered by the debug handler */\r
-       {\r
-               /* send CP read request (command 0x40) */\r
-               xscale_send_u32(target, 0x40);\r
-\r
-               /* send CP register number */\r
-               xscale_send_u32(target, arch_info->dbg_handler_number);\r
-\r
-               /* read register value */\r
-               xscale_read_tx(target, 1);\r
-               buf_cpy(xscale->reg_cache->reg_list[XSCALE_TX].value, reg->value, 32);\r
-\r
-               reg->dirty = 0;\r
-               reg->valid = 1;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_set_reg(reg_t *reg, u8* buf)\r
-{\r
-       xscale_reg_t *arch_info = reg->arch_info;\r
-       target_t *target = arch_info->target;\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       u32 value = buf_get_u32(buf, 0, 32);\r
-\r
-       /* DCSR, TX and RX are accessible via JTAG */\r
-       if (strcmp(reg->name, "XSCALE_DCSR") == 0)\r
-       {\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32, value);\r
-               return xscale_write_dcsr(arch_info->target, -1, -1);\r
-       }\r
-       else if (strcmp(reg->name, "XSCALE_RX") == 0)\r
-       {\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);\r
-               return xscale_write_rx(arch_info->target);\r
-       }\r
-       else if (strcmp(reg->name, "XSCALE_TX") == 0)\r
-       {\r
-               /* can't write to TX register (debug-handler -> host) */\r
-               return ERROR_OK;\r
-       }\r
-       else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0)\r
-       {\r
-               /* can't (explicitly) write to TXRXCTRL register */\r
-               return ERROR_OK;\r
-       }\r
-       else /* Other DBG registers have to be transfered by the debug handler */\r
-       {\r
-               /* send CP write request (command 0x41) */\r
-               xscale_send_u32(target, 0x41);\r
-\r
-               /* send CP register number */\r
-               xscale_send_u32(target, arch_info->dbg_handler_number);\r
-\r
-               /* send CP register value */\r
-               xscale_send_u32(target, value);\r
-               buf_set_u32(reg->value, 0, 32, value);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* convenience wrapper to access XScale specific registers */\r
-int xscale_set_reg_u32(reg_t *reg, u32 value)\r
-{\r
-       u8 buf[4];\r
-\r
-       buf_set_u32(buf, 0, 32, value);\r
-\r
-       return xscale_set_reg(reg, buf);\r
-}\r
-\r
-int xscale_write_dcsr_sw(target_t *target, u32 value)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       reg_t *dcsr = &xscale->reg_cache->reg_list[XSCALE_DCSR];\r
-       xscale_reg_t *dcsr_arch_info = dcsr->arch_info;\r
-\r
-       /* send CP write request (command 0x41) */\r
-       xscale_send_u32(target, 0x41);\r
-\r
-       /* send CP register number */\r
-       xscale_send_u32(target, dcsr_arch_info->dbg_handler_number);\r
-\r
-       /* send CP register value */\r
-       xscale_send_u32(target, value);\r
-       buf_set_u32(dcsr->value, 0, 32, value);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_read_trace(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       xscale_trace_data_t **trace_data_p;\r
-\r
-       /* 258 words from debug handler\r
-        * 256 trace buffer entries\r
-        * 2 checkpoint addresses\r
-        */\r
-       u32 trace_buffer[258];\r
-       int is_address[256];\r
-       int i, j;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               WARNING("target must be stopped to read trace data");\r
-               return ERROR_TARGET_NOT_HALTED;\r
-       }\r
-\r
-       /* send read trace buffer command (command 0x61) */\r
-       xscale_send_u32(target, 0x61);\r
-\r
-       /* receive trace buffer content */\r
-       xscale_receive(target, trace_buffer, 258);\r
-\r
-       /* parse buffer backwards to identify address entries */\r
-       for (i = 255; i >= 0; i--)\r
-       {\r
-               is_address[i] = 0;\r
-               if (((trace_buffer[i] & 0xf0) == 0x90) ||\r
-                       ((trace_buffer[i] & 0xf0) == 0xd0))\r
-               {\r
-                       if (i >= 3)\r
-                               is_address[--i] = 1;\r
-                       if (i >= 2)\r
-                               is_address[--i] = 1;\r
-                       if (i >= 1)\r
-                               is_address[--i] = 1;\r
-                       if (i >= 0)\r
-                               is_address[--i] = 1;\r
-               }\r
-       }\r
-\r
-\r
-       /* search first non-zero entry */\r
-       for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)\r
-               ;\r
-\r
-       if (j == 256)\r
-       {\r
-               DEBUG("no trace data collected");\r
-               return ERROR_XSCALE_NO_TRACE_DATA;\r
-       }\r
-\r
-       for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next)\r
-               ;\r
-\r
-       *trace_data_p = malloc(sizeof(xscale_trace_data_t));\r
-       (*trace_data_p)->next = NULL;\r
-       (*trace_data_p)->chkpt0 = trace_buffer[256];\r
-       (*trace_data_p)->chkpt1 = trace_buffer[257];\r
-       (*trace_data_p)->last_instruction = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-       (*trace_data_p)->entries = malloc(sizeof(xscale_trace_entry_t) * (256 - j));\r
-       (*trace_data_p)->depth = 256 - j;\r
-\r
-       for (i = j; i < 256; i++)\r
-       {\r
-               (*trace_data_p)->entries[i - j].data = trace_buffer[i];\r
-               if (is_address[i])\r
-                       (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS;\r
-               else\r
-                       (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       int i;\r
-       int section = -1;\r
-       u32 size_read;\r
-       u32 opcode;\r
-       int retval;\r
-\r
-       if (!xscale->trace.image)\r
-               return ERROR_TRACE_IMAGE_UNAVAILABLE;\r
-\r
-       /* search for the section the current instruction belongs to */\r
-       for (i = 0; i < xscale->trace.image->num_sections; i++)\r
-       {\r
-               if ((xscale->trace.image->sections[i].base_address <= xscale->trace.current_pc) &&\r
-                       (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > xscale->trace.current_pc))\r
-               {\r
-                       section = i;\r
-                       break;\r
-               }\r
-       }\r
-\r
-       if (section == -1)\r
-       {\r
-               /* current instruction couldn't be found in the image */\r
-               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-       }\r
-\r
-       if (xscale->trace.core_state == ARMV4_5_STATE_ARM)\r
-       {\r
-               u8 buf[4];\r
-               if ((retval = image_read_section(xscale->trace.image, section,\r
-                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,\r
-                       4, buf, &size_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("error while reading instruction: %i", retval);\r
-                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-               }\r
-               opcode = target_buffer_get_u32(target, buf);\r
-               arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);\r
-       }\r
-       else if (xscale->trace.core_state == ARMV4_5_STATE_THUMB)\r
-       {\r
-               u8 buf[2];\r
-               if ((retval = image_read_section(xscale->trace.image, section,\r
-                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,\r
-                       2, buf, &size_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("error while reading instruction: %i", retval);\r
-                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-               }\r
-               opcode = target_buffer_get_u16(target, buf);\r
-               thumb_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: unknown core state encountered");\r
-               exit(-1);\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_branch_address(xscale_trace_data_t *trace_data, int i, u32 *target)\r
-{\r
-       /* if there are less than four entries prior to the indirect branch message\r
-        * we can't extract the address */\r
-       if (i < 4)\r
-       {\r
-               return -1;\r
-       }\r
-\r
-       *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |\r
-                               (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);\r
-\r
-       return 0;\r
-}\r
-\r
-int xscale_analyze_trace(target_t *target, command_context_t *cmd_ctx)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-       int next_pc_ok = 0;\r
-       u32 next_pc = 0x0;\r
-       xscale_trace_data_t *trace_data = xscale->trace.data;\r
-       int retval;\r
-\r
-       while (trace_data)\r
-       {\r
-               int i, chkpt;\r
-               int rollover;\r
-               int branch;\r
-               int exception;\r
-               xscale->trace.core_state = ARMV4_5_STATE_ARM;\r
-\r
-               chkpt = 0;\r
-               rollover = 0;\r
-\r
-               for (i = 0; i < trace_data->depth; i++)\r
-               {\r
-                       next_pc_ok = 0;\r
-                       branch = 0;\r
-                       exception = 0;\r
-\r
-                       if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)\r
-                               continue;\r
-\r
-                       switch ((trace_data->entries[i].data & 0xf0) >> 4)\r
-                       {\r
-                               case 0:         /* Exceptions */\r
-                               case 1:\r
-                               case 2:\r
-                               case 3:\r
-                               case 4:\r
-                               case 5:\r
-                               case 6:\r
-                               case 7:\r
-                                       exception = (trace_data->entries[i].data & 0x70) >> 4;\r
-                                       next_pc_ok = 1;\r
-                                       next_pc = (trace_data->entries[i].data & 0xf0) >> 2;\r
-                                       command_print(cmd_ctx, "--- exception %i ---", (trace_data->entries[i].data & 0xf0) >> 4);\r
-                                       break;\r
-                               case 8:         /* Direct Branch */\r
-                                       branch = 1;\r
-                                       break;\r
-                               case 9:         /* Indirect Branch */\r
-                                       branch = 1;\r
-                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)\r
-                                       {\r
-                                               next_pc_ok = 1;\r
-                                       }\r
-                                       break;\r
-                               case 13:        /* Checkpointed Indirect Branch */\r
-                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)\r
-                                       {\r
-                                               next_pc_ok = 1;\r
-                                               if (((chkpt == 0) && (next_pc != trace_data->chkpt0))\r
-                                                       || ((chkpt == 1) && (next_pc != trace_data->chkpt1)))\r
-                                                       WARNING("checkpointed indirect branch target address doesn't match checkpoint");\r
-                                       }\r
-                                       /* explicit fall-through */\r
-                               case 12:        /* Checkpointed Direct Branch */\r
-                                       branch = 1;\r
-                                       if (chkpt == 0)\r
-                                       {\r
-                                               next_pc_ok = 1;\r
-                                               next_pc = trace_data->chkpt0;\r
-                                               chkpt++;\r
-                                       }\r
-                                       else if (chkpt == 1)\r
-                                       {\r
-                                               next_pc_ok = 1;\r
-                                               next_pc = trace_data->chkpt0;\r
-                                               chkpt++;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               WARNING("more than two checkpointed branches encountered");\r
-                                       }\r
-                                       break;\r
-                               case 15:        /* Roll-over */\r
-                                       rollover++;\r
-                                       continue;\r
-                               default:        /* Reserved */\r
-                                       command_print(cmd_ctx, "--- reserved trace message ---");\r
-                                       ERROR("BUG: trace message %i is reserved", (trace_data->entries[i].data & 0xf0) >> 4);\r
-                                       return ERROR_OK;\r
-                       }\r
-\r
-                       if (xscale->trace.pc_ok)\r
-                       {\r
-                               int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;\r
-                               arm_instruction_t instruction;\r
-\r
-                               if ((exception == 6) || (exception == 7))\r
-                               {\r
-                                       /* IRQ or FIQ exception, no instruction executed */\r
-                                       executed -= 1;\r
-                               }\r
-\r
-                               while (executed-- >= 0)\r
-                               {\r
-                                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)\r
-                                       {\r
-                                               /* can't continue tracing with no image available */\r
-                                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)\r
-                                               {\r
-                                                       return retval;\r
-                                               }\r
-                                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)\r
-                                               {\r
-                                                       /* TODO: handle incomplete images */\r
-                                               }\r
-                                       }\r
-\r
-                                       /* a precise abort on a load to the PC is included in the incremental\r
-                                        * word count, other instructions causing data aborts are not included\r
-                                        */\r
-                                       if ((executed == 0) && (exception == 4)\r
-                                               && ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDM)))\r
-                                       {\r
-                                               if ((instruction.type == ARM_LDM)\r
-                                                       && ((instruction.info.load_store_multiple.register_list & 0x8000) == 0))\r
-                                               {\r
-                                                       executed--;\r
-                                               }\r
-                                               else if (((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))\r
-                                                       && (instruction.info.load_store.Rd != 15))\r
-                                               {\r
-                                                       executed--;\r
-                                               }\r
-                                       }\r
-\r
-                                       /* only the last instruction executed\r
-                                        * (the one that caused the control flow change)\r
-                                        * could be a taken branch\r
-                                        */\r
-                                       if (((executed == -1) && (branch == 1)) &&\r
-                                               (((instruction.type == ARM_B) ||\r
-                                                       (instruction.type == ARM_BL) ||\r
-                                                       (instruction.type == ARM_BLX)) &&\r
-                                                       (instruction.info.b_bl_bx_blx.target_address != -1)))\r
-                                       {\r
-                                               xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
-                                       }\r
-                                       command_print(cmd_ctx, "%s", instruction.text);\r
-                               }\r
-\r
-                               rollover = 0;\r
-                       }\r
-\r
-                       if (next_pc_ok)\r
-                       {\r
-                               xscale->trace.current_pc = next_pc;\r
-                               xscale->trace.pc_ok = 1;\r
-                       }\r
-               }\r
-\r
-               for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)\r
-               {\r
-                       arm_instruction_t instruction;\r
-                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)\r
-                       {\r
-                               /* can't continue tracing with no image available */\r
-                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)\r
-                               {\r
-                                       return retval;\r
-                               }\r
-                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)\r
-                               {\r
-                                       /* TODO: handle incomplete images */\r
-                               }\r
-                       }\r
-                       command_print(cmd_ctx, "%s", instruction.text);\r
-               }\r
-\r
-               trace_data = trace_data->next;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-void xscale_build_reg_cache(target_t *target)\r
-{\r
-       /* get pointers to arch-specific information */\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);\r
-       xscale_reg_t *arch_info = malloc(sizeof(xscale_reg_arch_info));\r
-       int i;\r
-       int num_regs = sizeof(xscale_reg_arch_info) / sizeof(xscale_reg_t);\r
-\r
-       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);\r
-       armv4_5->core_cache = (*cache_p);\r
-\r
-       /* register a register arch-type for XScale dbg registers only once */\r
-       if (xscale_reg_arch_type == -1)\r
-               xscale_reg_arch_type = register_reg_arch_type(xscale_get_reg, xscale_set_reg);\r
-\r
-       (*cache_p)->next = malloc(sizeof(reg_cache_t));\r
-       cache_p = &(*cache_p)->next;\r
-\r
-       /* fill in values for the xscale reg cache */\r
-       (*cache_p)->name = "XScale registers";\r
-       (*cache_p)->next = NULL;\r
-       (*cache_p)->reg_list = malloc(num_regs * sizeof(reg_t));\r
-       (*cache_p)->num_regs = num_regs;\r
-\r
-       for (i = 0; i < num_regs; i++)\r
-       {\r
-               (*cache_p)->reg_list[i].name = xscale_reg_list[i];\r
-               (*cache_p)->reg_list[i].value = calloc(4, 1);\r
-               (*cache_p)->reg_list[i].dirty = 0;\r
-               (*cache_p)->reg_list[i].valid = 0;\r
-               (*cache_p)->reg_list[i].size = 32;\r
-               (*cache_p)->reg_list[i].bitfield_desc = NULL;\r
-               (*cache_p)->reg_list[i].num_bitfields = 0;\r
-               (*cache_p)->reg_list[i].arch_info = &arch_info[i];\r
-               (*cache_p)->reg_list[i].arch_type = xscale_reg_arch_type;\r
-               arch_info[i] = xscale_reg_arch_info[i];\r
-               arch_info[i].target = target;\r
-       }\r
-\r
-       xscale->reg_cache = (*cache_p);\r
-}\r
-\r
-int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target)\r
-{\r
-       if (startup_mode != DAEMON_RESET)\r
-       {\r
-               ERROR("XScale target requires a reset");\r
-               ERROR("Reset target to enable debug");\r
-       }\r
-\r
-       /* assert TRST once during startup */\r
-       jtag_add_reset(1, 0);\r
-       jtag_add_sleep(5000);\r
-       jtag_add_reset(0, 0);\r
-       jtag_execute_queue();\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_quit()\r
-{\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_pos, char *variant)\r
-{\r
-       armv4_5_common_t *armv4_5;\r
-       u32 high_reset_branch, low_reset_branch;\r
-       int i;\r
-\r
-       armv4_5 = &xscale->armv4_5_common;\r
-\r
-       /* store architecture specfic data (none so far) */\r
-       xscale->arch_info = NULL;\r
-       xscale->common_magic = XSCALE_COMMON_MAGIC;\r
-\r
-       /* remember the variant (PXA25x, PXA27x, IXP42x, ...) */\r
-       xscale->variant = strdup(variant);\r
-\r
-       /* prepare JTAG information for the new target */\r
-       xscale->jtag_info.chain_pos = chain_pos;\r
-       jtag_register_event_callback(xscale_jtag_callback, target);\r
-\r
-       xscale->jtag_info.dbgrx = 0x02;\r
-       xscale->jtag_info.dbgtx = 0x10;\r
-       xscale->jtag_info.dcsr = 0x09;\r
-       xscale->jtag_info.ldic = 0x07;\r
-\r
-       if ((strcmp(xscale->variant, "pxa250") == 0) ||\r
-               (strcmp(xscale->variant, "pxa255") == 0) ||\r
-               (strcmp(xscale->variant, "pxa26x") == 0))\r
-       {\r
-               xscale->jtag_info.ir_length = 5;\r
-       }\r
-       else if ((strcmp(xscale->variant, "pxa27x") == 0) ||\r
-               (strcmp(xscale->variant, "ixp42x") == 0) ||\r
-               (strcmp(xscale->variant, "ixp45x") == 0) ||\r
-               (strcmp(xscale->variant, "ixp46x") == 0))\r
-       {\r
-               xscale->jtag_info.ir_length = 7;\r
-       }\r
-\r
-       /* the debug handler isn't installed (and thus not running) at this time */\r
-       xscale->handler_installed = 0;\r
-       xscale->handler_running = 0;\r
-       xscale->handler_address = 0xfe000800;\r
-\r
-       /* clear the vectors we keep locally for reference */\r
-       memset(xscale->low_vectors, 0, sizeof(xscale->low_vectors));\r
-       memset(xscale->high_vectors, 0, sizeof(xscale->high_vectors));\r
-\r
-       /* no user-specified vectors have been configured yet */\r
-       xscale->static_low_vectors_set = 0x0;\r
-       xscale->static_high_vectors_set = 0x0;\r
-\r
-       /* calculate branches to debug handler */\r
-       low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;\r
-       high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;\r
-\r
-       xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);\r
-       xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);\r
-\r
-       for (i = 1; i <= 7; i++)\r
-       {\r
-               xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);\r
-               xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);\r
-       }\r
-\r
-       /* 64kB aligned region used for DCache cleaning */\r
-       xscale->cache_clean_address = 0xfffe0000;\r
-\r
-       xscale->hold_rst = 0;\r
-       xscale->external_debug_break = 0;\r
-\r
-       xscale->force_hw_bkpts = 1;\r
-\r
-       xscale->ibcr_available = 2;\r
-       xscale->ibcr0_used = 0;\r
-       xscale->ibcr1_used = 0;\r
-\r
-       xscale->dbr_available = 2;\r
-       xscale->dbr0_used = 0;\r
-       xscale->dbr1_used = 0;\r
-\r
-       xscale->arm_bkpt = ARMV5_BKPT(0x0);\r
-       xscale->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;\r
-\r
-       xscale->vector_catch = 0x1;\r
-\r
-       xscale->trace.capture_status = TRACE_IDLE;\r
-       xscale->trace.data = NULL;\r
-       xscale->trace.image = NULL;\r
-       xscale->trace.buffer_enabled = 0;\r
-       xscale->trace.buffer_fill = 0;\r
-\r
-       /* prepare ARMv4/5 specific information */\r
-       armv4_5->arch_info = xscale;\r
-       armv4_5->read_core_reg = xscale_read_core_reg;\r
-       armv4_5->write_core_reg = xscale_write_core_reg;\r
-       armv4_5->full_context = xscale_full_context;\r
-\r
-       armv4_5_init_arch_info(target, armv4_5);\r
-\r
-       xscale->armv4_5_mmu.armv4_5_cache.ctype = -1;\r
-       xscale->armv4_5_mmu.get_ttb = xscale_get_ttb;\r
-       xscale->armv4_5_mmu.read_memory = xscale_read_memory;\r
-       xscale->armv4_5_mmu.write_memory = xscale_write_memory;\r
-       xscale->armv4_5_mmu.disable_mmu_caches = xscale_disable_mmu_caches;\r
-       xscale->armv4_5_mmu.enable_mmu_caches = xscale_enable_mmu_caches;\r
-       xscale->armv4_5_mmu.has_tiny_pages = 1;\r
-       xscale->armv4_5_mmu.mmu_enabled = 0;\r
-\r
-       xscale->fast_memory_access = 0;\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-/* target xscale <endianess> <startup_mode> <chain_pos> <variant> */\r
-int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)\r
-{\r
-       int chain_pos;\r
-       char *variant = NULL;\r
-       xscale_common_t *xscale = malloc(sizeof(xscale_common_t));\r
-\r
-       if (argc < 5)\r
-       {\r
-               ERROR("'target xscale' requires four arguments: <endianess> <startup_mode> <chain_pos> <variant>");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       chain_pos = strtoul(args[3], NULL, 0);\r
-\r
-       variant = args[4];\r
-\r
-       xscale_init_arch_info(target, xscale, chain_pos, variant);\r
-       xscale_build_reg_cache(target);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = NULL;\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       u32 handler_address;\r
-\r
-       if (argc < 2)\r
-       {\r
-               ERROR("'xscale debug_handler <target#> <address>' command takes two required operands");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)\r
-       {\r
-               ERROR("no target '%s' configured", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       handler_address = strtoul(args[1], NULL, 0);\r
-\r
-       if (((handler_address >= 0x800) && (handler_address <= 0x1fef800)) ||\r
-               ((handler_address >= 0xfe000800) && (handler_address <= 0xfffff800)))\r
-       {\r
-               xscale->handler_address = handler_address;\r
-       }\r
-       else\r
-       {\r
-               ERROR("xscale debug_handler <address> must be between 0x800 and 0x1fef800 or between 0xfe000800 and 0xfffff800");\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = NULL;\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       u32 cache_clean_address;\r
-\r
-       if (argc < 2)\r
-       {\r
-               ERROR("'xscale cache_clean_address <target#> <address>' command takes two required operands");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)\r
-       {\r
-               ERROR("no target '%s' configured", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       cache_clean_address = strtoul(args[1], NULL, 0);\r
-\r
-       if (cache_clean_address & 0xffff)\r
-       {\r
-               ERROR("xscale cache_clean_address <address> must be 64kb aligned");\r
-       }\r
-       else\r
-       {\r
-               xscale->cache_clean_address = cache_clean_address;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);\r
-}\r
-\r
-static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical)\r
-{\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-       int retval;\r
-       int type;\r
-       u32 cb;\r
-       int domain;\r
-       u32 ap;\r
-       \r
-       if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK)\r
-       {\r
-               return retval;\r
-       }\r
-       u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);\r
-       if (type == -1)\r
-       {\r
-               return ret;\r
-       }\r
-       \r
-       *physical = ret;\r
-       return ERROR_OK;\r
-}\r
-\r
-static int xscale_mmu(struct target_s *target, int *enabled)\r
-{\r
-       armv4_5_common_t *armv4_5 = target->arch_info;\r
-       xscale_common_t *xscale = armv4_5->arch_info;\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               ERROR("Target not halted");\r
-               return ERROR_TARGET_INVALID;\r
-       }\r
-       \r
-       *enabled = xscale->armv4_5_mmu.mmu_enabled;\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (argc >= 1)\r
-       {\r
-               if (strcmp("enable", args[0]) == 0)\r
-               {\r
-                       xscale_enable_mmu_caches(target, 1, 0, 0);\r
-                       xscale->armv4_5_mmu.mmu_enabled = 1;\r
-               }\r
-               else if (strcmp("disable", args[0]) == 0)\r
-               {\r
-                       xscale_disable_mmu_caches(target, 1, 0, 0);\r
-                       xscale->armv4_5_mmu.mmu_enabled = 0;\r
-               }\r
-       }\r
-\r
-       command_print(cmd_ctx, "mmu %s", (xscale->armv4_5_mmu.mmu_enabled) ? "enabled" : "disabled");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_idcache_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-       int icache = 0, dcache = 0;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (strcmp(cmd, "icache") == 0)\r
-               icache = 1;\r
-       else if (strcmp(cmd, "dcache") == 0)\r
-               dcache = 1;\r
-\r
-       if (argc >= 1)\r
-       {\r
-               if (strcmp("enable", args[0]) == 0)\r
-               {\r
-                       xscale_enable_mmu_caches(target, 0, dcache, icache);\r
-\r
-                       if (icache)\r
-                               xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 1;\r
-                       else if (dcache)\r
-                               xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 1;\r
-               }\r
-               else if (strcmp("disable", args[0]) == 0)\r
-               {\r
-                       xscale_disable_mmu_caches(target, 0, dcache, icache);\r
-\r
-                       if (icache)\r
-                               xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;\r
-                       else if (dcache)\r
-                               xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;\r
-               }\r
-       }\r
-\r
-       if (icache)\r
-               command_print(cmd_ctx, "icache %s", (xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled) ? "enabled" : "disabled");\r
-\r
-       if (dcache)\r
-               command_print(cmd_ctx, "dcache %s", (xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) ? "enabled" : "disabled");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: xscale vector_catch [mask]");\r
-       }\r
-       else\r
-       {\r
-               xscale->vector_catch = strtoul(args[0], NULL, 0);\r
-               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 8, xscale->vector_catch);\r
-               xscale_write_dcsr(target, -1, -1);\r
-       }\r
-\r
-       command_print(cmd_ctx, "vector catch mask: 0x%2.2x", xscale->vector_catch);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if ((argc >= 1) && (strcmp("enable", args[0]) == 0))\r
-       {\r
-               xscale->force_hw_bkpts = 1;\r
-       }\r
-       else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))\r
-       {\r
-               xscale->force_hw_bkpts = 0;\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "usage: xscale force_hw_bkpts <enable|disable>");\r
-       }\r
-\r
-       command_print(cmd_ctx, "force hardware breakpoints %s", (xscale->force_hw_bkpts) ? "enabled" : "disabled");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-       u32 dcsr_value;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if ((argc >= 1) && (strcmp("enable", args[0]) == 0))\r
-       {\r
-               xscale_trace_data_t *td, *next_td;\r
-               xscale->trace.buffer_enabled = 1;\r
-\r
-               /* free old trace data */\r
-               td = xscale->trace.data;\r
-               while (td)\r
-               {\r
-                       next_td = td->next;\r
-\r
-                       if (td->entries)\r
-                               free(td->entries);\r
-                       free(td);\r
-                       td = next_td;\r
-               }\r
-               xscale->trace.data = NULL;\r
-       }\r
-       else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))\r
-       {\r
-               xscale->trace.buffer_enabled = 0;\r
-       }\r
-\r
-       if ((argc >= 2) && (strcmp("fill", args[1]) == 0))\r
-       {\r
-               if (argc >= 3)\r
-                       xscale->trace.buffer_fill = strtoul(args[2], NULL, 0);\r
-               else\r
-                       xscale->trace.buffer_fill = 1;\r
-       }\r
-       else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))\r
-       {\r
-               xscale->trace.buffer_fill = -1;\r
-       }\r
-\r
-       if (xscale->trace.buffer_enabled)\r
-       {\r
-               /* if we enable the trace buffer in fill-once\r
-                * mode we know the address of the first instruction */\r
-               xscale->trace.pc_ok = 1;\r
-               xscale->trace.current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);\r
-       }\r
-       else\r
-       {\r
-               /* otherwise the address is unknown, and we have no known good PC */\r
-               xscale->trace.pc_ok = 0;\r
-       }\r
-\r
-       command_print(cmd_ctx, "trace buffer %s (%s)",\r
-               (xscale->trace.buffer_enabled) ? "enabled" : "disabled",\r
-               (xscale->trace.buffer_fill > 0) ? "fill" : "wrap");\r
-\r
-       dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);\r
-       if (xscale->trace.buffer_fill >= 0)\r
-               xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);\r
-       else\r
-               xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: xscale trace_image <file> [base address] [type]");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       target = get_current_target(cmd_ctx);\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (xscale->trace.image)\r
-       {\r
-               image_close(xscale->trace.image);\r
-               free(xscale->trace.image);\r
-               command_print(cmd_ctx, "previously loaded image found and closed");\r
-       }\r
-\r
-       xscale->trace.image = malloc(sizeof(image_t));\r
-       xscale->trace.image->base_address_set = 0;\r
-       xscale->trace.image->start_address_set = 0;\r
-\r
-       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */\r
-       if (argc >= 2)\r
-       {\r
-               xscale->trace.image->base_address_set = 1;\r
-               xscale->trace.image->base_address = strtoul(args[1], NULL, 0);\r
-       }\r
-       else\r
-       {\r
-               xscale->trace.image->base_address_set = 0;\r
-       }\r
-\r
-       if (image_open(xscale->trace.image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "image opening error: %s", xscale->trace.image->error_str);\r
-               free(xscale->trace.image);\r
-               xscale->trace.image = NULL;\r
-               return ERROR_OK;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-       xscale_trace_data_t *trace_data;\r
-       fileio_t file;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: xscale dump_trace <file>");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       trace_data = xscale->trace.data;\r
-\r
-       if (!trace_data)\r
-       {\r
-               command_print(cmd_ctx, "no trace data collected");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "file open error: %s", file.error_str);\r
-               return ERROR_OK;\r
-       }\r
-\r
-       while (trace_data)\r
-       {\r
-               int i;\r
-\r
-               fileio_write_u32(&file, trace_data->chkpt0);\r
-               fileio_write_u32(&file, trace_data->chkpt1);\r
-               fileio_write_u32(&file, trace_data->last_instruction);\r
-               fileio_write_u32(&file, trace_data->depth);\r
-\r
-               for (i = 0; i < trace_data->depth; i++)\r
-                       fileio_write_u32(&file, trace_data->entries[i].data | ((trace_data->entries[i].type & 0xffff) << 16));\r
-\r
-               trace_data = trace_data->next;\r
-       }\r
-\r
-       fileio_close(&file);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-\r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-\r
-       xscale_analyze_trace(target, cmd_ctx);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-       \r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (target->state != TARGET_HALTED)\r
-       {\r
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);\r
-               return ERROR_OK;\r
-       }\r
-       u32 reg_no = 0;\r
-       reg_t *reg = NULL;\r
-       if(argc > 0)\r
-       {\r
-               reg_no = strtoul(args[0], NULL, 0);\r
-               /*translate from xscale cp15 register no to openocd register*/\r
-               switch(reg_no)\r
-               {\r
-               case 0:\r
-                       reg_no = XSCALE_MAINID;\r
-                       break;\r
-               case 1:\r
-                       reg_no = XSCALE_CTRL;\r
-                       break;\r
-               case 2:\r
-                       reg_no = XSCALE_TTB;\r
-                       break; \r
-               case 3:\r
-                       reg_no = XSCALE_DAC;\r
-                       break;\r
-               case 5:\r
-                       reg_no = XSCALE_FSR;\r
-                       break;\r
-               case 6:\r
-                       reg_no = XSCALE_FAR;\r
-                       break;\r
-               case 13:\r
-                       reg_no = XSCALE_PID;\r
-                       break;\r
-               case 15:\r
-                       reg_no = XSCALE_CPACCESS;\r
-                       break;\r
-               default:\r
-                       command_print(cmd_ctx, "invalid register number");\r
-                       return ERROR_INVALID_ARGUMENTS;\r
-               }\r
-               reg = &xscale->reg_cache->reg_list[reg_no];\r
-               \r
-       }\r
-       if(argc == 1)\r
-       {\r
-               u32 value;\r
-               \r
-               /* read cp15 control register */\r
-               xscale_get_reg(reg);\r
-               value = buf_get_u32(reg->value, 0, 32);\r
-               command_print(cmd_ctx, "%s (/%i): 0x%x", reg->name, reg->size, value);\r
-       }\r
-       else if(argc == 2)\r
-       {   \r
-\r
-               u32 value = strtoul(args[1], NULL, 0);\r
-               \r
-               /* send CP write request (command 0x41) */\r
-               xscale_send_u32(target, 0x41);\r
-               \r
-               /* send CP register number */\r
-               xscale_send_u32(target, reg_no);\r
-               \r
-               /* send CP register value */\r
-               xscale_send_u32(target, value);\r
-               \r
-               /* execute cpwait to ensure outstanding operations complete */\r
-               xscale_send_u32(target, 0x53);\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "usage: cp15 [register]<, [value]>");    \r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_xscale_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target = get_current_target(cmd_ctx);\r
-       armv4_5_common_t *armv4_5;\r
-       xscale_common_t *xscale;\r
-       \r
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)\r
-       {\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (argc == 1)\r
-       {\r
-               if (strcmp("enable", args[0]) == 0)\r
-               {\r
-                       xscale->fast_memory_access = 1;\r
-               }\r
-               else if (strcmp("disable", args[0]) == 0)\r
-               {\r
-                       xscale->fast_memory_access = 0;\r
-               }\r
-               else\r
-               {\r
-                       return ERROR_COMMAND_SYNTAX_ERROR;\r
-               }\r
-       } else if (argc!=0)\r
-       {\r
-               return ERROR_COMMAND_SYNTAX_ERROR;\r
-       }\r
-               \r
-       command_print(cmd_ctx, "fast memory access is %s", (xscale->fast_memory_access) ? "enabled" : "disabled");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xscale_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       command_t *xscale_cmd;\r
-\r
-       xscale_cmd = register_command(cmd_ctx, NULL, "xscale", NULL, COMMAND_ANY, "xscale specific commands");\r
-\r
-       register_command(cmd_ctx, xscale_cmd, "debug_handler", xscale_handle_debug_handler_command, COMMAND_ANY, "'xscale debug_handler <target#> <address>' command takes two required operands");\r
-       register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);\r
-\r
-       register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);\r
-       register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");\r
-       register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");\r
-       register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");\r
-\r
-       register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_idcache_command, COMMAND_EXEC, "<mask> of vectors that should be catched");\r
-\r
-       register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable|disable> ['fill' [n]|'wrap']");\r
-\r
-       register_command(cmd_ctx, xscale_cmd, "dump_trace", xscale_handle_dump_trace_command, COMMAND_EXEC, "dump content of trace buffer to <file>");\r
-       register_command(cmd_ctx, xscale_cmd, "analyze_trace", xscale_handle_analyze_trace_buffer_command, COMMAND_EXEC, "analyze content of trace buffer");\r
-       register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,\r
-               COMMAND_EXEC, "load image from <file> [base address]");\r
-\r
-       register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");\r
-       register_command(cmd_ctx, xscale_cmd, "fast_memory_access", handle_xscale_fast_memory_access_command,\r
-                COMMAND_ANY, "use fast memory accesses instead of slower but potentially unsafe slow accesses <enable|disable>");\r
-       \r
-       armv4_5_register_commands(cmd_ctx);\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2006, 2007 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "xscale.h"
+
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "arm_simulator.h"
+#include "arm_disassembler.h"
+#include "log.h"
+#include "jtag.h"
+#include "binarybuffer.h"
+#include "time_support.h"
+#include "breakpoints.h"
+#include "fileio.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+/* cli handling */
+int xscale_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int xscale_quit();
+
+int xscale_arch_state(struct target_s *target);
+int xscale_poll(target_t *target);
+int xscale_halt(target_t *target);
+int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
+int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
+int xscale_debug_entry(target_t *target);
+int xscale_restore_context(target_t *target);
+
+int xscale_assert_reset(target_t *target);
+int xscale_deassert_reset(target_t *target);
+int xscale_soft_reset_halt(struct target_s *target);
+int xscale_prepare_reset_halt(struct target_s *target);
+
+int xscale_set_reg_u32(reg_t *reg, u32 value);
+
+int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode);
+int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value);
+
+int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
+int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
+
+int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+void xscale_enable_watchpoints(struct target_s *target);
+void xscale_enable_breakpoints(struct target_s *target);
+static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
+static int xscale_mmu(struct target_s *target, int *enabled);
+
+int xscale_read_trace(target_t *target);
+
+target_type_t xscale_target =
+{
+       .name = "xscale",
+
+       .poll = xscale_poll,
+       .arch_state = xscale_arch_state,
+
+       .target_request_data = NULL,
+
+       .halt = xscale_halt,
+       .resume = xscale_resume,
+       .step = xscale_step,
+
+       .assert_reset = xscale_assert_reset,
+       .deassert_reset = xscale_deassert_reset,
+       .soft_reset_halt = xscale_soft_reset_halt,
+       .prepare_reset_halt = xscale_prepare_reset_halt,
+
+       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+       .read_memory = xscale_read_memory,
+       .write_memory = xscale_write_memory,
+       .bulk_write_memory = xscale_bulk_write_memory,
+       .checksum_memory = xscale_checksum_memory,
+
+       .run_algorithm = armv4_5_run_algorithm,
+
+       .add_breakpoint = xscale_add_breakpoint,
+       .remove_breakpoint = xscale_remove_breakpoint,
+       .add_watchpoint = xscale_add_watchpoint,
+       .remove_watchpoint = xscale_remove_watchpoint,
+
+       .register_commands = xscale_register_commands,
+       .target_command = xscale_target_command,
+       .init_target = xscale_init_target,
+       .quit = xscale_quit,
+       
+       .virt2phys = xscale_virt2phys,
+       .mmu = xscale_mmu
+};
+
+char* xscale_reg_list[] =
+{
+       "XSCALE_MAINID",                /* 0 */
+       "XSCALE_CACHETYPE",
+       "XSCALE_CTRL",
+       "XSCALE_AUXCTRL",
+       "XSCALE_TTB",
+       "XSCALE_DAC",
+       "XSCALE_FSR",
+       "XSCALE_FAR",
+       "XSCALE_PID",
+       "XSCALE_CPACCESS",
+       "XSCALE_IBCR0",                 /* 10 */
+       "XSCALE_IBCR1",
+       "XSCALE_DBR0",
+       "XSCALE_DBR1",
+       "XSCALE_DBCON",
+       "XSCALE_TBREG",
+       "XSCALE_CHKPT0",
+       "XSCALE_CHKPT1",
+       "XSCALE_DCSR",
+       "XSCALE_TX",
+       "XSCALE_RX",                    /* 20 */
+       "XSCALE_TXRXCTRL",
+};
+
+xscale_reg_t xscale_reg_arch_info[] =
+{
+       {XSCALE_MAINID, NULL},
+       {XSCALE_CACHETYPE, NULL},
+       {XSCALE_CTRL, NULL},
+       {XSCALE_AUXCTRL, NULL},
+       {XSCALE_TTB, NULL},
+       {XSCALE_DAC, NULL},
+       {XSCALE_FSR, NULL},
+       {XSCALE_FAR, NULL},
+       {XSCALE_PID, NULL},
+       {XSCALE_CPACCESS, NULL},
+       {XSCALE_IBCR0, NULL},
+       {XSCALE_IBCR1, NULL},
+       {XSCALE_DBR0, NULL},
+       {XSCALE_DBR1, NULL},
+       {XSCALE_DBCON, NULL},
+       {XSCALE_TBREG, NULL},
+       {XSCALE_CHKPT0, NULL},
+       {XSCALE_CHKPT1, NULL},
+       {XSCALE_DCSR, NULL}, /* DCSR accessed via JTAG or SW */
+       {-1, NULL}, /* TX accessed via JTAG */
+       {-1, NULL}, /* RX accessed via JTAG */
+       {-1, NULL}, /* TXRXCTRL implicit access via JTAG */
+};
+
+int xscale_reg_arch_type = -1;
+
+int xscale_get_reg(reg_t *reg);
+int xscale_set_reg(reg_t *reg, u8 *buf);
+
+int xscale_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, xscale_common_t **xscale_p)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               ERROR("target isn't an XScale target");
+               return -1;
+       }
+
+       if (xscale->common_magic != XSCALE_COMMON_MAGIC)
+       {
+               ERROR("target isn't an XScale target");
+               return -1;
+       }
+
+       *armv4_5_p = armv4_5;
+       *xscale_p = xscale;
+
+       return ERROR_OK;
+}
+
+int xscale_jtag_set_instr(int chain_pos, u32 new_instr)
+{
+       jtag_device_t *device = jtag_get_device(chain_pos);
+
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+
+               field.device = chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               jtag_set_check_value(&field, device->expected, device->expected_mask, NULL);
+
+               jtag_add_ir_scan(1, &field, -1);
+
+               free(field.out_value);
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_jtag_callback(enum jtag_event event, void *priv)
+{
+       switch (event)
+       {
+               case JTAG_TRST_ASSERTED:
+                       break;
+               case JTAG_TRST_RELEASED:
+                       break;
+               case JTAG_SRST_ASSERTED:
+                       break;
+               case JTAG_SRST_RELEASED:
+                       break;
+               default:
+                       WARNING("unhandled JTAG event");
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_read_dcsr(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       int retval;
+
+       scan_field_t fields[3];
+       u8 field0 = 0x0;
+       u8 field0_check_value = 0x2;
+       u8 field0_check_mask = 0x7;
+       u8 field2 = 0x0;
+       u8 field2_check_value = 0x0;
+       u8 field2_check_mask = 0x1;
+
+       jtag_add_end_state(TAP_PD);
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
+
+       buf_set_u32(&field0, 1, 1, xscale->hold_rst);
+       buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 3;
+       fields[0].out_value = &field0;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+
+
+       fields[2].device = xscale->jtag_info.chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = &field2;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+       jtag_add_dr_scan(3, fields, -1);
+
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               ERROR("JTAG error while reading DCSR");
+               return retval;
+       }
+
+       xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
+       xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
+
+       /* write the register with the value we just read
+        * on this second pass, only the first bit of field0 is guaranteed to be 0)
+        */
+       field0_check_mask = 0x1;
+       fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
+       fields[1].in_value = NULL;
+
+       jtag_add_end_state(TAP_RTI);
+
+       jtag_add_dr_scan(3, fields, -1);
+
+       return ERROR_OK;
+}
+
+int xscale_receive(target_t *target, u32 *buffer, int num_words)
+{
+       int retval = ERROR_OK;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       enum tap_state path[3];
+       scan_field_t fields[3];
+
+       u8 *field0 = malloc(num_words * 1);
+       u8 field0_check_value = 0x2;
+       u8 field0_check_mask = 0x6;
+       u32 *field1 = malloc(num_words * 4);
+       u8 field2_check_value = 0x0;
+       u8 field2_check_mask = 0x1;
+       int words_done = 0;
+       int words_scheduled = 0;
+
+       int i;
+
+       path[0] = TAP_SDS;
+       path[1] = TAP_CD;
+       path[2] = TAP_SD;
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 3;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       /* fields[0].in_value = field0; */
+       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+
+
+       fields[2].device = xscale->jtag_info.chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = NULL;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+       jtag_add_end_state(TAP_RTI);
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);
+       jtag_add_runtest(1, -1);
+
+       /* repeat until all words have been collected */
+       int attempts = 0;
+       while (words_done < num_words)
+       {
+               /* schedule reads */
+               words_scheduled = 0;
+               for (i = words_done; i < num_words; i++)
+               {
+                       fields[0].in_value = &field0[i];
+                       fields[1].in_handler = buf_to_u32_handler;
+                       fields[1].in_handler_priv = (u8*)&field1[i];
+
+                       jtag_add_pathmove(3, path);
+                       jtag_add_dr_scan(3, fields, TAP_RTI);
+                       words_scheduled++;
+               }
+
+               if ((retval = jtag_execute_queue()) != ERROR_OK)
+               {
+                       ERROR("JTAG error while receiving data from debug handler");
+                       break;
+               }
+
+               /* examine results */
+               for (i = words_done; i < num_words; i++)
+               {
+                       if (!(field0[0] & 1))
+                       {
+                               /* move backwards if necessary */
+                               int j;
+                               for (j = i; j < num_words - 1; j++)
+                               {
+                                       field0[j] = field0[j+1];
+                                       field1[j] = field1[j+1];
+                               }
+                               words_scheduled--;
+                       }
+               }
+               if (words_scheduled == 0)
+               {
+                       if (attempts++ == 1000)
+                       {
+                               ERROR("Failed to receiving data from debug handler after 1000 attempts");
+                               retval = ERROR_JTAG_QUEUE_FAILED;
+                               break;
+                       }
+               }
+               
+               words_done += words_scheduled;
+       }
+
+       for (i = 0; i < num_words; i++)
+               *(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);
+
+       free(field1);
+
+       return retval;
+}
+
+int xscale_read_tx(target_t *target, int consume)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       enum tap_state path[3];
+       enum tap_state noconsume_path[9];
+
+       int retval;
+       struct timeval timeout, now;
+
+       scan_field_t fields[3];
+       u8 field0_in = 0x0;
+       u8 field0_check_value = 0x2;
+       u8 field0_check_mask = 0x6;
+       u8 field2_check_value = 0x0;
+       u8 field2_check_mask = 0x1;
+
+       jtag_add_end_state(TAP_RTI);
+
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);
+
+       path[0] = TAP_SDS;
+       path[1] = TAP_CD;
+       path[2] = TAP_SD;
+
+       noconsume_path[0] = TAP_SDS;
+       noconsume_path[1] = TAP_CD;
+       noconsume_path[2] = TAP_E1D;
+       noconsume_path[3] = TAP_PD;
+       noconsume_path[4] = TAP_E2D;
+       noconsume_path[5] = TAP_UD;
+       noconsume_path[6] = TAP_SDS;
+       noconsume_path[7] = TAP_CD;
+       noconsume_path[8] = TAP_SD;
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 3;
+       fields[0].out_value = NULL;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = &field0_in;
+       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = NULL;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+
+
+       fields[2].device = xscale->jtag_info.chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = NULL;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, 5, 0);
+
+       do
+       {
+               /* if we want to consume the register content (i.e. clear TX_READY),
+                * we have to go straight from Capture-DR to Shift-DR
+                * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR
+               */
+               if (consume)
+                       jtag_add_pathmove(3, path);
+               else
+                       jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
+
+               jtag_add_dr_scan(3, fields, TAP_RTI);
+
+               if ((retval = jtag_execute_queue()) != ERROR_OK)
+               {
+                       ERROR("JTAG error while reading TX");
+                       return ERROR_TARGET_TIMEOUT;
+               }
+
+               gettimeofday(&now, NULL);
+               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
+               {
+                       ERROR("time out reading TX register");
+                       return ERROR_TARGET_TIMEOUT;
+               }
+       } while ((!(field0_in & 1)) && consume);
+
+       if (!(field0_in & 1))
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+
+       return ERROR_OK;
+}
+
+int xscale_write_rx(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       int retval;
+       struct timeval timeout, now;
+
+       scan_field_t fields[3];
+       u8 field0_out = 0x0;
+       u8 field0_in = 0x0;
+       u8 field0_check_value = 0x2;
+       u8 field0_check_mask = 0x6;
+       u8 field2 = 0x0;
+       u8 field2_check_value = 0x0;
+       u8 field2_check_mask = 0x1;
+
+       jtag_add_end_state(TAP_RTI);
+
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 3;
+       fields[0].out_value = &field0_out;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = &field0_in;
+       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+
+
+       fields[2].device = xscale->jtag_info.chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = &field2;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, 5, 0);
+
+       /* poll until rx_read is low */
+       DEBUG("polling RX");
+       do
+       {
+               jtag_add_dr_scan(3, fields, TAP_RTI);
+
+               if ((retval = jtag_execute_queue()) != ERROR_OK)
+               {
+                       ERROR("JTAG error while writing RX");
+                       return retval;
+               }
+
+               gettimeofday(&now, NULL);
+               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec)&& (now.tv_usec > timeout.tv_usec)))
+               {
+                       ERROR("time out writing RX register");
+                       return ERROR_TARGET_TIMEOUT;
+               }
+       } while (field0_in & 1);
+
+       /* set rx_valid */
+       field2 = 0x1;
+       jtag_add_dr_scan(3, fields, TAP_RTI);
+
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               ERROR("JTAG error while writing RX");
+               return retval;
+       }
+
+       return ERROR_OK;
+}
+
+/* send count elements of size byte to the debug handler */
+int xscale_send(target_t *target, u8 *buffer, int count, int size)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       int retval;
+
+       int done_count = 0;
+       u8 output[4] = {0, 0, 0, 0};
+
+       scan_field_t fields[3];
+       u8 field0_out = 0x0;
+       u8 field0_check_value = 0x2;
+       u8 field0_check_mask = 0x6;
+       u8 field2 = 0x1;
+       u8 field2_check_value = 0x0;
+       u8 field2_check_mask = 0x1;
+
+       jtag_add_end_state(TAP_RTI);
+
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 3;
+       fields[0].out_value = &field0_out;
+       fields[0].out_mask = NULL;
+       fields[0].in_handler = NULL;
+       if (!xscale->fast_memory_access)
+       {
+               jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+       }
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = output;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+
+
+       fields[2].device = xscale->jtag_info.chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = &field2;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       fields[2].in_handler = NULL;
+       if (!xscale->fast_memory_access)
+       {
+               jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+       }
+
+       if (size==4)
+       {
+               int endianness = target->endianness;
+               while (done_count++ < count)
+               {
+                       if (endianness == TARGET_LITTLE_ENDIAN)
+                       {
+                               output[0]=buffer[0];
+                               output[1]=buffer[1];
+                               output[2]=buffer[2];
+                               output[3]=buffer[3];
+                       } else
+                       {
+                               output[0]=buffer[3];
+                               output[1]=buffer[2];
+                               output[2]=buffer[1];
+                               output[3]=buffer[0];
+                       }
+                       jtag_add_dr_scan(3, fields, TAP_RTI);
+                       buffer += size;
+               }
+               
+       } else
+       {
+               while (done_count++ < count)
+               {
+               /* extract sized element from target-endian buffer, and put it
+                * into little-endian output buffer
+                */
+               switch (size)
+               {
+                       case 2:
+                               buf_set_u32(output, 0, 32, target_buffer_get_u16(target, buffer));
+                               break;
+                       case 1:
+                               output[0] = *buffer;
+                               break;
+                       default:
+                               ERROR("BUG: size neither 4, 2 nor 1");
+                               exit(-1);
+               }
+
+               jtag_add_dr_scan(3, fields, TAP_RTI);
+               buffer += size;
+       }
+
+       }
+
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               ERROR("JTAG error while sending data to debug handler");
+               return retval;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_send_u32(target_t *target, u32 value)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
+       return xscale_write_rx(target);
+}
+
+int xscale_write_dcsr(target_t *target, int hold_rst, int ext_dbg_brk)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       int retval;
+
+       scan_field_t fields[3];
+       u8 field0 = 0x0;
+       u8 field0_check_value = 0x2;
+       u8 field0_check_mask = 0x7;
+       u8 field2 = 0x0;
+       u8 field2_check_value = 0x0;
+       u8 field2_check_mask = 0x1;
+
+       if (hold_rst != -1)
+               xscale->hold_rst = hold_rst;
+
+       if (ext_dbg_brk != -1)
+               xscale->external_debug_break = ext_dbg_brk;
+
+       jtag_add_end_state(TAP_RTI);
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
+
+       buf_set_u32(&field0, 1, 1, xscale->hold_rst);
+       buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 3;
+       fields[0].out_value = &field0;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 32;
+       fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+
+
+
+       fields[2].device = xscale->jtag_info.chain_pos;
+       fields[2].num_bits = 1;
+       fields[2].out_value = &field2;
+       fields[2].out_mask = NULL;
+       fields[2].in_value = NULL;
+       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+       jtag_add_dr_scan(3, fields, -1);
+
+       if ((retval = jtag_execute_queue()) != ERROR_OK)
+       {
+               ERROR("JTAG error while writing DCSR");
+               return retval;
+       }
+
+       xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
+       xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
+
+       return ERROR_OK;
+}
+
+/* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */
+unsigned int parity (unsigned int v)
+{
+       unsigned int ov = v;
+       v ^= v >> 16;
+       v ^= v >> 8;
+       v ^= v >> 4;
+       v &= 0xf;
+       DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1);
+       return (0x6996 >> v) & 1;
+}
+
+int xscale_load_ic(target_t *target, int mini, u32 va, u32 buffer[8])
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u8 packet[4];
+       u8 cmd;
+       int word;
+
+       scan_field_t fields[2];
+
+       DEBUG("loading miniIC at 0x%8.8x", va);
+
+       jtag_add_end_state(TAP_RTI);
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */
+
+       /* CMD is b010 for Main IC and b011 for Mini IC */
+       if (mini)
+               buf_set_u32(&cmd, 0, 3, 0x3);
+       else
+               buf_set_u32(&cmd, 0, 3, 0x2);
+
+       buf_set_u32(&cmd, 3, 3, 0x0);
+
+       /* virtual address of desired cache line */
+       buf_set_u32(packet, 0, 27, va >> 5);
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 6;
+       fields[0].out_value = &cmd;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 27;
+       fields[1].out_value = packet;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       fields[0].num_bits = 32;
+       fields[0].out_value = packet;
+
+       fields[1].num_bits = 1;
+       fields[1].out_value = &cmd;
+
+       for (word = 0; word < 8; word++)
+       {
+               buf_set_u32(packet, 0, 32, buffer[word]);
+               cmd = parity(*((u32*)packet));
+               jtag_add_dr_scan(2, fields, -1);
+       }
+
+       jtag_execute_queue();
+
+       return ERROR_OK;
+}
+
+int xscale_invalidate_ic_line(target_t *target, u32 va)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u8 packet[4];
+       u8 cmd;
+
+       scan_field_t fields[2];
+
+       jtag_add_end_state(TAP_RTI);
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */
+
+       /* CMD for invalidate IC line b000, bits [6:4] b000 */
+       buf_set_u32(&cmd, 0, 6, 0x0);
+
+       /* virtual address of desired cache line */
+       buf_set_u32(packet, 0, 27, va >> 5);
+
+       fields[0].device = xscale->jtag_info.chain_pos;
+       fields[0].num_bits = 6;
+       fields[0].out_value = &cmd;
+       fields[0].out_mask = NULL;
+       fields[0].in_value = NULL;
+       fields[0].in_check_value = NULL;
+       fields[0].in_check_mask = NULL;
+       fields[0].in_handler = NULL;
+       fields[0].in_handler_priv = NULL;
+
+       fields[1].device = xscale->jtag_info.chain_pos;
+       fields[1].num_bits = 27;
+       fields[1].out_value = packet;
+       fields[1].out_mask = NULL;
+       fields[1].in_value = NULL;
+       fields[1].in_check_value = NULL;
+       fields[1].in_check_mask = NULL;
+       fields[1].in_handler = NULL;
+       fields[1].in_handler_priv = NULL;
+
+       jtag_add_dr_scan(2, fields, -1);
+
+       return ERROR_OK;
+}
+
+int xscale_update_vectors(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       int i;
+
+       u32 low_reset_branch, high_reset_branch;
+
+       for (i = 1; i < 8; i++)
+       {
+               /* if there's a static vector specified for this exception, override */
+               if (xscale->static_high_vectors_set & (1 << i))
+               {
+                       xscale->high_vectors[i] = xscale->static_high_vectors[i];
+               }
+               else
+               {
+                       if (target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]) != ERROR_OK)
+                       {
+                               xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+                       }
+               }
+       }
+
+       for (i = 1; i < 8; i++)
+       {
+               if (xscale->static_low_vectors_set & (1 << i))
+               {
+                       xscale->low_vectors[i] = xscale->static_low_vectors[i];
+               }
+               else
+               {
+                       if (target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]) != ERROR_OK)
+                       {
+                               xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+                       }
+               }
+       }
+
+       /* calculate branches to debug handler */
+       low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
+       high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
+
+       xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
+       xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
+
+       /* invalidate and load exception vectors in mini i-cache */
+       xscale_invalidate_ic_line(target, 0x0);
+       xscale_invalidate_ic_line(target, 0xffff0000);
+
+       xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
+       xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
+
+       return ERROR_OK;
+}
+
+int xscale_arch_state(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       char *state[] =
+       {
+               "disabled", "enabled"
+       };
+
+       char *arch_dbg_reason[] =
+       {
+               "", "\n(processor reset)", "\n(trace buffer full)"
+       };
+
+       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       {
+               ERROR("BUG: called for a non-ARMv4/5 target");
+               exit(-1);
+       }
+
+       USER("target halted in %s state due to %s, current mode: %s\n"
+                       "cpsr: 0x%8.8x pc: 0x%8.8x\n"
+                       "MMU: %s, D-Cache: %s, I-Cache: %s"
+                       "%s",
+                        armv4_5_state_strings[armv4_5->core_state],
+                        target_debug_reason_strings[target->debug_reason],
+                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+                        buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
+                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
+                        state[xscale->armv4_5_mmu.mmu_enabled],
+                        state[xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
+                        state[xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled],
+                        arch_dbg_reason[xscale->arch_debug_reason]);
+
+       return ERROR_OK;
+}
+
+int xscale_poll(target_t *target)
+{
+       int retval=ERROR_OK;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
+       {
+               enum target_state previous_state = target->state;
+               if ((retval = xscale_read_tx(target, 0)) == ERROR_OK)
+               {
+
+                       /* there's data to read from the tx register, we entered debug state */
+                       xscale->handler_running = 1;
+
+                       target->state = TARGET_HALTED;
+
+                       /* process debug entry, fetching current mode regs */
+                       retval = xscale_debug_entry(target);
+               }
+               else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+               {
+                       USER("error while polling TX register, reset CPU");
+                       /* here we "lie" so GDB won't get stuck and a reset can be perfomed */
+                       target->state = TARGET_HALTED;
+               }
+
+                       /* debug_entry could have overwritten target state (i.e. immediate resume)
+                        * don't signal event handlers in that case
+                        */
+               if (target->state != TARGET_HALTED)
+                       return ERROR_OK;
+
+               /* if target was running, signal that we halted
+                * otherwise we reentered from debug execution */
+               if (previous_state == TARGET_RUNNING)
+                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               else
+                       target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+       }
+       return retval;
+}
+
+int xscale_debug_entry(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u32 pc;
+       u32 buffer[10];
+       int i;
+
+       u32 moe;
+
+       /* clear external dbg break (will be written on next DCSR read) */
+       xscale->external_debug_break = 0;
+       xscale_read_dcsr(target);
+
+       /* get r0, pc, r1 to r7 and cpsr */
+       xscale_receive(target, buffer, 10);
+
+       /* move r0 from buffer to register cache */
+       buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, buffer[0]);
+       armv4_5->core_cache->reg_list[15].dirty = 1;
+       armv4_5->core_cache->reg_list[15].valid = 1;
+       DEBUG("r0: 0x%8.8x", buffer[0]);
+
+       /* move pc from buffer to register cache */
+       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, buffer[1]);
+       armv4_5->core_cache->reg_list[15].dirty = 1;
+       armv4_5->core_cache->reg_list[15].valid = 1;
+       DEBUG("pc: 0x%8.8x", buffer[1]);
+
+       /* move data from buffer to register cache */
+       for (i = 1; i <= 7; i++)
+       {
+               buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, buffer[1 + i]);
+               armv4_5->core_cache->reg_list[i].dirty = 1;
+               armv4_5->core_cache->reg_list[i].valid = 1;
+               DEBUG("r%i: 0x%8.8x", i, buffer[i + 1]);
+       }
+
+       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, buffer[9]);
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+       DEBUG("cpsr: 0x%8.8x", buffer[9]);
+
+       armv4_5->core_mode = buffer[9] & 0x1f;
+       if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
+       {
+               target->state = TARGET_UNKNOWN;
+               ERROR("cpsr contains invalid mode value - communication failure");
+               return ERROR_TARGET_FAILURE;
+       }
+       DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
+
+       if (buffer[9] & 0x20)
+               armv4_5->core_state = ARMV4_5_STATE_THUMB;
+       else
+               armv4_5->core_state = ARMV4_5_STATE_ARM;
+
+       /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
+       if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS))
+       {
+               xscale_receive(target, buffer, 8);
+               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);
+               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;
+               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1;
+       }
+       else
+       {
+               /* r8 to r14, but no spsr */
+               xscale_receive(target, buffer, 7);
+       }
+
+       /* move data from buffer to register cache */
+       for (i = 8; i <= 14; i++)
+       {
+               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, buffer[i - 8]);
+               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;
+               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
+       }
+
+       /* examine debug reason */
+       xscale_read_dcsr(target);
+       moe = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 2, 3);
+
+       /* stored PC (for calculating fixup) */
+       pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+
+       switch (moe)
+       {
+               case 0x0: /* Processor reset */
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_RESET;
+                       pc -= 4;
+                       break;
+               case 0x1: /* Instruction breakpoint hit */
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+                       pc -= 4;
+                       break;
+               case 0x2: /* Data breakpoint hit */
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+                       pc -= 4;
+                       break;
+               case 0x3: /* BKPT instruction executed */
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+                       pc -= 4;
+                       break;
+               case 0x4: /* Ext. debug event */
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+                       pc -= 4;
+                       break;
+               case 0x5: /* Vector trap occured */
+                       target->debug_reason = DBG_REASON_BREAKPOINT;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+                       pc -= 4;
+                       break;
+               case 0x6: /* Trace buffer full break */
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       xscale->arch_debug_reason = XSCALE_DBG_REASON_TB_FULL;
+                       pc -= 4;
+                       break;
+               case 0x7: /* Reserved */
+               default:
+                       ERROR("Method of Entry is 'Reserved'");
+                       exit(-1);
+                       break;
+       }
+
+       /* apply PC fixup */
+       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, pc);
+
+       /* on the first debug entry, identify cache type */
+       if (xscale->armv4_5_mmu.armv4_5_cache.ctype == -1)
+       {
+               u32 cache_type_reg;
+
+               /* read cp15 cache type register */
+               xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CACHETYPE]);
+               cache_type_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CACHETYPE].value, 0, 32);
+
+               armv4_5_identify_cache(cache_type_reg, &xscale->armv4_5_mmu.armv4_5_cache);
+       }
+
+       /* examine MMU and Cache settings */
+       /* read cp15 control register */
+       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       xscale->cp15_control_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
+       xscale->armv4_5_mmu.mmu_enabled = (xscale->cp15_control_reg & 0x1U) ? 1 : 0;
+       xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (xscale->cp15_control_reg & 0x4U) ? 1 : 0;
+       xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (xscale->cp15_control_reg & 0x1000U) ? 1 : 0;
+
+       /* tracing enabled, read collected trace data */
+       if (xscale->trace.buffer_enabled)
+       {
+               xscale_read_trace(target);
+               xscale->trace.buffer_fill--;
+
+               /* resume if we're still collecting trace data */
+               if ((xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)
+                       && (xscale->trace.buffer_fill > 0))
+               {
+                       xscale_resume(target, 1, 0x0, 1, 0);
+               }
+               else
+               {
+                       xscale->trace.buffer_enabled = 0;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_halt(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       DEBUG("target->state: %s", target_state_strings[target->state]);
+
+       if (target->state == TARGET_HALTED)
+       {
+               WARNING("target was already halted");
+               return ERROR_TARGET_ALREADY_HALTED;
+       }
+       else if (target->state == TARGET_UNKNOWN)
+       {
+               /* this must not happen for a xscale target */
+               ERROR("target was in unknown state when halt was requested");
+               return ERROR_TARGET_INVALID;
+       }
+       else if (target->state == TARGET_RESET)
+       {
+               DEBUG("target->state == TARGET_RESET");
+       }
+       else
+       {
+               /* assert external dbg break */
+               xscale->external_debug_break = 1;
+               xscale_read_dcsr(target);
+
+               target->debug_reason = DBG_REASON_DBGRQ;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_enable_single_step(struct target_s *target, u32 next_pc)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale= armv4_5->arch_info;
+       reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
+
+       if (xscale->ibcr0_used)
+       {
+               breakpoint_t *ibcr0_bp = breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe);
+
+               if (ibcr0_bp)
+               {
+                       xscale_unset_breakpoint(target, ibcr0_bp);
+               }
+               else
+               {
+                       ERROR("BUG: xscale->ibcr0_used is set, but no breakpoint with that address found");
+                       exit(-1);
+               }
+       }
+
+       xscale_set_reg_u32(ibcr0, next_pc | 0x1);
+
+       return ERROR_OK;
+}
+
+int xscale_disable_single_step(struct target_s *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale= armv4_5->arch_info;
+       reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
+
+       xscale_set_reg_u32(ibcr0, 0x0);
+
+       return ERROR_OK;
+}
+
+int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale= armv4_5->arch_info;
+       breakpoint_t *breakpoint = target->breakpoints;
+
+       u32 current_pc;
+
+       int retval;
+       int i;
+
+       DEBUG("-");
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (!debug_execution)
+       {
+               target_free_all_working_areas(target);
+       }
+
+       /* update vector tables */
+       xscale_update_vectors(target);
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current)
+               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
+
+       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+
+       /* if we're at the reset vector, we have to simulate the branch */
+       if (current_pc == 0x0)
+       {
+               arm_simulate_step(target, NULL);
+               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       }
+
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+       {
+               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
+               {
+                       u32 next_pc;
+
+                       /* there's a breakpoint at the current PC, we have to step over it */
+                       DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
+                       xscale_unset_breakpoint(target, breakpoint);
+
+                       /* calculate PC of next instruction */
+                       if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
+                       {
+                               u32 current_opcode;
+                               target_read_u32(target, current_pc, &current_opcode);
+                               ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
+                       }
+
+                       DEBUG("enable single-step");
+                       xscale_enable_single_step(target, next_pc);
+
+                       /* restore banked registers */
+                       xscale_restore_context(target);
+
+                       /* send resume request (command 0x30 or 0x31)
+                        * clean the trace buffer if it is to be enabled (0x62) */
+                       if (xscale->trace.buffer_enabled)
+                       {
+                               xscale_send_u32(target, 0x62);
+                               xscale_send_u32(target, 0x31);
+                       }
+                       else
+                               xscale_send_u32(target, 0x30);
+
+                       /* send CPSR */
+                       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+                       DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+
+                       for (i = 7; i >= 0; i--)
+                       {
+                               /* send register */
+                               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+                               DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+                       }
+
+                       /* send PC */
+                       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+                       DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+
+                       /* wait for and process debug entry */
+                       xscale_debug_entry(target);
+
+                       DEBUG("disable single-step");
+                       xscale_disable_single_step(target);
+
+                       DEBUG("set breakpoint at 0x%8.8x", breakpoint->address);
+                       xscale_set_breakpoint(target, breakpoint);
+               }
+       }
+
+       /* enable any pending breakpoints and watchpoints */
+       xscale_enable_breakpoints(target);
+       xscale_enable_watchpoints(target);
+
+       /* restore banked registers */
+       xscale_restore_context(target);
+
+       /* send resume request (command 0x30 or 0x31)
+        * clean the trace buffer if it is to be enabled (0x62) */
+       if (xscale->trace.buffer_enabled)
+       {
+               xscale_send_u32(target, 0x62);
+               xscale_send_u32(target, 0x31);
+       }
+       else
+               xscale_send_u32(target, 0x30);
+
+       /* send CPSR */
+       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+       DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+
+       for (i = 7; i >= 0; i--)
+       {
+               /* send register */
+               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+               DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+       }
+
+       /* send PC */
+       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+       DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+
+       target->debug_reason = DBG_REASON_NOTHALTED;
+
+       if (!debug_execution)
+       {
+               /* registers are now invalid */
+               armv4_5_invalidate_core_regs(target);
+               target->state = TARGET_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+       }
+       else
+       {
+               target->state = TARGET_DEBUG_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+       }
+
+       DEBUG("target resumed");
+
+       xscale->handler_running = 1;
+
+       return ERROR_OK;
+}
+
+int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       breakpoint_t *breakpoint = target->breakpoints;
+
+       u32 current_pc, next_pc;
+       int i;
+       int retval;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* current = 1: continue on current pc, otherwise continue at <address> */
+       if (!current)
+               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
+
+       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+
+       /* if we're at the reset vector, we have to simulate the step */
+       if (current_pc == 0x0)
+       {
+               arm_simulate_step(target, NULL);
+               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+
+               target->debug_reason = DBG_REASON_SINGLESTEP;
+               target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+
+               return ERROR_OK;
+       }
+
+       /* the front-end may request us not to handle breakpoints */
+       if (handle_breakpoints)
+               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
+               {
+                       xscale_unset_breakpoint(target, breakpoint);
+               }
+
+       target->debug_reason = DBG_REASON_SINGLESTEP;
+
+       /* calculate PC of next instruction */
+       if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
+       {
+               u32 current_opcode;
+               target_read_u32(target, current_pc, &current_opcode);
+               ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
+       }
+
+       DEBUG("enable single-step");
+       xscale_enable_single_step(target, next_pc);
+
+       /* restore banked registers */
+       xscale_restore_context(target);
+
+       /* send resume request (command 0x30 or 0x31)
+        * clean the trace buffer if it is to be enabled (0x62) */
+       if (xscale->trace.buffer_enabled)
+       {
+               xscale_send_u32(target, 0x62);
+               xscale_send_u32(target, 0x31);
+       }
+       else
+               xscale_send_u32(target, 0x30);
+
+       /* send CPSR */
+       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+       DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+
+       for (i = 7; i >= 0; i--)
+       {
+               /* send register */
+               xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+               DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+       }
+
+       /* send PC */
+       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+       DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+
+       target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+
+       /* registers are now invalid */
+       armv4_5_invalidate_core_regs(target);
+
+       /* wait for and process debug entry */
+       xscale_debug_entry(target);
+
+       DEBUG("disable single-step");
+       xscale_disable_single_step(target);
+
+       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+
+       if (breakpoint)
+       {
+               xscale_set_breakpoint(target, breakpoint);
+       }
+
+       DEBUG("target stepped");
+
+       return ERROR_OK;
+
+}
+
+int xscale_assert_reset(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       DEBUG("target->state: %s", target_state_strings[target->state]);
+
+       /* select DCSR instruction (set endstate to R-T-I to ensure we don't
+        * end up in T-L-R, which would reset JTAG
+        */
+       jtag_add_end_state(TAP_RTI);
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
+
+       /* set Hold reset, Halt mode and Trap Reset */
+       buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
+       buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
+       xscale_write_dcsr(target, 1, 0);
+
+       /* select BYPASS, because having DCSR selected caused problems on the PXA27x */
+       xscale_jtag_set_instr(xscale->jtag_info.chain_pos, 0x7f);
+       jtag_execute_queue();
+
+       /* assert reset */
+       jtag_add_reset(0, 1);
+
+       /* sleep 1ms, to be sure we fulfill any requirements */
+       jtag_add_sleep(1000);
+       jtag_execute_queue();
+
+       target->state = TARGET_RESET;
+
+       return ERROR_OK;
+}
+
+int xscale_deassert_reset(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       fileio_t debug_handler;
+       u32 address;
+       u32 binary_size;
+
+       u32 buf_cnt;
+       int i;
+       int retval;
+
+       breakpoint_t *breakpoint = target->breakpoints;
+
+       DEBUG("-");
+
+       xscale->ibcr_available = 2;
+       xscale->ibcr0_used = 0;
+       xscale->ibcr1_used = 0;
+
+       xscale->dbr_available = 2;
+       xscale->dbr0_used = 0;
+       xscale->dbr1_used = 0;
+
+       /* mark all hardware breakpoints as unset */
+       while (breakpoint)
+       {
+               if (breakpoint->type == BKPT_HARD)
+               {
+                       breakpoint->set = 0;
+               }
+               breakpoint = breakpoint->next;
+       }
+
+       if (!xscale->handler_installed)
+       {
+               /* release SRST */
+               jtag_add_reset(0, 0);
+
+               /* wait 300ms; 150 and 100ms were not enough */
+               jtag_add_sleep(300*1000);
+
+               jtag_add_runtest(2030, TAP_RTI);
+               jtag_execute_queue();
+
+               /* set Hold reset, Halt mode and Trap Reset */
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
+               xscale_write_dcsr(target, 1, 0);
+
+               /* Load debug handler */
+               if (fileio_open(&debug_handler, PKGLIBDIR "/xscale/debug_handler.bin", FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
+               {
+                       ERROR("file open error: %s", debug_handler.error_str);
+                       return ERROR_OK;
+               }
+
+               if ((binary_size = debug_handler.size) % 4)
+               {
+                       ERROR("debug_handler.bin: size not a multiple of 4");
+                       exit(-1);
+               }
+
+               if (binary_size > 0x800)
+               {
+                       ERROR("debug_handler.bin: larger than 2kb");
+                       exit(-1);
+               }
+
+               binary_size = CEIL(binary_size, 32) * 32;
+
+               address = xscale->handler_address;
+               while (binary_size > 0)
+               {
+                       u32 cache_line[8];
+                       u8 buffer[32];
+
+                       if ((retval = fileio_read(&debug_handler, 32, buffer, &buf_cnt)) != ERROR_OK)
+                       {
+                               ERROR("reading debug handler failed: %s", debug_handler.error_str);
+                       }
+
+                       for (i = 0; i < buf_cnt; i += 4)
+                       {
+                               /* convert LE buffer to host-endian u32 */
+                               cache_line[i / 4] = le_to_h_u32(&buffer[i]);
+                       }
+
+                       for (; buf_cnt < 32; buf_cnt += 4)
+                       {
+                                       cache_line[buf_cnt / 4] = 0xe1a08008;
+                       }
+
+                       /* only load addresses other than the reset vectors */
+                       if ((address % 0x400) != 0x0)
+                       {
+                               xscale_load_ic(target, 1, address, cache_line);
+                       }
+
+                       address += buf_cnt;
+                       binary_size -= buf_cnt;
+               };
+
+               xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
+               xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
+
+               jtag_add_runtest(30, TAP_RTI);
+
+               jtag_add_sleep(100000);
+
+               /* set Hold reset, Halt mode and Trap Reset */
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
+               xscale_write_dcsr(target, 1, 0);
+
+               /* clear Hold reset to let the target run (should enter debug handler) */
+               xscale_write_dcsr(target, 0, 1);
+               target->state = TARGET_RUNNING;
+
+               if ((target->reset_mode != RESET_HALT) && (target->reset_mode != RESET_INIT))
+               {
+                       jtag_add_sleep(10000);
+
+                       /* we should have entered debug now */
+                       xscale_debug_entry(target);
+                       target->state = TARGET_HALTED;
+
+                       /* resume the target */
+                       xscale_resume(target, 1, 0x0, 1, 0);
+               }
+
+               fileio_close(&debug_handler);
+       }
+       else
+       {
+               jtag_add_reset(0, 0);
+       }
+
+
+       return ERROR_OK;
+}
+
+int xscale_soft_reset_halt(struct target_s *target)
+{
+
+       return ERROR_OK;
+}
+
+int xscale_prepare_reset_halt(struct target_s *target)
+{
+       /* nothing to be done for reset_halt on XScale targets
+        * we always halt after a reset to upload the debug handler
+        */
+       return ERROR_OK;
+}
+
+int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)
+{
+
+       return ERROR_OK;
+}
+
+int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value)
+{
+
+       return ERROR_OK;
+}
+
+int xscale_full_context(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+
+       u32 *buffer;
+
+       int i, j;
+
+       DEBUG("-");
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       buffer = malloc(4 * 8);
+
+       /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)
+        * we can't enter User mode on an XScale (unpredictable),
+        * but User shares registers with SYS
+        */
+       for(i = 1; i < 7; i++)
+       {
+               int valid = 1;
+
+               /* check if there are invalid registers in the current mode
+                */
+               for (j = 0; j <= 16; j++)
+               {
+                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid == 0)
+                               valid = 0;
+               }
+
+               if (!valid)
+               {
+                       u32 tmp_cpsr;
+
+                       /* request banked registers */
+                       xscale_send_u32(target, 0x0);
+
+                       tmp_cpsr = 0x0;
+                       tmp_cpsr |= armv4_5_number_to_mode(i);
+                       tmp_cpsr |= 0xc0; /* I/F bits */
+
+                       /* send CPSR for desired mode */
+                       xscale_send_u32(target, tmp_cpsr);
+
+                       /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
+                       if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
+                       {
+                               xscale_receive(target, buffer, 8);
+                               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);
+                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
+                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).valid = 1;
+                       }
+                       else
+                       {
+                               xscale_receive(target, buffer, 7);
+                       }
+
+                       /* move data from buffer to register cache */
+                       for (j = 8; j <= 14; j++)
+                       {
+                               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).value, 0, 32, buffer[j - 8]);
+                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
+                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid = 1;
+                       }
+               }
+       }
+
+       free(buffer);
+
+       return ERROR_OK;
+}
+
+int xscale_restore_context(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+
+       int i, j;
+
+       DEBUG("-");
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)
+       * we can't enter User mode on an XScale (unpredictable),
+       * but User shares registers with SYS
+       */
+       for(i = 1; i < 7; i++)
+       {
+               int dirty = 0;
+
+               /* check if there are invalid registers in the current mode
+               */
+               for (j = 8; j <= 14; j++)
+               {
+                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty == 1)
+                               dirty = 1;
+               }
+
+               /* if not USR/SYS, check if the SPSR needs to be written */
+               if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
+               {
+                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty == 1)
+                               dirty = 1;
+               }
+
+               if (dirty)
+               {
+                       u32 tmp_cpsr;
+
+                       /* send banked registers */
+                       xscale_send_u32(target, 0x1);
+
+                       tmp_cpsr = 0x0;
+                       tmp_cpsr |= armv4_5_number_to_mode(i);
+                       tmp_cpsr |= 0xc0; /* I/F bits */
+
+                       /* send CPSR for desired mode */
+                       xscale_send_u32(target, tmp_cpsr);
+
+                       /* send banked registers, r8 to r14, and spsr if not in USR/SYS mode */
+                       for (j = 8; j <= 14; j++)
+                       {
+                               xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, j).value, 0, 32));
+                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
+                       }
+
+                       if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
+                       {
+                               xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32));
+                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u32 *buf32;
+       int i;
+
+       DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       /* send memory read request (command 0x1n, n: access size) */
+       xscale_send_u32(target, 0x10 | size);
+
+       /* send base address for read request */
+       xscale_send_u32(target, address);
+
+       /* send number of requested data words */
+       xscale_send_u32(target, count);
+
+       /* receive data from target (count times 32-bit words in host endianness) */
+       buf32 = malloc(4 * count);
+       xscale_receive(target, buf32, count);
+
+       /* extract data from host-endian buffer into byte stream */
+       for (i = 0; i < count; i++)
+       {
+               switch (size)
+               {
+                       case 4:
+                               target_buffer_set_u32(target, buffer, buf32[i]);
+                               buffer += 4;
+                               break;
+                       case 2:
+                               target_buffer_set_u16(target, buffer, buf32[i] & 0xffff);
+                               buffer += 2;
+                               break;
+                       case 1:
+                               *buffer++ = buf32[i] & 0xff;
+                               break;
+                       default:
+                               ERROR("should never get here");
+                               exit(-1);
+               }
+       }
+
+       free(buf32);
+
+       /* examine DCSR, to see if Sticky Abort (SA) got set */
+       xscale_read_dcsr(target);
+       if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)
+       {
+               /* clear SA bit */
+               xscale_send_u32(target, 0x60);
+
+               return ERROR_TARGET_DATA_ABORT;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+
+       /* send memory write request (command 0x2n, n: access size) */
+       xscale_send_u32(target, 0x20 | size);
+
+       /* send base address for read request */
+       xscale_send_u32(target, address);
+
+       /* send number of requested data words to be written*/
+       xscale_send_u32(target, count);
+
+       /* extract data from host-endian buffer into byte stream */
+#if 0
+       for (i = 0; i < count; i++)
+       {
+               switch (size)
+               {
+                       case 4:
+                               value = target_buffer_get_u32(target, buffer);
+                               xscale_send_u32(target, value);
+                               buffer += 4;
+                               break;
+                       case 2:
+                               value = target_buffer_get_u16(target, buffer);
+                               xscale_send_u32(target, value);
+                               buffer += 2;
+                               break;
+                       case 1:
+                               value = *buffer;
+                               xscale_send_u32(target, value);
+                               buffer += 1;
+                               break;
+                       default:
+                               ERROR("should never get here");
+                               exit(-1);
+               }
+       }
+#endif
+       xscale_send(target, buffer, count, size);
+
+       /* examine DCSR, to see if Sticky Abort (SA) got set */
+       xscale_read_dcsr(target);
+       if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)
+       {
+               /* clear SA bit */
+               xscale_send_u32(target, 0x60);
+
+               return ERROR_TARGET_DATA_ABORT;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
+{
+       return xscale_write_memory(target, address, 4, count, buffer);
+}
+
+int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+{
+       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+}
+
+u32 xscale_get_ttb(target_t *target)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u32 ttb;
+
+       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]);
+       ttb = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_TTB].value, 0, 32);
+
+       return ttb;
+}
+
+void xscale_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
+
+       if (mmu)
+               cp15_control &= ~0x1U;
+
+       if (d_u_cache)
+       {
+               /* clean DCache */
+               xscale_send_u32(target, 0x50);
+               xscale_send_u32(target, xscale->cache_clean_address);
+
+               /* invalidate DCache */
+               xscale_send_u32(target, 0x51);
+
+               cp15_control &= ~0x4U;
+       }
+
+       if (i_cache)
+       {
+               /* invalidate ICache */
+               xscale_send_u32(target, 0x52);
+               cp15_control &= ~0x1000U;
+       }
+
+       /* write new cp15 control register */
+       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+
+       /* execute cpwait to ensure outstanding operations complete */
+       xscale_send_u32(target, 0x53);
+}
+
+void xscale_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u32 cp15_control;
+
+       /* read cp15 control register */
+       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
+
+       if (mmu)
+               cp15_control |= 0x1U;
+
+       if (d_u_cache)
+               cp15_control |= 0x4U;
+
+       if (i_cache)
+               cp15_control |= 0x1000U;
+
+       /* write new cp15 control register */
+       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+
+       /* execute cpwait to ensure outstanding operations complete */
+       xscale_send_u32(target, 0x53);
+}
+
+int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (xscale->force_hw_bkpts)
+               breakpoint->type = BKPT_HARD;
+
+       if (breakpoint->set)
+       {
+               WARNING("breakpoint already set");
+               return ERROR_OK;
+       }
+
+       if (breakpoint->type == BKPT_HARD)
+       {
+               u32 value = breakpoint->address | 1;
+               if (!xscale->ibcr0_used)
+               {
+                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value);
+                       xscale->ibcr0_used = 1;
+                       breakpoint->set = 1;    /* breakpoint set on first breakpoint register */
+               }
+               else if (!xscale->ibcr1_used)
+               {
+                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value);
+                       xscale->ibcr1_used = 1;
+                       breakpoint->set = 2;    /* breakpoint set on second breakpoint register */
+               }
+               else
+               {
+                       ERROR("BUG: no hardware comparator available");
+                       return ERROR_OK;
+               }
+       }
+       else if (breakpoint->type == BKPT_SOFT)
+       {
+               if (breakpoint->length == 4)
+               {
+                       /* keep the original instruction in target endianness */
+                       target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       target_write_u32(target, breakpoint->address, xscale->arm_bkpt);
+               }
+               else
+               {
+                       /* keep the original instruction in target endianness */
+                       target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       target_write_u32(target, breakpoint->address, xscale->thumb_bkpt);
+               }
+               breakpoint->set = 1;
+       }
+
+       return ERROR_OK;
+
+}
+
+int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (xscale->force_hw_bkpts)
+       {
+               DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);
+               breakpoint->type = BKPT_HARD;
+       }
+
+       if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1))
+       {
+               INFO("no breakpoint unit available for hardware breakpoint");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+       else
+       {
+               xscale->ibcr_available--;
+       }
+
+       if ((breakpoint->length != 2) && (breakpoint->length != 4))
+       {
+               INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (!breakpoint->set)
+       {
+               WARNING("breakpoint not set");
+               return ERROR_OK;
+       }
+
+       if (breakpoint->type == BKPT_HARD)
+       {
+               if (breakpoint->set == 1)
+               {
+                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0);
+                       xscale->ibcr0_used = 0;
+               }
+               else if (breakpoint->set == 2)
+               {
+                       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0);
+                       xscale->ibcr1_used = 0;
+               }
+               breakpoint->set = 0;
+       }
+       else
+       {
+               /* restore original instruction (kept in target endianness) */
+               if (breakpoint->length == 4)
+               {
+                       target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+               }
+               else
+               {
+                       target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+               }
+               breakpoint->set = 0;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (breakpoint->set)
+       {
+               xscale_unset_breakpoint(target, breakpoint);
+       }
+
+       if (breakpoint->type == BKPT_HARD)
+               xscale->ibcr_available++;
+
+       return ERROR_OK;
+}
+
+int xscale_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u8 enable = 0;
+       reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
+       u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       xscale_get_reg(dbcon);
+
+       switch (watchpoint->rw)
+       {
+               case WPT_READ:
+                       enable = 0x3;
+                       break;
+               case WPT_ACCESS:
+                       enable = 0x2;
+                       break;
+               case WPT_WRITE:
+                       enable = 0x1;
+                       break;
+               default:
+                       ERROR("BUG: watchpoint->rw neither read, write nor access");
+       }
+
+       if (!xscale->dbr0_used)
+       {
+               xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address);
+               dbcon_value |= enable;
+               xscale_set_reg_u32(dbcon, dbcon_value);
+               watchpoint->set = 1;
+               xscale->dbr0_used = 1;
+       }
+       else if (!xscale->dbr1_used)
+       {
+               xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address);
+               dbcon_value |= enable << 2;
+               xscale_set_reg_u32(dbcon, dbcon_value);
+               watchpoint->set = 2;
+               xscale->dbr1_used = 1;
+       }
+       else
+       {
+               ERROR("BUG: no hardware comparator available");
+               return ERROR_OK;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (xscale->dbr_available < 1)
+       {
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
+       {
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       xscale->dbr_available--;
+
+       return ERROR_OK;
+}
+
+int xscale_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
+       u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (!watchpoint->set)
+       {
+               WARNING("breakpoint not set");
+               return ERROR_OK;
+       }
+
+       if (watchpoint->set == 1)
+       {
+               dbcon_value &= ~0x3;
+               xscale_set_reg_u32(dbcon, dbcon_value);
+               xscale->dbr0_used = 0;
+       }
+       else if (watchpoint->set == 2)
+       {
+               dbcon_value &= ~0xc;
+               xscale_set_reg_u32(dbcon, dbcon_value);
+               xscale->dbr1_used = 0;
+       }
+       watchpoint->set = 0;
+
+       return ERROR_OK;
+}
+
+int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (watchpoint->set)
+       {
+               xscale_unset_watchpoint(target, watchpoint);
+       }
+
+       xscale->dbr_available++;
+
+       return ERROR_OK;
+}
+
+void xscale_enable_watchpoints(struct target_s *target)
+{
+       watchpoint_t *watchpoint = target->watchpoints;
+
+       while (watchpoint)
+       {
+               if (watchpoint->set == 0)
+                       xscale_set_watchpoint(target, watchpoint);
+               watchpoint = watchpoint->next;
+       }
+}
+
+void xscale_enable_breakpoints(struct target_s *target)
+{
+       breakpoint_t *breakpoint = target->breakpoints;
+
+       /* set any pending breakpoints */
+       while (breakpoint)
+       {
+               if (breakpoint->set == 0)
+                       xscale_set_breakpoint(target, breakpoint);
+               breakpoint = breakpoint->next;
+       }
+}
+
+int xscale_get_reg(reg_t *reg)
+{
+       xscale_reg_t *arch_info = reg->arch_info;
+       target_t *target = arch_info->target;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       /* DCSR, TX and RX are accessible via JTAG */
+       if (strcmp(reg->name, "XSCALE_DCSR") == 0)
+       {
+               return xscale_read_dcsr(arch_info->target);
+       }
+       else if (strcmp(reg->name, "XSCALE_TX") == 0)
+       {
+               /* 1 = consume register content */
+               return xscale_read_tx(arch_info->target, 1);
+       }
+       else if (strcmp(reg->name, "XSCALE_RX") == 0)
+       {
+               /* can't read from RX register (host -> debug handler) */
+               return ERROR_OK;
+       }
+       else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0)
+       {
+               /* can't (explicitly) read from TXRXCTRL register */
+               return ERROR_OK;
+       }
+       else /* Other DBG registers have to be transfered by the debug handler */
+       {
+               /* send CP read request (command 0x40) */
+               xscale_send_u32(target, 0x40);
+
+               /* send CP register number */
+               xscale_send_u32(target, arch_info->dbg_handler_number);
+
+               /* read register value */
+               xscale_read_tx(target, 1);
+               buf_cpy(xscale->reg_cache->reg_list[XSCALE_TX].value, reg->value, 32);
+
+               reg->dirty = 0;
+               reg->valid = 1;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_set_reg(reg_t *reg, u8* buf)
+{
+       xscale_reg_t *arch_info = reg->arch_info;
+       target_t *target = arch_info->target;
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       u32 value = buf_get_u32(buf, 0, 32);
+
+       /* DCSR, TX and RX are accessible via JTAG */
+       if (strcmp(reg->name, "XSCALE_DCSR") == 0)
+       {
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32, value);
+               return xscale_write_dcsr(arch_info->target, -1, -1);
+       }
+       else if (strcmp(reg->name, "XSCALE_RX") == 0)
+       {
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
+               return xscale_write_rx(arch_info->target);
+       }
+       else if (strcmp(reg->name, "XSCALE_TX") == 0)
+       {
+               /* can't write to TX register (debug-handler -> host) */
+               return ERROR_OK;
+       }
+       else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0)
+       {
+               /* can't (explicitly) write to TXRXCTRL register */
+               return ERROR_OK;
+       }
+       else /* Other DBG registers have to be transfered by the debug handler */
+       {
+               /* send CP write request (command 0x41) */
+               xscale_send_u32(target, 0x41);
+
+               /* send CP register number */
+               xscale_send_u32(target, arch_info->dbg_handler_number);
+
+               /* send CP register value */
+               xscale_send_u32(target, value);
+               buf_set_u32(reg->value, 0, 32, value);
+       }
+
+       return ERROR_OK;
+}
+
+/* convenience wrapper to access XScale specific registers */
+int xscale_set_reg_u32(reg_t *reg, u32 value)
+{
+       u8 buf[4];
+
+       buf_set_u32(buf, 0, 32, value);
+
+       return xscale_set_reg(reg, buf);
+}
+
+int xscale_write_dcsr_sw(target_t *target, u32 value)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       reg_t *dcsr = &xscale->reg_cache->reg_list[XSCALE_DCSR];
+       xscale_reg_t *dcsr_arch_info = dcsr->arch_info;
+
+       /* send CP write request (command 0x41) */
+       xscale_send_u32(target, 0x41);
+
+       /* send CP register number */
+       xscale_send_u32(target, dcsr_arch_info->dbg_handler_number);
+
+       /* send CP register value */
+       xscale_send_u32(target, value);
+       buf_set_u32(dcsr->value, 0, 32, value);
+
+       return ERROR_OK;
+}
+
+int xscale_read_trace(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       xscale_trace_data_t **trace_data_p;
+
+       /* 258 words from debug handler
+        * 256 trace buffer entries
+        * 2 checkpoint addresses
+        */
+       u32 trace_buffer[258];
+       int is_address[256];
+       int i, j;
+
+       if (target->state != TARGET_HALTED)
+       {
+               WARNING("target must be stopped to read trace data");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* send read trace buffer command (command 0x61) */
+       xscale_send_u32(target, 0x61);
+
+       /* receive trace buffer content */
+       xscale_receive(target, trace_buffer, 258);
+
+       /* parse buffer backwards to identify address entries */
+       for (i = 255; i >= 0; i--)
+       {
+               is_address[i] = 0;
+               if (((trace_buffer[i] & 0xf0) == 0x90) ||
+                       ((trace_buffer[i] & 0xf0) == 0xd0))
+               {
+                       if (i >= 3)
+                               is_address[--i] = 1;
+                       if (i >= 2)
+                               is_address[--i] = 1;
+                       if (i >= 1)
+                               is_address[--i] = 1;
+                       if (i >= 0)
+                               is_address[--i] = 1;
+               }
+       }
+
+
+       /* search first non-zero entry */
+       for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)
+               ;
+
+       if (j == 256)
+       {
+               DEBUG("no trace data collected");
+               return ERROR_XSCALE_NO_TRACE_DATA;
+       }
+
+       for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next)
+               ;
+
+       *trace_data_p = malloc(sizeof(xscale_trace_data_t));
+       (*trace_data_p)->next = NULL;
+       (*trace_data_p)->chkpt0 = trace_buffer[256];
+       (*trace_data_p)->chkpt1 = trace_buffer[257];
+       (*trace_data_p)->last_instruction = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       (*trace_data_p)->entries = malloc(sizeof(xscale_trace_entry_t) * (256 - j));
+       (*trace_data_p)->depth = 256 - j;
+
+       for (i = j; i < 256; i++)
+       {
+               (*trace_data_p)->entries[i - j].data = trace_buffer[i];
+               if (is_address[i])
+                       (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS;
+               else
+                       (*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       int i;
+       int section = -1;
+       u32 size_read;
+       u32 opcode;
+       int retval;
+
+       if (!xscale->trace.image)
+               return ERROR_TRACE_IMAGE_UNAVAILABLE;
+
+       /* search for the section the current instruction belongs to */
+       for (i = 0; i < xscale->trace.image->num_sections; i++)
+       {
+               if ((xscale->trace.image->sections[i].base_address <= xscale->trace.current_pc) &&
+                       (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > xscale->trace.current_pc))
+               {
+                       section = i;
+                       break;
+               }
+       }
+
+       if (section == -1)
+       {
+               /* current instruction couldn't be found in the image */
+               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+       }
+
+       if (xscale->trace.core_state == ARMV4_5_STATE_ARM)
+       {
+               u8 buf[4];
+               if ((retval = image_read_section(xscale->trace.image, section,
+                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+                       4, buf, &size_read)) != ERROR_OK)
+               {
+                       ERROR("error while reading instruction: %i", retval);
+                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+               }
+               opcode = target_buffer_get_u32(target, buf);
+               arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+       }
+       else if (xscale->trace.core_state == ARMV4_5_STATE_THUMB)
+       {
+               u8 buf[2];
+               if ((retval = image_read_section(xscale->trace.image, section,
+                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+                       2, buf, &size_read)) != ERROR_OK)
+               {
+                       ERROR("error while reading instruction: %i", retval);
+                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+               }
+               opcode = target_buffer_get_u16(target, buf);
+               thumb_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+       }
+       else
+       {
+               ERROR("BUG: unknown core state encountered");
+               exit(-1);
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_branch_address(xscale_trace_data_t *trace_data, int i, u32 *target)
+{
+       /* if there are less than four entries prior to the indirect branch message
+        * we can't extract the address */
+       if (i < 4)
+       {
+               return -1;
+       }
+
+       *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
+                               (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
+
+       return 0;
+}
+
+int xscale_analyze_trace(target_t *target, command_context_t *cmd_ctx)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+       int next_pc_ok = 0;
+       u32 next_pc = 0x0;
+       xscale_trace_data_t *trace_data = xscale->trace.data;
+       int retval;
+
+       while (trace_data)
+       {
+               int i, chkpt;
+               int rollover;
+               int branch;
+               int exception;
+               xscale->trace.core_state = ARMV4_5_STATE_ARM;
+
+               chkpt = 0;
+               rollover = 0;
+
+               for (i = 0; i < trace_data->depth; i++)
+               {
+                       next_pc_ok = 0;
+                       branch = 0;
+                       exception = 0;
+
+                       if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
+                               continue;
+
+                       switch ((trace_data->entries[i].data & 0xf0) >> 4)
+                       {
+                               case 0:         /* Exceptions */
+                               case 1:
+                               case 2:
+                               case 3:
+                               case 4:
+                               case 5:
+                               case 6:
+                               case 7:
+                                       exception = (trace_data->entries[i].data & 0x70) >> 4;
+                                       next_pc_ok = 1;
+                                       next_pc = (trace_data->entries[i].data & 0xf0) >> 2;
+                                       command_print(cmd_ctx, "--- exception %i ---", (trace_data->entries[i].data & 0xf0) >> 4);
+                                       break;
+                               case 8:         /* Direct Branch */
+                                       branch = 1;
+                                       break;
+                               case 9:         /* Indirect Branch */
+                                       branch = 1;
+                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)
+                                       {
+                                               next_pc_ok = 1;
+                                       }
+                                       break;
+                               case 13:        /* Checkpointed Indirect Branch */
+                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)
+                                       {
+                                               next_pc_ok = 1;
+                                               if (((chkpt == 0) && (next_pc != trace_data->chkpt0))
+                                                       || ((chkpt == 1) && (next_pc != trace_data->chkpt1)))
+                                                       WARNING("checkpointed indirect branch target address doesn't match checkpoint");
+                                       }
+                                       /* explicit fall-through */
+                               case 12:        /* Checkpointed Direct Branch */
+                                       branch = 1;
+                                       if (chkpt == 0)
+                                       {
+                                               next_pc_ok = 1;
+                                               next_pc = trace_data->chkpt0;
+                                               chkpt++;
+                                       }
+                                       else if (chkpt == 1)
+                                       {
+                                               next_pc_ok = 1;
+                                               next_pc = trace_data->chkpt0;
+                                               chkpt++;
+                                       }
+                                       else
+                                       {
+                                               WARNING("more than two checkpointed branches encountered");
+                                       }
+                                       break;
+                               case 15:        /* Roll-over */
+                                       rollover++;
+                                       continue;
+                               default:        /* Reserved */
+                                       command_print(cmd_ctx, "--- reserved trace message ---");
+                                       ERROR("BUG: trace message %i is reserved", (trace_data->entries[i].data & 0xf0) >> 4);
+                                       return ERROR_OK;
+                       }
+
+                       if (xscale->trace.pc_ok)
+                       {
+                               int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;
+                               arm_instruction_t instruction;
+
+                               if ((exception == 6) || (exception == 7))
+                               {
+                                       /* IRQ or FIQ exception, no instruction executed */
+                                       executed -= 1;
+                               }
+
+                               while (executed-- >= 0)
+                               {
+                                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
+                                       {
+                                               /* can't continue tracing with no image available */
+                                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+                                               {
+                                                       return retval;
+                                               }
+                                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+                                               {
+                                                       /* TODO: handle incomplete images */
+                                               }
+                                       }
+
+                                       /* a precise abort on a load to the PC is included in the incremental
+                                        * word count, other instructions causing data aborts are not included
+                                        */
+                                       if ((executed == 0) && (exception == 4)
+                                               && ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDM)))
+                                       {
+                                               if ((instruction.type == ARM_LDM)
+                                                       && ((instruction.info.load_store_multiple.register_list & 0x8000) == 0))
+                                               {
+                                                       executed--;
+                                               }
+                                               else if (((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
+                                                       && (instruction.info.load_store.Rd != 15))
+                                               {
+                                                       executed--;
+                                               }
+                                       }
+
+                                       /* only the last instruction executed
+                                        * (the one that caused the control flow change)
+                                        * could be a taken branch
+                                        */
+                                       if (((executed == -1) && (branch == 1)) &&
+                                               (((instruction.type == ARM_B) ||
+                                                       (instruction.type == ARM_BL) ||
+                                                       (instruction.type == ARM_BLX)) &&
+                                                       (instruction.info.b_bl_bx_blx.target_address != -1)))
+                                       {
+                                               xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;
+                                       }
+                                       else
+                                       {
+                                               xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                                       }
+                                       command_print(cmd_ctx, "%s", instruction.text);
+                               }
+
+                               rollover = 0;
+                       }
+
+                       if (next_pc_ok)
+                       {
+                               xscale->trace.current_pc = next_pc;
+                               xscale->trace.pc_ok = 1;
+                       }
+               }
+
+               for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)
+               {
+                       arm_instruction_t instruction;
+                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
+                       {
+                               /* can't continue tracing with no image available */
+                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+                               {
+                                       return retval;
+                               }
+                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+                               {
+                                       /* TODO: handle incomplete images */
+                               }
+                       }
+                       command_print(cmd_ctx, "%s", instruction.text);
+               }
+
+               trace_data = trace_data->next;
+       }
+
+       return ERROR_OK;
+}
+
+void xscale_build_reg_cache(target_t *target)
+{
+       /* get pointers to arch-specific information */
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+       xscale_reg_t *arch_info = malloc(sizeof(xscale_reg_arch_info));
+       int i;
+       int num_regs = sizeof(xscale_reg_arch_info) / sizeof(xscale_reg_t);
+
+       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+       armv4_5->core_cache = (*cache_p);
+
+       /* register a register arch-type for XScale dbg registers only once */
+       if (xscale_reg_arch_type == -1)
+               xscale_reg_arch_type = register_reg_arch_type(xscale_get_reg, xscale_set_reg);
+
+       (*cache_p)->next = malloc(sizeof(reg_cache_t));
+       cache_p = &(*cache_p)->next;
+
+       /* fill in values for the xscale reg cache */
+       (*cache_p)->name = "XScale registers";
+       (*cache_p)->next = NULL;
+       (*cache_p)->reg_list = malloc(num_regs * sizeof(reg_t));
+       (*cache_p)->num_regs = num_regs;
+
+       for (i = 0; i < num_regs; i++)
+       {
+               (*cache_p)->reg_list[i].name = xscale_reg_list[i];
+               (*cache_p)->reg_list[i].value = calloc(4, 1);
+               (*cache_p)->reg_list[i].dirty = 0;
+               (*cache_p)->reg_list[i].valid = 0;
+               (*cache_p)->reg_list[i].size = 32;
+               (*cache_p)->reg_list[i].bitfield_desc = NULL;
+               (*cache_p)->reg_list[i].num_bitfields = 0;
+               (*cache_p)->reg_list[i].arch_info = &arch_info[i];
+               (*cache_p)->reg_list[i].arch_type = xscale_reg_arch_type;
+               arch_info[i] = xscale_reg_arch_info[i];
+               arch_info[i].target = target;
+       }
+
+       xscale->reg_cache = (*cache_p);
+}
+
+int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+       if (startup_mode != DAEMON_RESET)
+       {
+               ERROR("XScale target requires a reset");
+               ERROR("Reset target to enable debug");
+       }
+
+       /* assert TRST once during startup */
+       jtag_add_reset(1, 0);
+       jtag_add_sleep(5000);
+       jtag_add_reset(0, 0);
+       jtag_execute_queue();
+
+       return ERROR_OK;
+}
+
+int xscale_quit()
+{
+
+       return ERROR_OK;
+}
+
+int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_pos, char *variant)
+{
+       armv4_5_common_t *armv4_5;
+       u32 high_reset_branch, low_reset_branch;
+       int i;
+
+       armv4_5 = &xscale->armv4_5_common;
+
+       /* store architecture specfic data (none so far) */
+       xscale->arch_info = NULL;
+       xscale->common_magic = XSCALE_COMMON_MAGIC;
+
+       /* remember the variant (PXA25x, PXA27x, IXP42x, ...) */
+       xscale->variant = strdup(variant);
+
+       /* prepare JTAG information for the new target */
+       xscale->jtag_info.chain_pos = chain_pos;
+       jtag_register_event_callback(xscale_jtag_callback, target);
+
+       xscale->jtag_info.dbgrx = 0x02;
+       xscale->jtag_info.dbgtx = 0x10;
+       xscale->jtag_info.dcsr = 0x09;
+       xscale->jtag_info.ldic = 0x07;
+
+       if ((strcmp(xscale->variant, "pxa250") == 0) ||
+               (strcmp(xscale->variant, "pxa255") == 0) ||
+               (strcmp(xscale->variant, "pxa26x") == 0))
+       {
+               xscale->jtag_info.ir_length = 5;
+       }
+       else if ((strcmp(xscale->variant, "pxa27x") == 0) ||
+               (strcmp(xscale->variant, "ixp42x") == 0) ||
+               (strcmp(xscale->variant, "ixp45x") == 0) ||
+               (strcmp(xscale->variant, "ixp46x") == 0))
+       {
+               xscale->jtag_info.ir_length = 7;
+       }
+
+       /* the debug handler isn't installed (and thus not running) at this time */
+       xscale->handler_installed = 0;
+       xscale->handler_running = 0;
+       xscale->handler_address = 0xfe000800;
+
+       /* clear the vectors we keep locally for reference */
+       memset(xscale->low_vectors, 0, sizeof(xscale->low_vectors));
+       memset(xscale->high_vectors, 0, sizeof(xscale->high_vectors));
+
+       /* no user-specified vectors have been configured yet */
+       xscale->static_low_vectors_set = 0x0;
+       xscale->static_high_vectors_set = 0x0;
+
+       /* calculate branches to debug handler */
+       low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
+       high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
+
+       xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
+       xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
+
+       for (i = 1; i <= 7; i++)
+       {
+               xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+               xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+       }
+
+       /* 64kB aligned region used for DCache cleaning */
+       xscale->cache_clean_address = 0xfffe0000;
+
+       xscale->hold_rst = 0;
+       xscale->external_debug_break = 0;
+
+       xscale->force_hw_bkpts = 1;
+
+       xscale->ibcr_available = 2;
+       xscale->ibcr0_used = 0;
+       xscale->ibcr1_used = 0;
+
+       xscale->dbr_available = 2;
+       xscale->dbr0_used = 0;
+       xscale->dbr1_used = 0;
+
+       xscale->arm_bkpt = ARMV5_BKPT(0x0);
+       xscale->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
+
+       xscale->vector_catch = 0x1;
+
+       xscale->trace.capture_status = TRACE_IDLE;
+       xscale->trace.data = NULL;
+       xscale->trace.image = NULL;
+       xscale->trace.buffer_enabled = 0;
+       xscale->trace.buffer_fill = 0;
+
+       /* prepare ARMv4/5 specific information */
+       armv4_5->arch_info = xscale;
+       armv4_5->read_core_reg = xscale_read_core_reg;
+       armv4_5->write_core_reg = xscale_write_core_reg;
+       armv4_5->full_context = xscale_full_context;
+
+       armv4_5_init_arch_info(target, armv4_5);
+
+       xscale->armv4_5_mmu.armv4_5_cache.ctype = -1;
+       xscale->armv4_5_mmu.get_ttb = xscale_get_ttb;
+       xscale->armv4_5_mmu.read_memory = xscale_read_memory;
+       xscale->armv4_5_mmu.write_memory = xscale_write_memory;
+       xscale->armv4_5_mmu.disable_mmu_caches = xscale_disable_mmu_caches;
+       xscale->armv4_5_mmu.enable_mmu_caches = xscale_enable_mmu_caches;
+       xscale->armv4_5_mmu.has_tiny_pages = 1;
+       xscale->armv4_5_mmu.mmu_enabled = 0;
+
+       xscale->fast_memory_access = 0;
+
+       return ERROR_OK;
+}
+
+/* target xscale <endianess> <startup_mode> <chain_pos> <variant> */
+int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+       int chain_pos;
+       char *variant = NULL;
+       xscale_common_t *xscale = malloc(sizeof(xscale_common_t));
+
+       if (argc < 5)
+       {
+               ERROR("'target xscale' requires four arguments: <endianess> <startup_mode> <chain_pos> <variant>");
+               return ERROR_OK;
+       }
+
+       chain_pos = strtoul(args[3], NULL, 0);
+
+       variant = args[4];
+
+       xscale_init_arch_info(target, xscale, chain_pos, variant);
+       xscale_build_reg_cache(target);
+
+       return ERROR_OK;
+}
+
+int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = NULL;
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       u32 handler_address;
+
+       if (argc < 2)
+       {
+               ERROR("'xscale debug_handler <target#> <address>' command takes two required operands");
+               return ERROR_OK;
+       }
+
+       if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)
+       {
+               ERROR("no target '%s' configured", args[0]);
+               return ERROR_OK;
+       }
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       handler_address = strtoul(args[1], NULL, 0);
+
+       if (((handler_address >= 0x800) && (handler_address <= 0x1fef800)) ||
+               ((handler_address >= 0xfe000800) && (handler_address <= 0xfffff800)))
+       {
+               xscale->handler_address = handler_address;
+       }
+       else
+       {
+               ERROR("xscale debug_handler <address> must be between 0x800 and 0x1fef800 or between 0xfe000800 and 0xfffff800");
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = NULL;
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       u32 cache_clean_address;
+
+       if (argc < 2)
+       {
+               ERROR("'xscale cache_clean_address <target#> <address>' command takes two required operands");
+               return ERROR_OK;
+       }
+
+       if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)
+       {
+               ERROR("no target '%s' configured", args[0]);
+               return ERROR_OK;
+       }
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       cache_clean_address = strtoul(args[1], NULL, 0);
+
+       if (cache_clean_address & 0xffff)
+       {
+               ERROR("xscale cache_clean_address <address> must be 64kb aligned");
+       }
+       else
+       {
+               xscale->cache_clean_address = cache_clean_address;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);
+}
+
+static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+       int retval;
+       int type;
+       u32 cb;
+       int domain;
+       u32 ap;
+       
+       if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK)
+       {
+               return retval;
+       }
+       u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
+       if (type == -1)
+       {
+               return ret;
+       }
+       
+       *physical = ret;
+       return ERROR_OK;
+}
+
+static int xscale_mmu(struct target_s *target, int *enabled)
+{
+       armv4_5_common_t *armv4_5 = target->arch_info;
+       xscale_common_t *xscale = armv4_5->arch_info;
+
+       if (target->state != TARGET_HALTED)
+       {
+               ERROR("Target not halted");
+               return ERROR_TARGET_INVALID;
+       }
+       
+       *enabled = xscale->armv4_5_mmu.mmu_enabled;
+       return ERROR_OK;
+}
+
+int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       if (argc >= 1)
+       {
+               if (strcmp("enable", args[0]) == 0)
+               {
+                       xscale_enable_mmu_caches(target, 1, 0, 0);
+                       xscale->armv4_5_mmu.mmu_enabled = 1;
+               }
+               else if (strcmp("disable", args[0]) == 0)
+               {
+                       xscale_disable_mmu_caches(target, 1, 0, 0);
+                       xscale->armv4_5_mmu.mmu_enabled = 0;
+               }
+       }
+
+       command_print(cmd_ctx, "mmu %s", (xscale->armv4_5_mmu.mmu_enabled) ? "enabled" : "disabled");
+
+       return ERROR_OK;
+}
+
+int xscale_handle_idcache_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+       int icache = 0, dcache = 0;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       if (strcmp(cmd, "icache") == 0)
+               icache = 1;
+       else if (strcmp(cmd, "dcache") == 0)
+               dcache = 1;
+
+       if (argc >= 1)
+       {
+               if (strcmp("enable", args[0]) == 0)
+               {
+                       xscale_enable_mmu_caches(target, 0, dcache, icache);
+
+                       if (icache)
+                               xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 1;
+                       else if (dcache)
+                               xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 1;
+               }
+               else if (strcmp("disable", args[0]) == 0)
+               {
+                       xscale_disable_mmu_caches(target, 0, dcache, icache);
+
+                       if (icache)
+                               xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+                       else if (dcache)
+                               xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+               }
+       }
+
+       if (icache)
+               command_print(cmd_ctx, "icache %s", (xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled) ? "enabled" : "disabled");
+
+       if (dcache)
+               command_print(cmd_ctx, "dcache %s", (xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) ? "enabled" : "disabled");
+
+       return ERROR_OK;
+}
+
+int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: xscale vector_catch [mask]");
+       }
+       else
+       {
+               xscale->vector_catch = strtoul(args[0], NULL, 0);
+               buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 8, xscale->vector_catch);
+               xscale_write_dcsr(target, -1, -1);
+       }
+
+       command_print(cmd_ctx, "vector catch mask: 0x%2.2x", xscale->vector_catch);
+
+       return ERROR_OK;
+}
+
+int xscale_handle_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
+       {
+               xscale->force_hw_bkpts = 1;
+       }
+       else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
+       {
+               xscale->force_hw_bkpts = 0;
+       }
+       else
+       {
+               command_print(cmd_ctx, "usage: xscale force_hw_bkpts <enable|disable>");
+       }
+
+       command_print(cmd_ctx, "force hardware breakpoints %s", (xscale->force_hw_bkpts) ? "enabled" : "disabled");
+
+       return ERROR_OK;
+}
+
+int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+       u32 dcsr_value;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
+       {
+               xscale_trace_data_t *td, *next_td;
+               xscale->trace.buffer_enabled = 1;
+
+               /* free old trace data */
+               td = xscale->trace.data;
+               while (td)
+               {
+                       next_td = td->next;
+
+                       if (td->entries)
+                               free(td->entries);
+                       free(td);
+                       td = next_td;
+               }
+               xscale->trace.data = NULL;
+       }
+       else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
+       {
+               xscale->trace.buffer_enabled = 0;
+       }
+
+       if ((argc >= 2) && (strcmp("fill", args[1]) == 0))
+       {
+               if (argc >= 3)
+                       xscale->trace.buffer_fill = strtoul(args[2], NULL, 0);
+               else
+                       xscale->trace.buffer_fill = 1;
+       }
+       else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))
+       {
+               xscale->trace.buffer_fill = -1;
+       }
+
+       if (xscale->trace.buffer_enabled)
+       {
+               /* if we enable the trace buffer in fill-once
+                * mode we know the address of the first instruction */
+               xscale->trace.pc_ok = 1;
+               xscale->trace.current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       }
+       else
+       {
+               /* otherwise the address is unknown, and we have no known good PC */
+               xscale->trace.pc_ok = 0;
+       }
+
+       command_print(cmd_ctx, "trace buffer %s (%s)",
+               (xscale->trace.buffer_enabled) ? "enabled" : "disabled",
+               (xscale->trace.buffer_fill > 0) ? "fill" : "wrap");
+
+       dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
+       if (xscale->trace.buffer_fill >= 0)
+               xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
+       else
+               xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
+
+       return ERROR_OK;
+}
+
+int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target;
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: xscale trace_image <file> [base address] [type]");
+               return ERROR_OK;
+       }
+
+       target = get_current_target(cmd_ctx);
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if (xscale->trace.image)
+       {
+               image_close(xscale->trace.image);
+               free(xscale->trace.image);
+               command_print(cmd_ctx, "previously loaded image found and closed");
+       }
+
+       xscale->trace.image = malloc(sizeof(image_t));
+       xscale->trace.image->base_address_set = 0;
+       xscale->trace.image->start_address_set = 0;
+
+       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       if (argc >= 2)
+       {
+               xscale->trace.image->base_address_set = 1;
+               xscale->trace.image->base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               xscale->trace.image->base_address_set = 0;
+       }
+
+       if (image_open(xscale->trace.image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "image opening error: %s", xscale->trace.image->error_str);
+               free(xscale->trace.image);
+               xscale->trace.image = NULL;
+               return ERROR_OK;
+       }
+
+       return ERROR_OK;
+}
+
+int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+       xscale_trace_data_t *trace_data;
+       fileio_t file;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: xscale dump_trace <file>");
+               return ERROR_OK;
+       }
+
+       trace_data = xscale->trace.data;
+
+       if (!trace_data)
+       {
+               command_print(cmd_ctx, "no trace data collected");
+               return ERROR_OK;
+       }
+
+       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "file open error: %s", file.error_str);
+               return ERROR_OK;
+       }
+
+       while (trace_data)
+       {
+               int i;
+
+               fileio_write_u32(&file, trace_data->chkpt0);
+               fileio_write_u32(&file, trace_data->chkpt1);
+               fileio_write_u32(&file, trace_data->last_instruction);
+               fileio_write_u32(&file, trace_data->depth);
+
+               for (i = 0; i < trace_data->depth; i++)
+                       fileio_write_u32(&file, trace_data->entries[i].data | ((trace_data->entries[i].type & 0xffff) << 16));
+
+               trace_data = trace_data->next;
+       }
+
+       fileio_close(&file);
+
+       return ERROR_OK;
+}
+
+int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       xscale_analyze_trace(target, cmd_ctx);
+
+       return ERROR_OK;
+}
+
+int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+       
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+       
+       if (target->state != TARGET_HALTED)
+       {
+               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               return ERROR_OK;
+       }
+       u32 reg_no = 0;
+       reg_t *reg = NULL;
+       if(argc > 0)
+       {
+               reg_no = strtoul(args[0], NULL, 0);
+               /*translate from xscale cp15 register no to openocd register*/
+               switch(reg_no)
+               {
+               case 0:
+                       reg_no = XSCALE_MAINID;
+                       break;
+               case 1:
+                       reg_no = XSCALE_CTRL;
+                       break;
+               case 2:
+                       reg_no = XSCALE_TTB;
+                       break; 
+               case 3:
+                       reg_no = XSCALE_DAC;
+                       break;
+               case 5:
+                       reg_no = XSCALE_FSR;
+                       break;
+               case 6:
+                       reg_no = XSCALE_FAR;
+                       break;
+               case 13:
+                       reg_no = XSCALE_PID;
+                       break;
+               case 15:
+                       reg_no = XSCALE_CPACCESS;
+                       break;
+               default:
+                       command_print(cmd_ctx, "invalid register number");
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+               reg = &xscale->reg_cache->reg_list[reg_no];
+               
+       }
+       if(argc == 1)
+       {
+               u32 value;
+               
+               /* read cp15 control register */
+               xscale_get_reg(reg);
+               value = buf_get_u32(reg->value, 0, 32);
+               command_print(cmd_ctx, "%s (/%i): 0x%x", reg->name, reg->size, value);
+       }
+       else if(argc == 2)
+       {   
+
+               u32 value = strtoul(args[1], NULL, 0);
+               
+               /* send CP write request (command 0x41) */
+               xscale_send_u32(target, 0x41);
+               
+               /* send CP register number */
+               xscale_send_u32(target, reg_no);
+               
+               /* send CP register value */
+               xscale_send_u32(target, value);
+               
+               /* execute cpwait to ensure outstanding operations complete */
+               xscale_send_u32(target, 0x53);
+       }
+       else
+       {
+               command_print(cmd_ctx, "usage: cp15 [register]<, [value]>");    
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_xscale_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       armv4_5_common_t *armv4_5;
+       xscale_common_t *xscale;
+       
+       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+       
+       if (argc == 1)
+       {
+               if (strcmp("enable", args[0]) == 0)
+               {
+                       xscale->fast_memory_access = 1;
+               }
+               else if (strcmp("disable", args[0]) == 0)
+               {
+                       xscale->fast_memory_access = 0;
+               }
+               else
+               {
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               }
+       } else if (argc!=0)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+               
+       command_print(cmd_ctx, "fast memory access is %s", (xscale->fast_memory_access) ? "enabled" : "disabled");
+
+       return ERROR_OK;
+}
+
+int xscale_register_commands(struct command_context_s *cmd_ctx)
+{
+       command_t *xscale_cmd;
+
+       xscale_cmd = register_command(cmd_ctx, NULL, "xscale", NULL, COMMAND_ANY, "xscale specific commands");
+
+       register_command(cmd_ctx, xscale_cmd, "debug_handler", xscale_handle_debug_handler_command, COMMAND_ANY, "'xscale debug_handler <target#> <address>' command takes two required operands");
+       register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);
+
+       register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);
+       register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");
+       register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");
+       register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");
+
+       register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_idcache_command, COMMAND_EXEC, "<mask> of vectors that should be catched");
+
+       register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable|disable> ['fill' [n]|'wrap']");
+
+       register_command(cmd_ctx, xscale_cmd, "dump_trace", xscale_handle_dump_trace_command, COMMAND_EXEC, "dump content of trace buffer to <file>");
+       register_command(cmd_ctx, xscale_cmd, "analyze_trace", xscale_handle_analyze_trace_buffer_command, COMMAND_EXEC, "analyze content of trace buffer");
+       register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,
+               COMMAND_EXEC, "load image from <file> [base address]");
+
+       register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");
+       register_command(cmd_ctx, xscale_cmd, "fast_memory_access", handle_xscale_fast_memory_access_command,
+                COMMAND_ANY, "use fast memory accesses instead of slower but potentially unsafe slow accesses <enable|disable>");
+       
+       armv4_5_register_commands(cmd_ctx);
+
+       return ERROR_OK;
+}
index 298377d9d52c25053388a28f2b91c0053324ad70..b589a8a75de6069f8feb4f32f5aa16dc95e6144e 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\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 "xsvf.h"\r
-\r
-#include "jtag.h"\r
-#include "command.h"\r
-#include "log.h"\r
-\r
-#include <stdlib.h>\r
-#include <unistd.h>\r
-#include <sys/types.h>\r
-#include <sys/stat.h>\r
-#include <fcntl.h>\r
-#include <string.h>\r
-\r
-#include <sys/time.h>\r
-#include <time.h>\r
-\r
-#define XSTATE_MAX_PATH (12)\r
-\r
-int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
-\r
-int xsvf_fd = 0;\r
-\r
-u8 *dr_out_buf;        /* from host to device (TDI) */\r
-u8 *dr_in_buf; /* from device to host (TDO) */\r
-u8 *dr_in_mask;\r
-\r
-int xsdrsize = 0;\r
-int xruntest = 0;      /* number of TCK cycles / microseconds */\r
-int xrepeat = 0x20; /* number of XC9500 retries */\r
-\r
-int xendir = 0;\r
-int xenddr = 0;\r
-\r
-enum tap_state xsvf_to_tap[] =\r
-{\r
-       TAP_TLR, TAP_RTI,\r
-       TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD,\r
-       TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI,\r
-};\r
-\r
-int tap_to_xsvf[] =\r
-{\r
-       0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf\r
-};\r
-\r
-int xsvf_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,\r
-               COMMAND_EXEC, "run xsvf <file>");\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xsvf_read_buffer(int num_bits, int fd, u8* buf)\r
-{\r
-       int num_bytes;\r
-\r
-       for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--)\r
-       {\r
-               if (read(fd, buf + num_bytes - 1, 1) < 0)\r
-                       return ERROR_XSVF_EOF;\r
-       }\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len)\r
-{\r
-       char c;\r
-       unsigned char uc;\r
-       \r
-       while ((read(fd, &c, 1) > 0) && (c == 0x12))\r
-       {\r
-               if (*path_len > max_path)\r
-               {\r
-                       WARNING("XSTATE path longer than max_path");\r
-                       break;\r
-               }\r
-               if (read(fd, &uc, 1) < 0)\r
-               {\r
-                       return ERROR_XSVF_EOF;\r
-               }\r
-               path[(*path_len)++] = xsvf_to_tap[uc];\r
-       }\r
-       \r
-       lseek(fd, -1, SEEK_CUR);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       char c;\r
-       u8 buf4[4], buf2[2];\r
-       unsigned char uc, uc2;\r
-       unsigned int ui;\r
-       unsigned short us;\r
-\r
-       int do_abort = 0;\r
-       int unsupported = 0;\r
-       int tdo_mismatch = 0;\r
-       \r
-       int runtest_requires_tck = 0;\r
-       \r
-       int device = -1;        /* use -1 to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device that should be affected */\r
-\r
-       if (argc < 2)\r
-       {\r
-               command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (strcmp(args[0], "plain") != 0)\r
-       {\r
-               device = strtoul(args[0], NULL, 0);\r
-       }\r
-\r
-       if ((xsvf_fd = open(args[1], O_RDONLY)) < 0)\r
-       {\r
-               command_print(cmd_ctx, "file %s not found", args[0]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if ((argc > 2) && (strcmp(args[2], "virt2") == 0))\r
-       {\r
-               runtest_requires_tck = 1;\r
-       }\r
-\r
-       while (read(xsvf_fd, &c, 1) > 0)\r
-       {\r
-               switch (c)\r
-               {\r
-                       case 0x00:      /* XCOMPLETE */\r
-                               DEBUG("XCOMPLETE");\r
-                               if (jtag_execute_queue() != ERROR_OK)\r
-                               {\r
-                                       tdo_mismatch = 1;\r
-                                       break;  \r
-                               }\r
-                               break;\r
-                       case 0x01:      /* XTDOMASK */\r
-                               DEBUG("XTDOMASK");\r
-                               if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))\r
-                                       do_abort = 1;\r
-                               break;\r
-                       case 0x02:      /* XSIR */\r
-                               DEBUG("XSIR");\r
-                               if (read(xsvf_fd, &c, 1) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       u8 *ir_buf = malloc((c + 7) / 8);\r
-                                       if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK)\r
-                                               do_abort = 1;\r
-                                       else\r
-                                       {\r
-                                               scan_field_t field;\r
-                                               field.device = device;\r
-                                               field.num_bits = c;\r
-                                               field.out_value = ir_buf;\r
-                                               field.out_mask = NULL;\r
-                                               field.in_value = NULL;\r
-                                               field.in_check_value = NULL;\r
-                                               field.in_check_mask = NULL;\r
-                                               field.in_handler = NULL;\r
-                                               field.in_handler_priv = NULL;\r
-                                               if (device == -1)\r
-                                                       jtag_add_plain_ir_scan(1, &field, TAP_PI);\r
-                                               else\r
-                                                       jtag_add_ir_scan(1, &field, TAP_PI);\r
-                                               if (jtag_execute_queue() != ERROR_OK)\r
-                                               {\r
-                                                       tdo_mismatch = 1;\r
-                                                       free(ir_buf);\r
-                                                       break;\r
-                                               }\r
-                                               if (xruntest)\r
-                                               {\r
-                                                       if (runtest_requires_tck)\r
-                                                               jtag_add_runtest(xruntest, xsvf_to_tap[xendir]);\r
-                                                       else\r
-                                                       {\r
-                                                               jtag_add_statemove(TAP_RTI);\r
-                                                               jtag_add_sleep(xruntest);\r
-                                                               jtag_add_statemove(xsvf_to_tap[xendir]);\r
-                                                       }\r
-                                               }\r
-                                               else if (xendir != 0xd) /* Pause-IR */\r
-                                                       jtag_add_statemove(xsvf_to_tap[xendir]);\r
-                                       }\r
-                                       free(ir_buf);\r
-                               }\r
-                               break;\r
-                       case 0x03:      /* XSDR */\r
-                               DEBUG("XSDR");\r
-                               if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       scan_field_t field;\r
-                                       field.device = device;\r
-                                       field.num_bits = xsdrsize;\r
-                                       field.out_value = dr_out_buf;\r
-                                       field.out_mask = NULL;\r
-                                       field.in_value = NULL;\r
-                                       jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);\r
-                                       if (device == -1)\r
-                                               jtag_add_plain_dr_scan(1, &field, TAP_PD);\r
-                                       else\r
-                                               jtag_add_dr_scan(1, &field, TAP_PD);\r
-                                       if (jtag_execute_queue() != ERROR_OK)\r
-                                       {\r
-                                               tdo_mismatch = 1;\r
-                                               break;  \r
-                                       }\r
-                                       if (xruntest)\r
-                                       {\r
-                                               if (runtest_requires_tck)\r
-                                                       jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);\r
-                                               else\r
-                                               {\r
-                                                       jtag_add_statemove(TAP_RTI);\r
-                                                       jtag_add_sleep(xruntest);\r
-                                                       jtag_add_statemove(xsvf_to_tap[xenddr]);\r
-                                               }\r
-                                       }\r
-                                       else if (xendir != 0x6) /* Pause-DR */\r
-                                               jtag_add_statemove(xsvf_to_tap[xenddr]);\r
-                               }\r
-                               break;\r
-                       case 0x04:      /* XRUNTEST */\r
-                               DEBUG("XRUNTEST");\r
-                               if (read(xsvf_fd, buf4, 4) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       xruntest = be_to_h_u32(buf4);\r
-                               }\r
-                               break;\r
-                       case 0x07:      /* XREPEAT */\r
-                               DEBUG("XREPEAT");\r
-                               if (read(xsvf_fd, &c, 1) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       xrepeat = c;\r
-                               }\r
-                               break;\r
-                       case 0x08:      /* XSDRSIZE */\r
-                               DEBUG("XSDRSIZE");\r
-                               if (read(xsvf_fd, buf4, 4) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       xsdrsize = be_to_h_u32(buf4);\r
-                                       free(dr_out_buf);\r
-                                       free(dr_in_buf);\r
-                                       free(dr_in_mask);\r
-                                       dr_out_buf = malloc((xsdrsize + 7) / 8);\r
-                                       dr_in_buf = malloc((xsdrsize + 7) / 8);\r
-                                       dr_in_mask = malloc((xsdrsize + 7) / 8);\r
-                               }\r
-                               break;\r
-                       case 0x09:      /* XSDRTDO */\r
-                               DEBUG("XSDRTDO");\r
-                               if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)\r
-                                               do_abort = 1;\r
-                                       else\r
-                                       {\r
-                                               scan_field_t field;\r
-                                               field.device = device;\r
-                                               field.num_bits = xsdrsize;\r
-                                               field.out_value = dr_out_buf;\r
-                                               field.out_mask = NULL;\r
-                                               field.in_value = NULL;\r
-                                               jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);\r
-                                               if (device == -1)\r
-                                                       jtag_add_plain_dr_scan(1, &field, TAP_PD);\r
-                                               else\r
-                                                       jtag_add_dr_scan(1, &field, TAP_PD);\r
-                                               if (jtag_execute_queue() != ERROR_OK)\r
-                                               {\r
-                                                       tdo_mismatch = 1;\r
-                                                       break;  \r
-                                               }\r
-                                               if (xruntest)\r
-                                               {\r
-                                                       if (runtest_requires_tck)\r
-                                                               jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);\r
-                                                       else\r
-                                                       {\r
-                                                               jtag_add_statemove(TAP_RTI);\r
-                                                               jtag_add_sleep(xruntest);\r
-                                                               jtag_add_statemove(xsvf_to_tap[xenddr]);\r
-                                                       }\r
-                                               }\r
-                                               else if (xendir != 0x6) /* Pause-DR */\r
-                                                       jtag_add_statemove(xsvf_to_tap[xenddr]);\r
-                                       }\r
-                               }\r
-                               break;\r
-                       case 0x0a:      /* XSETDRMASKS */\r
-                               ERROR("unsupported XSETSDRMASKS\n");\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x0b:      /* XSDRINC */\r
-                               ERROR("unsupported XSDRINC\n");\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x0c:      /* XSDRB */\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x0d:      /* XSDRC */\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x0e:      /* XSDRE */\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x0f:      /* XSDRTDOB */\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x10:      /* XSDRTDOB */\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x11:      /* XSDRTDOB */\r
-                               unsupported = 1;\r
-                               break;\r
-                       case 0x12:      /* XSTATE */\r
-                               DEBUG("XSTATE");\r
-                               if (read(xsvf_fd, &uc, 1) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);\r
-                                       int path_len = 1;\r
-                                       path[0] = xsvf_to_tap[uc];\r
-                                       if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)\r
-                                               do_abort = 1;\r
-                                       else\r
-                                       {\r
-                                               jtag_add_pathmove(path_len, path);\r
-                                       }\r
-                                       free(path);\r
-                               }\r
-                               break;\r
-                       case 0x13:      /* XENDIR */\r
-                               DEBUG("XENDIR");\r
-                               if (read(xsvf_fd, &c, 1) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       if (c == 0)\r
-                                               xendir = 1;\r
-                                       else if (c == 1)\r
-                                               xendir = 0xd;\r
-                                       else\r
-                                       {\r
-                                               ERROR("unknown XENDIR endstate");\r
-                                               unsupported = 1;\r
-                                       }\r
-                               }\r
-                               break;\r
-                       case 0x14:      /* XENDDR */\r
-                               DEBUG("XENDDR");\r
-                               if (read(xsvf_fd, &c, 1) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       if (c == 0)\r
-                                               xenddr = 1;\r
-                                       else if (c == 1)\r
-                                               xenddr = 0x6;\r
-                                       else\r
-                                       {\r
-                                               ERROR("unknown XENDDR endstate");\r
-                                               unsupported = 1;\r
-                                       }\r
-                               }\r
-                               break;\r
-                       case 0x15:      /* XSIR2 */\r
-                               DEBUG("XSIR2");\r
-                               if (read(xsvf_fd, buf2, 2) < 0)\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       u8 *ir_buf;\r
-                                       us = be_to_h_u16(buf2);\r
-                                       ir_buf = malloc((us + 7) / 8);\r
-                                       if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)\r
-                                               do_abort = 1;\r
-                                       else\r
-                                       {\r
-                                               scan_field_t field;\r
-                                               field.device = device;\r
-                                               field.num_bits = us;\r
-                                               field.out_value = ir_buf;\r
-                                               field.out_mask = NULL;\r
-                                               field.in_value = NULL;\r
-                                               field.in_check_value = NULL;\r
-                                               field.in_check_mask = NULL;\r
-                                               field.in_handler = NULL;\r
-                                               field.in_handler_priv = NULL;\r
-                                               if (device == -1)\r
-                                                       jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);\r
-                                               else\r
-                                                       jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);\r
-                                       }\r
-                                       free(ir_buf);\r
-                               }\r
-                               break;\r
-                       case 0x16:      /* XCOMMENT */\r
-                               do\r
-                               {\r
-                                       if (read(xsvf_fd, &c, 1) < 0)\r
-                                       {\r
-                                               do_abort = 1;\r
-                                               break;\r
-                                       }\r
-                               } while (c != 0);\r
-                               break;\r
-                       case 0x17:      /* XWAIT */\r
-                               DEBUG("XWAIT");\r
-                               if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))\r
-                                       do_abort = 1;\r
-                               else\r
-                               {\r
-                                       jtag_add_statemove(xsvf_to_tap[uc]);\r
-                                       ui = be_to_h_u32(buf4);\r
-                                       jtag_add_sleep(ui);\r
-                                       jtag_add_statemove(xsvf_to_tap[uc2]);\r
-                               }\r
-                               break;\r
-                       default:\r
-                               ERROR("unknown xsvf command (0x%2.2x)\n", c);\r
-                               unsupported = 1;\r
-               }\r
-\r
-               if (do_abort || unsupported || tdo_mismatch)\r
-                       break;\r
-       }\r
-       \r
-       if (tdo_mismatch)\r
-       {\r
-               command_print(cmd_ctx, "TDO mismatch, aborting");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (unsupported)\r
-       {\r
-               command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (do_abort)\r
-       {\r
-               command_print(cmd_ctx, "premature end detected, aborting");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (dr_out_buf)\r
-               free(dr_out_buf);\r
-       \r
-       if (dr_in_buf)\r
-               free(dr_in_buf);\r
-       \r
-       if (dr_in_mask)\r
-               free(dr_in_mask);\r
-\r
-       close(xsvf_fd);\r
-       \r
-       command_print(cmd_ctx, "XSVF file programmed successfully");\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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 "xsvf.h"
+
+#include "jtag.h"
+#include "command.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#define XSTATE_MAX_PATH (12)
+
+int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int xsvf_fd = 0;
+
+u8 *dr_out_buf;        /* from host to device (TDI) */
+u8 *dr_in_buf; /* from device to host (TDO) */
+u8 *dr_in_mask;
+
+int xsdrsize = 0;
+int xruntest = 0;      /* number of TCK cycles / microseconds */
+int xrepeat = 0x20; /* number of XC9500 retries */
+
+int xendir = 0;
+int xenddr = 0;
+
+enum tap_state xsvf_to_tap[] =
+{
+       TAP_TLR, TAP_RTI,
+       TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD,
+       TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI,
+};
+
+int tap_to_xsvf[] =
+{
+       0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf
+};
+
+int xsvf_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,
+               COMMAND_EXEC, "run xsvf <file>");
+
+       return ERROR_OK;
+}
+
+int xsvf_read_buffer(int num_bits, int fd, u8* buf)
+{
+       int num_bytes;
+
+       for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--)
+       {
+               if (read(fd, buf + num_bytes - 1, 1) < 0)
+                       return ERROR_XSVF_EOF;
+       }
+
+       return ERROR_OK;
+}
+
+int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len)
+{
+       char c;
+       unsigned char uc;
+       
+       while ((read(fd, &c, 1) > 0) && (c == 0x12))
+       {
+               if (*path_len > max_path)
+               {
+                       WARNING("XSTATE path longer than max_path");
+                       break;
+               }
+               if (read(fd, &uc, 1) < 0)
+               {
+                       return ERROR_XSVF_EOF;
+               }
+               path[(*path_len)++] = xsvf_to_tap[uc];
+       }
+       
+       lseek(fd, -1, SEEK_CUR);
+       
+       return ERROR_OK;
+}
+
+int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       char c;
+       u8 buf4[4], buf2[2];
+       unsigned char uc, uc2;
+       unsigned int ui;
+       unsigned short us;
+
+       int do_abort = 0;
+       int unsupported = 0;
+       int tdo_mismatch = 0;
+       
+       int runtest_requires_tck = 0;
+       
+       int device = -1;        /* use -1 to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device that should be affected */
+
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>");
+               return ERROR_OK;
+       }
+
+       if (strcmp(args[0], "plain") != 0)
+       {
+               device = strtoul(args[0], NULL, 0);
+       }
+
+       if ((xsvf_fd = open(args[1], O_RDONLY)) < 0)
+       {
+               command_print(cmd_ctx, "file %s not found", args[0]);
+               return ERROR_OK;
+       }
+       
+       if ((argc > 2) && (strcmp(args[2], "virt2") == 0))
+       {
+               runtest_requires_tck = 1;
+       }
+
+       while (read(xsvf_fd, &c, 1) > 0)
+       {
+               switch (c)
+               {
+                       case 0x00:      /* XCOMPLETE */
+                               DEBUG("XCOMPLETE");
+                               if (jtag_execute_queue() != ERROR_OK)
+                               {
+                                       tdo_mismatch = 1;
+                                       break;  
+                               }
+                               break;
+                       case 0x01:      /* XTDOMASK */
+                               DEBUG("XTDOMASK");
+                               if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))
+                                       do_abort = 1;
+                               break;
+                       case 0x02:      /* XSIR */
+                               DEBUG("XSIR");
+                               if (read(xsvf_fd, &c, 1) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       u8 *ir_buf = malloc((c + 7) / 8);
+                                       if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK)
+                                               do_abort = 1;
+                                       else
+                                       {
+                                               scan_field_t field;
+                                               field.device = device;
+                                               field.num_bits = c;
+                                               field.out_value = ir_buf;
+                                               field.out_mask = NULL;
+                                               field.in_value = NULL;
+                                               field.in_check_value = NULL;
+                                               field.in_check_mask = NULL;
+                                               field.in_handler = NULL;
+                                               field.in_handler_priv = NULL;
+                                               if (device == -1)
+                                                       jtag_add_plain_ir_scan(1, &field, TAP_PI);
+                                               else
+                                                       jtag_add_ir_scan(1, &field, TAP_PI);
+                                               if (jtag_execute_queue() != ERROR_OK)
+                                               {
+                                                       tdo_mismatch = 1;
+                                                       free(ir_buf);
+                                                       break;
+                                               }
+                                               if (xruntest)
+                                               {
+                                                       if (runtest_requires_tck)
+                                                               jtag_add_runtest(xruntest, xsvf_to_tap[xendir]);
+                                                       else
+                                                       {
+                                                               jtag_add_statemove(TAP_RTI);
+                                                               jtag_add_sleep(xruntest);
+                                                               jtag_add_statemove(xsvf_to_tap[xendir]);
+                                                       }
+                                               }
+                                               else if (xendir != 0xd) /* Pause-IR */
+                                                       jtag_add_statemove(xsvf_to_tap[xendir]);
+                                       }
+                                       free(ir_buf);
+                               }
+                               break;
+                       case 0x03:      /* XSDR */
+                               DEBUG("XSDR");
+                               if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
+                                       do_abort = 1;
+                               else
+                               {
+                                       scan_field_t field;
+                                       field.device = device;
+                                       field.num_bits = xsdrsize;
+                                       field.out_value = dr_out_buf;
+                                       field.out_mask = NULL;
+                                       field.in_value = NULL;
+                                       jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
+                                       if (device == -1)
+                                               jtag_add_plain_dr_scan(1, &field, TAP_PD);
+                                       else
+                                               jtag_add_dr_scan(1, &field, TAP_PD);
+                                       if (jtag_execute_queue() != ERROR_OK)
+                                       {
+                                               tdo_mismatch = 1;
+                                               break;  
+                                       }
+                                       if (xruntest)
+                                       {
+                                               if (runtest_requires_tck)
+                                                       jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
+                                               else
+                                               {
+                                                       jtag_add_statemove(TAP_RTI);
+                                                       jtag_add_sleep(xruntest);
+                                                       jtag_add_statemove(xsvf_to_tap[xenddr]);
+                                               }
+                                       }
+                                       else if (xendir != 0x6) /* Pause-DR */
+                                               jtag_add_statemove(xsvf_to_tap[xenddr]);
+                               }
+                               break;
+                       case 0x04:      /* XRUNTEST */
+                               DEBUG("XRUNTEST");
+                               if (read(xsvf_fd, buf4, 4) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       xruntest = be_to_h_u32(buf4);
+                               }
+                               break;
+                       case 0x07:      /* XREPEAT */
+                               DEBUG("XREPEAT");
+                               if (read(xsvf_fd, &c, 1) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       xrepeat = c;
+                               }
+                               break;
+                       case 0x08:      /* XSDRSIZE */
+                               DEBUG("XSDRSIZE");
+                               if (read(xsvf_fd, buf4, 4) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       xsdrsize = be_to_h_u32(buf4);
+                                       free(dr_out_buf);
+                                       free(dr_in_buf);
+                                       free(dr_in_mask);
+                                       dr_out_buf = malloc((xsdrsize + 7) / 8);
+                                       dr_in_buf = malloc((xsdrsize + 7) / 8);
+                                       dr_in_mask = malloc((xsdrsize + 7) / 8);
+                               }
+                               break;
+                       case 0x09:      /* XSDRTDO */
+                               DEBUG("XSDRTDO");
+                               if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)
+                                       do_abort = 1;
+                               else
+                               {
+                                       if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)
+                                               do_abort = 1;
+                                       else
+                                       {
+                                               scan_field_t field;
+                                               field.device = device;
+                                               field.num_bits = xsdrsize;
+                                               field.out_value = dr_out_buf;
+                                               field.out_mask = NULL;
+                                               field.in_value = NULL;
+                                               jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
+                                               if (device == -1)
+                                                       jtag_add_plain_dr_scan(1, &field, TAP_PD);
+                                               else
+                                                       jtag_add_dr_scan(1, &field, TAP_PD);
+                                               if (jtag_execute_queue() != ERROR_OK)
+                                               {
+                                                       tdo_mismatch = 1;
+                                                       break;  
+                                               }
+                                               if (xruntest)
+                                               {
+                                                       if (runtest_requires_tck)
+                                                               jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);
+                                                       else
+                                                       {
+                                                               jtag_add_statemove(TAP_RTI);
+                                                               jtag_add_sleep(xruntest);
+                                                               jtag_add_statemove(xsvf_to_tap[xenddr]);
+                                                       }
+                                               }
+                                               else if (xendir != 0x6) /* Pause-DR */
+                                                       jtag_add_statemove(xsvf_to_tap[xenddr]);
+                                       }
+                               }
+                               break;
+                       case 0x0a:      /* XSETDRMASKS */
+                               ERROR("unsupported XSETSDRMASKS\n");
+                               unsupported = 1;
+                               break;
+                       case 0x0b:      /* XSDRINC */
+                               ERROR("unsupported XSDRINC\n");
+                               unsupported = 1;
+                               break;
+                       case 0x0c:      /* XSDRB */
+                               unsupported = 1;
+                               break;
+                       case 0x0d:      /* XSDRC */
+                               unsupported = 1;
+                               break;
+                       case 0x0e:      /* XSDRE */
+                               unsupported = 1;
+                               break;
+                       case 0x0f:      /* XSDRTDOB */
+                               unsupported = 1;
+                               break;
+                       case 0x10:      /* XSDRTDOB */
+                               unsupported = 1;
+                               break;
+                       case 0x11:      /* XSDRTDOB */
+                               unsupported = 1;
+                               break;
+                       case 0x12:      /* XSTATE */
+                               DEBUG("XSTATE");
+                               if (read(xsvf_fd, &uc, 1) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);
+                                       int path_len = 1;
+                                       path[0] = xsvf_to_tap[uc];
+                                       if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)
+                                               do_abort = 1;
+                                       else
+                                       {
+                                               jtag_add_pathmove(path_len, path);
+                                       }
+                                       free(path);
+                               }
+                               break;
+                       case 0x13:      /* XENDIR */
+                               DEBUG("XENDIR");
+                               if (read(xsvf_fd, &c, 1) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       if (c == 0)
+                                               xendir = 1;
+                                       else if (c == 1)
+                                               xendir = 0xd;
+                                       else
+                                       {
+                                               ERROR("unknown XENDIR endstate");
+                                               unsupported = 1;
+                                       }
+                               }
+                               break;
+                       case 0x14:      /* XENDDR */
+                               DEBUG("XENDDR");
+                               if (read(xsvf_fd, &c, 1) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       if (c == 0)
+                                               xenddr = 1;
+                                       else if (c == 1)
+                                               xenddr = 0x6;
+                                       else
+                                       {
+                                               ERROR("unknown XENDDR endstate");
+                                               unsupported = 1;
+                                       }
+                               }
+                               break;
+                       case 0x15:      /* XSIR2 */
+                               DEBUG("XSIR2");
+                               if (read(xsvf_fd, buf2, 2) < 0)
+                                       do_abort = 1;
+                               else
+                               {
+                                       u8 *ir_buf;
+                                       us = be_to_h_u16(buf2);
+                                       ir_buf = malloc((us + 7) / 8);
+                                       if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)
+                                               do_abort = 1;
+                                       else
+                                       {
+                                               scan_field_t field;
+                                               field.device = device;
+                                               field.num_bits = us;
+                                               field.out_value = ir_buf;
+                                               field.out_mask = NULL;
+                                               field.in_value = NULL;
+                                               field.in_check_value = NULL;
+                                               field.in_check_mask = NULL;
+                                               field.in_handler = NULL;
+                                               field.in_handler_priv = NULL;
+                                               if (device == -1)
+                                                       jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);
+                                               else
+                                                       jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);
+                                       }
+                                       free(ir_buf);
+                               }
+                               break;
+                       case 0x16:      /* XCOMMENT */
+                               do
+                               {
+                                       if (read(xsvf_fd, &c, 1) < 0)
+                                       {
+                                               do_abort = 1;
+                                               break;
+                                       }
+                               } while (c != 0);
+                               break;
+                       case 0x17:      /* XWAIT */
+                               DEBUG("XWAIT");
+                               if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))
+                                       do_abort = 1;
+                               else
+                               {
+                                       jtag_add_statemove(xsvf_to_tap[uc]);
+                                       ui = be_to_h_u32(buf4);
+                                       jtag_add_sleep(ui);
+                                       jtag_add_statemove(xsvf_to_tap[uc2]);
+                               }
+                               break;
+                       default:
+                               ERROR("unknown xsvf command (0x%2.2x)\n", c);
+                               unsupported = 1;
+               }
+
+               if (do_abort || unsupported || tdo_mismatch)
+                       break;
+       }
+       
+       if (tdo_mismatch)
+       {
+               command_print(cmd_ctx, "TDO mismatch, aborting");
+               return ERROR_OK;
+       }
+
+       if (unsupported)
+       {
+               command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");
+               return ERROR_OK;
+       }
+
+       if (do_abort)
+       {
+               command_print(cmd_ctx, "premature end detected, aborting");
+               return ERROR_OK;
+       }
+       
+       if (dr_out_buf)
+               free(dr_out_buf);
+       
+       if (dr_in_buf)
+               free(dr_in_buf);
+       
+       if (dr_in_mask)
+               free(dr_in_mask);
+
+       close(xsvf_fd);
+       
+       command_print(cmd_ctx, "XSVF file programmed successfully");
+
+       return ERROR_OK;
+}