From 4fc97d3f2726efa147cfdb0c456eace51550e1e3 Mon Sep 17 00:00:00 2001
From: drath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Mon, 22 Jan 2007 14:47:00 +0000
Subject: [PATCH] - fix incorrect parsing of whitespace in command.c (thanks to
 Magnus Lundin) - fix infinite recursion in target_init_handler (thanks to jw
 and Magnus Lundin) - fix CFI flash handlign with buswidth < 32bit (thanks to
 Daniele Orio for reporting this) - add support for reading JTAG device id
 (currently only as debug output on startup) - cleaned up handling of
 EmbeddedICE registers. Supported functionality and register size now
 determined by EmbeddedICE version number. - small cleanups/fixes

git-svn-id: svn://svn.berlios.de/openocd/trunk@124 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 src/flash/cfi.c            | 57 ++++++++++++++++++----
 src/flash/flash.c          |  4 ++
 src/helper/command.c       | 25 +++++++---
 src/jtag/jtag.c            | 96 +++++++++++++++++++++++++++++++++++++-
 src/jtag/jtag.h            |  2 +-
 src/target/arm7_9_common.c |  4 ++
 src/target/arm7_9_common.h |  4 ++
 src/target/arm7tdmi.c      | 26 ++---------
 src/target/arm7tdmi.h      |  1 -
 src/target/arm920t.c       |  2 +-
 src/target/arm966e.c       | 42 -----------------
 src/target/arm966e.h       |  1 -
 src/target/arm9tdmi.c      | 29 ++++--------
 src/target/arm9tdmi.h      |  2 -
 src/target/embeddedice.c   | 67 ++++++++++++++++++++++----
 src/target/embeddedice.h   |  5 +-
 src/target/target.c        |  4 +-
 17 files changed, 252 insertions(+), 119 deletions(-)

diff --git a/src/flash/cfi.c b/src/flash/cfi.c
index e91fcc7ed..7f2313d82 100644
--- a/src/flash/cfi.c
+++ b/src/flash/cfi.c
@@ -88,6 +88,12 @@ void cfi_command(flash_bank_t *bank, u8 cmd, u8 *cmd_buf)
 	cfi_flash_bank_t *cfi_info = bank->driver_priv;
 	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 (cfi_info->target->endianness == TARGET_LITTLE_ENDIAN)
 	{
 		for (i = bank->bus_width; i > 0; i--)
@@ -206,7 +212,10 @@ u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)
 		DEBUG("status: 0x%x", status);
 		usleep(1000);
 	}
-	
+
+	/* mask out bit 0 (reserved) */
+	status = status & 0xfe;
+
 	DEBUG("status: 0x%x", status);
 	
 	if ((status & 0x80) != 0x80)
@@ -438,6 +447,7 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
 	cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
 	target_t *target = cfi_info->target;
 	u8 command[8];
+	int retry = 0;
 	int i;
 	
 	/* if the device supports neither legacy lock/unlock (bit 3) nor
@@ -451,22 +461,53 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
 	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;
 		}
-		
-		/* Clear lock bits operation may take up to 1.4s */
-		cfi_intel_wait_status_busy(bank, 1400);
+
+		/* 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,
@@ -683,7 +724,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
 
 	cfi_command(bank, 0x40, write_command);
 	cfi_command(bank, 0x80, busy_pattern);
-	cfi_command(bank, 0x7f, error_pattern);
+	cfi_command(bank, 0x7e, error_pattern);
 
 	while (count > 0)
 	{
@@ -694,9 +735,9 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
 		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, buf_get_u32(write_command, 0, 32));
-		buf_set_u32(reg_params[5].value, 0, 32, buf_get_u32(busy_pattern, 0, 32));
-		buf_set_u32(reg_params[6].value, 0, 32, buf_get_u32(error_pattern, 0, 32));
+		buf_set_u32(reg_params[3].value, 0, 32, target_buffer_get_u32(target, write_command));
+		buf_set_u32(reg_params[5].value, 0, 32, target_buffer_get_u32(target, busy_pattern));
+		buf_set_u32(reg_params[6].value, 0, 32, target_buffer_get_u32(target, error_pattern));
 	
 		if ((retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + (13 * 4), 10000, &armv4_5_info)) != ERROR_OK)
 		{
diff --git a/src/flash/flash.c b/src/flash/flash.c
index 736d3fca1..0a6796468 100644
--- a/src/flash/flash.c
+++ b/src/flash/flash.c
@@ -471,6 +471,10 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c
 					command_print(cmd_ctx, "unknown error");
 			}
 		}
+		else
+		{
+			command_print(cmd_ctx, "%s protection for sectors %i through %i on flash bank %i", (set) ? "set" : "cleared", first, last, strtoul(args[0], 0, 0));
+		}
 	}
 	else
 	{
diff --git a/src/helper/command.c b/src/helper/command.c
index ca08535a4..dbf3f2aa1 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -200,12 +200,23 @@ int parse_line(char *line, char *words[], int max_words)
 			/* we're inside a word or quote, and reached its end*/
 			if (word_start)
 			{
-				int len = p - word_start;
-
-				/* copy the word */
-				memcpy(words[nwords] = malloc(len + 1), word_start, len);
-				/* add terminating NUL */
-				words[nwords++][len] = 0;
+                         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 */
@@ -215,6 +226,8 @@ int parse_line(char *line, char *words[], int max_words)
 			/* skip over trailing quote or whitespace*/
 			if (inquote || isspace(*p))
 				p++;
+                     while (isspace(*p))
+                            p++;
 
 			inquote = 0;
 			word_start = 0;
diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c
index 263eed1a9..cc9f8dc45 100644
--- a/src/jtag/jtag.c
+++ b/src/jtag/jtag.c
@@ -115,6 +115,10 @@ int jtag_verify_capture_ir = 1;
 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;
 
@@ -597,8 +601,7 @@ int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
 			/* if a device is listed, the BYPASS register must not be selected */
 			if (jtag_get_device(i)->bypass)
 			{
-				ERROR("BUG: scan data for a device in BYPASS");
-				exit(-1);
+				WARNING("scan data for a device in BYPASS");
 			}
 		}
 	}
