- 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;
+}

Linking to existing account procedure

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

SSH host keys fingerprints

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