@@ -1116,6 +1119,93 @@ void jtag_sleep(u32 us)
 	usleep(us);
 }
 
+/* Try to examine chain layout according to IEEE 1149.1 ยง12
+ */
+int jtag_examine_chain()
+{
+	scan_field_t field;
+	u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+	int i;
+	int bit_count;
+	int device_count = 0;
+	u8 valid = 0x0;
+	
+	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, 0, 32, 0x000000FF);
+	}
+	
+	jtag_add_plain_dr_scan(1, &field, TAP_TLR);
+	jtag_execute_queue();
+	
+	for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
+	{
+		valid |= idcode_buffer[i];
+	}
+	
+	/* if there wasn't a single non-zero bit, the scan isn't valid */
+	if (!valid)
+	{
+		ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
+		exit(-1);
+	}
+	
+	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;
+			}
+			
+			device_count++;
+			
+			manufacturer = (idcode & 0xffe) >> 1;
+			part = (idcode & 0xffff000) >> 12;
+			version = (idcode & 0xf0000000) >> 28;
+
+			DEBUG("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);
+		exit(-1);
+	}
+	
+	return ERROR_OK;
+}
+
 int jtag_validate_chain()
 {
 	jtag_device_t *device = jtag_devices;
@@ -1244,6 +1334,8 @@ int jtag_init(struct command_context_s *cmd_ctx)
 				jtag_add_statemove(TAP_TLR);
 				jtag_execute_queue();
 				
+				jtag_examine_chain();
+				
 				jtag_validate_chain();
 				
 				return ERROR_OK;
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index 7ad382780..19f81ce63 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -25,7 +25,7 @@
 
 #include "command.h"
 
-#if 0
+#if 1
 #define _DEBUG_JTAG_IO_
 #endif
 
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index cd7e7fe18..8e74dedab 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -2388,7 +2388,11 @@ int arm7_9_init_arch_info(target_t *target, arm7_9_common_t *arm7_9)
 	arm7_9->wp1_used = 0;
 	arm7_9->force_hw_bkpts = 0;
 	arm7_9->use_dbgrq = 0;
+	
 	arm7_9->has_etm = 0;
+	arm7_9->has_single_step = 0;
+	arm7_9->has_monitor_mode = 0;
+	arm7_9->has_vector_catch = 0;
 	
 	arm7_9->reinit_embeddedice = 0;
 	
diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h
index fc90c0591..25141a14c 100644
--- a/src/target/arm7_9_common.h
+++ b/src/target/arm7_9_common.h
@@ -45,7 +45,11 @@ typedef struct arm7_9_common_s
 	int force_hw_bkpts;
 	int dbgreq_adjust_pc;
 	int use_dbgrq;
+	
 	int has_etm;
+	int has_single_step;
+	int has_monitor_mode;
+	int has_vector_catch;
 	
 	int reinit_embeddedice;
 	
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
index a1fde037e..5d925e219 100644
--- a/src/target/arm7tdmi.c
+++ b/src/target/arm7tdmi.c
@@ -742,7 +742,7 @@ void arm7tdmi_build_reg_cache(target_t *target)
 	(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
 	armv4_5->core_cache = (*cache_p);
 	
-	(*cache_p)->next = embeddedice_build_reg_cache(target, jtag_info, 0);
+	(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
 	arm7_9->eice_cache = (*cache_p)->next;
 	
 	if (arm7_9->has_etm)
@@ -750,14 +750,6 @@ void arm7tdmi_build_reg_cache(target_t *target)
 		(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, 0);
 		arm7_9->etm_cache = (*cache_p)->next->next;
 	}
-		
-	if (arch_info->has_monitor_mode)
-		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 6;
-	else
-		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 3;
-	
-	(*cache_p)->next->reg_list[EICE_DBG_STAT].size = 5;
-
 }
 
 int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
@@ -828,30 +820,20 @@ int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int c
 	arm7_9->sw_bkpts_enabled = 0;
 	arm7_9->dbgreq_adjust_pc = 2;
 	arm7_9->arch_info = arm7tdmi;
-	
-	arm7tdmi->has_monitor_mode = 0;
+
 	arm7tdmi->arch_info = NULL;
 	arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;
 	
 	if (variant)
 	{
-		if (strcmp(variant, "arm7tdmi-s_r4") == 0)
-			arm7tdmi->has_monitor_mode = 1;
-		else if (strcmp(variant, "arm7tdmi_r4") == 0)
-			arm7tdmi->has_monitor_mode = 1;
-		else if (strcmp(variant, "lpc2000") == 0)
-		{
-			arm7tdmi->has_monitor_mode = 1;
-			has_etm = 1;
-		}
 		arm7tdmi->variant = strdup(variant);
 	}
 	else
+	{
 		arm7tdmi->variant = strdup("");
+	}
 	
 	arm7_9_init_arch_info(target, arm7_9);
-	
-	arm7_9->has_etm = has_etm;
 
 	return ERROR_OK;
 }
diff --git a/src/target/arm7tdmi.h b/src/target/arm7tdmi.h
index ca2df8b69..104d1e032 100644
--- a/src/target/arm7tdmi.h
+++ b/src/target/arm7tdmi.h
@@ -33,7 +33,6 @@ typedef struct arm7tdmi_common_s
 {
 	int common_magic;
 	char *variant;
-	int has_monitor_mode;
 	void *arch_info;
 	arm7_9_common_t arm7_9_common;
 } arm7tdmi_common_t;
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index 97a08811e..1dae23192 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -701,7 +701,7 @@ int arm920t_init_arch_info(target_t *target, arm920t_common_t *arm920t, int chai
 	arm920t->preserve_cache = 0;
 	
 	/* override hw single-step capability from ARM9TDMI */
-	arm9tdmi->has_single_step = 1;
+	arm7_9->has_single_step = 1;
 	
 	return ERROR_OK;
 }
diff --git a/src/target/arm966e.c b/src/target/arm966e.c
index f5f4a209f..4573844a7 100644
--- a/src/target/arm966e.c
+++ b/src/target/arm966e.c
@@ -91,9 +91,6 @@ int arm966e_assert_reset(target_t *target)
 	arm966e_common_t *arm966e = arm9tdmi->arch_info;
 	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
 	int retval;
-	int trst_asserted_with_srt = 0;
-	
-	arm966e->monitor_mode_set = 1;
 	
 	DEBUG("target->state: %s", target_state_strings[target->state]);
 	
@@ -121,7 +118,6 @@ int arm966e_assert_reset(target_t *target)
 			{
 				WARNING("srst resets test logic, too");
 				retval = jtag_add_reset(1, 1);
-				trst_asserted_with_srt = 1;
 			}
 		}
 	}
@@ -133,7 +129,6 @@ int arm966e_assert_reset(target_t *target)
 			{
 				WARNING("srst resets test logic, too");
 				retval = jtag_add_reset(1, 1);
-				trst_asserted_with_srt = 1;
 			}
 			
 			if (retval == ERROR_JTAG_RESET_CANT_SRST)
@@ -153,23 +148,6 @@ int arm966e_assert_reset(target_t *target)
 	jtag_add_sleep(50000);
 	
 	armv4_5_invalidate_core_regs(target);
-
-	if( trst_asserted_with_srt == 0 )
-	{
-		DEBUG("monitor mode needs clearing");
-		
-		/* arm9e monitor mode enabled at reset */
-		embeddedice_read_reg(dbg_ctrl);
-		jtag_execute_queue();
-		
-		if(buf_get_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1))
-		{
-			buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1, 0);
-			embeddedice_store_reg(dbg_ctrl);
-			DEBUG("monitor mode disabled");
-		}
-		arm966e->monitor_mode_set = 0;
-	}
 	
 	return ERROR_OK;
 }
@@ -184,23 +162,6 @@ int arm966e_deassert_reset(target_t *target)
 	
 	arm7_9_deassert_reset( target );
 	
-	if( arm966e->monitor_mode_set == 1 )
-	{
-		DEBUG("monitor mode needs clearing");
-		
-		/* arm9e monitor mode enabled at reset */
-		embeddedice_read_reg(dbg_ctrl);
-		jtag_execute_queue();
-				
-		if(buf_get_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1))
-		{
-			buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_MONEN, 1, 0);
-			embeddedice_store_reg(dbg_ctrl);
-			arm966e->monitor_mode_set = 0;
-			DEBUG("monitor mode disabled");
-		}
-	}
-	
 	return ERROR_OK;
 }
 
@@ -226,9 +187,6 @@ int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chai
 	arm9tdmi->arch_info = arm966e;
 	arm966e->common_magic = ARM966E_COMMON_MAGIC;
 	
-	arm9tdmi->has_single_step = 0;
-	arm9tdmi->has_monitor_mode = 1;
-	
 	return ERROR_OK;
 }
 
diff --git a/src/target/arm966e.h b/src/target/arm966e.h
index dee067652..d4624f6c6 100644
--- a/src/target/arm966e.h
+++ b/src/target/arm966e.h
@@ -33,7 +33,6 @@ typedef struct arm966e_common_s
 	int common_magic;
 	arm9tdmi_common_t arm9tdmi_common;
 	u32 cp15_control_reg;
-	int monitor_mode_set;
 } arm966e_common_t;
 
 #endif /* ARM966E_H */
diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c
index ccd30312d..ef978956d 100644
--- a/src/target/arm9tdmi.c
+++ b/src/target/arm9tdmi.c
@@ -788,7 +788,7 @@ void arm9tdmi_enable_single_step(target_t *target)
 	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
 	arm9tdmi_common_t *arm9 = arm7_9->arch_info;
 	
-	if (arm9->has_single_step)
+	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]);
@@ -806,7 +806,7 @@ void arm9tdmi_disable_single_step(target_t *target)
 	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
 	arm9tdmi_common_t *arm9 = arm7_9->arch_info;
 	
-	if (arm9->has_single_step)
+	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]);
@@ -832,16 +832,10 @@ void arm9tdmi_build_reg_cache(target_t *target)
 	armv4_5->core_cache = (*cache_p);
 	
 	/* one extra register (vector catch) */
-	(*cache_p)->next = embeddedice_build_reg_cache(target, jtag_info, 1);
+	(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
 	arm7_9->eice_cache = (*cache_p)->next;
-	
-	if (arm9tdmi->has_monitor_mode)
-		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 6;
-	else
-		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 4;
-	
-	(*cache_p)->next->reg_list[EICE_DBG_STAT].size = 5;
 
+#if 0	
 	(*cache_p)->next->reg_list[EICE_VEC_CATCH].name = "vector catch";
 	(*cache_p)->next->reg_list[EICE_VEC_CATCH].dirty = 0;
 	(*cache_p)->next->reg_list[EICE_VEC_CATCH].valid = 0;
@@ -851,7 +845,7 @@ void arm9tdmi_build_reg_cache(target_t *target)
 	(*cache_p)->next->reg_list[EICE_VEC_CATCH].value = calloc(1, 4);
 	vec_catch_arch_info = (*cache_p)->next->reg_list[EICE_VEC_CATCH].arch_info;
 	vec_catch_arch_info->addr = 0x2;
-	
+#endif
 }
 
 int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
@@ -923,27 +917,24 @@ int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int c
 	arm7_9->arch_info = arm9tdmi;
 	
 	arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC;
-	arm9tdmi->has_monitor_mode = 0;
-	arm9tdmi->has_single_step = 0;
 	arm9tdmi->arch_info = NULL;
 
 	if (variant)
 	{
-		if (strcmp(variant, "arm920t") == 0)
-			arm9tdmi->has_single_step = 1;
-		else if (strcmp(variant, "arm922t") == 0)
-			arm9tdmi->has_single_step = 1;
-		else if (strcmp(variant, "arm940t") == 0)
-			arm9tdmi->has_single_step = 1;
 		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;
 }
diff --git a/src/target/arm9tdmi.h b/src/target/arm9tdmi.h
index 7bbaac7c9..f888c3559 100644
--- a/src/target/arm9tdmi.h
+++ b/src/target/arm9tdmi.h
@@ -33,8 +33,6 @@ typedef struct arm9tdmi_common_s
 {
 	int common_magic;
 	char *variant;
-	int has_monitor_mode;
-	int has_single_step;
 	void *arch_info;
 	arm7_9_common_t arm7_9_common;
 } arm9tdmi_common_t;
diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c
index b063bd2c3..6cf698161 100644
--- a/src/target/embeddedice.c
+++ b/src/target/embeddedice.c
@@ -48,7 +48,8 @@ int embeddedice_reg_arch_info[] =
 {
 	0x0, 0x1, 0x4, 0x5,
 	0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+	0x2
 };
 
 char* embeddedice_reg_list[] =
@@ -71,7 +72,9 @@ char* embeddedice_reg_list[] =
 	"watch 1 data value",
 	"watch 1 data mask",
 	"watch 1 control value",
-	"watch 1 control mask"
+	"watch 1 control mask",
+	
+	"vector catch"
 };
 
 int embeddedice_reg_arch_type = -1;
@@ -83,18 +86,25 @@ 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, arm_jtag_t *jtag_info, int extra_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;
-	int num_regs = 16 + extra_reg;
+	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));
@@ -106,7 +116,7 @@ reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info
 	reg_cache->num_regs = num_regs;
 	
 	/* set up registers */
-	for (i = 0; i < num_regs - extra_reg; i++)
+	for (i = 0; i < num_regs; i++)
 	{
 		reg_list[i].name = embeddedice_reg_list[i];
 		reg_list[i].size = 32;
@@ -121,12 +131,49 @@ reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info
 		arch_info[i].jtag_info = jtag_info;
 	}
 	
-	/* there may be one extra reg (Abort status (ARM7 rev4) or Vector catch (ARM9)) */
-	if (extra_reg)
+	/* 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)
 	{
-		reg_list[num_regs - 1].arch_info = &arch_info[num_regs - 1];
-		reg_list[num_regs - 1].arch_type = embeddedice_reg_arch_type;
-		arch_info[num_regs - 1].jtag_info = jtag_info;
+		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_single_step = 1;
+			arm7_9->has_monitor_mode = 1;
+			break;
+		default:
+			ERROR("unknown EmbeddedICE version (comms ctrl: 0x%4.4x)", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
 	}
 	
 	return reg_cache;
diff --git a/src/target/embeddedice.h b/src/target/embeddedice.h
index eedc21912..a50ea221f 100644
--- a/src/target/embeddedice.h
+++ b/src/target/embeddedice.h
@@ -23,6 +23,7 @@
 #include "target.h"
 #include "register.h"
 #include "arm_jtag.h"
+#include "arm7_9_common.h"
 
 enum
 {
@@ -42,7 +43,6 @@ enum
 	EICE_W1_DATA_MASK = 13,
 	EICE_W1_CONTROL_VALUE = 14,
 	EICE_W1_CONTROL_MASK = 15,
-	EICE_ABT_STATUS = 16,
 	EICE_VEC_CATCH = 16
 };
 
@@ -57,6 +57,7 @@ enum
 
 enum
 {
+	EICE_DBG_STATUS_IJBIT = 5,
 	EICE_DBG_STATUS_ITBIT = 4,
 	EICE_DBG_STATUS_SYSCOMP = 3,
 	EICE_DBG_STATUS_IFEN = 2,
@@ -89,7 +90,7 @@ typedef struct embeddedice_reg_s
 	arm_jtag_t *jtag_info;
 } embeddedice_reg_t;
 
-extern reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, int extra_reg);
+extern reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9);
 extern int embeddedice_read_reg(reg_t *reg);
 extern int embeddedice_write_reg(reg_t *reg, u32 value);
 extern int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask);
diff --git a/src/target/target.c b/src/target/target.c
index 732288880..8c6d97dfc 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -209,6 +209,8 @@ int target_init_handler(struct target_s *target, enum target_event event, void *
 	
 	if ((event == TARGET_EVENT_HALTED) && (target->reset_script))
 	{
+		target_unregister_event_callback(target_init_handler, priv);
+
 		script = fopen(target->reset_script, "r");
 		if (!script)
 		{
@@ -221,8 +223,6 @@ int target_init_handler(struct target_s *target, enum target_event event, void *
 		fclose(script);
 
 		jtag_execute_queue();
-
-		target_unregister_event_callback(target_init_handler, priv);
 	}
 	
 	return ERROR_OK;
-- 
GitLab