diff --git a/src/flash/cfi.c b/src/flash/cfi.c
index 3dc7885c073b69b80355971a8d28525cfc7a0254..fb3d4cc884d032e554804b7544f64d8432a12497 100644
--- a/src/flash/cfi.c
+++ b/src/flash/cfi.c
@@ -50,6 +50,7 @@ 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
 
 flash_driver_t cfi_flash =
 {
@@ -335,6 +336,13 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **
 		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 byte");
+		return ERROR_FLASH_BANK_INVALID;
+	}
+	
 	cfi_info = malloc(sizeof(cfi_flash_bank_t));
 	bank->driver_priv = cfi_info;
 	
diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
index 4b99922cc72d84ed865a236d7378325b96d46596..c0a2fe84b9d95d816e6b7fe3825a477147a4d35c 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -138,6 +138,23 @@ int gdb_get_char(connection_t *connection, int* next_char)
 	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;
+}
+
 int gdb_put_packet(connection_t *connection, char *buffer, int len)
 {
 	int i;
@@ -219,6 +236,8 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
 			if ((retval = gdb_get_char(connection, &character)) != ERROR_OK)
 				return retval;
 
+			DEBUG("character: '%c'", character);
+
 			switch (character)
 			{
 				case '$':
@@ -427,6 +446,9 @@ int gdb_new_connection(connection_t *connection)
 	if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
 		return retval;
 		
+	if (initial_ack != '+')
+		gdb_putback_char(connection, initial_ack);
+		
 	return ERROR_OK;
 }
 
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 2192469c3e0db542c85839919a15986a09cc2ef7..2936967a4cfec897181a67110897df18b3de0751 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -2,7 +2,8 @@ INCLUDES = -I$(top_srcdir)/src/gdb -I$(top_srcdir)/src/helper 	-I$(top_srcdir)/s
 METASOURCES = AUTO
 noinst_LIBRARIES = libtarget.a
 libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
-	arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c
+	arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
+	arm966e.c
 noinst_HEADERS = target.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
 		arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
-		arm_disassembler.h
+		arm_disassembler.h arm966e.h
diff --git a/src/target/arm720t.c b/src/target/arm720t.c
index 31428a2723b68db712c9b2f0e62561f3f8b38e08..677aa4587719ea0759106c6519a807f58fdbaf4e 100644
--- a/src/target/arm720t.c
+++ b/src/target/arm720t.c
@@ -458,7 +458,7 @@ int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **
 	chain_pos = strtoul(args[3], NULL, 0);
 	
 	if (argc >= 5)
-		variant = strdup(args[4]);
+		variant = args[4];
 	
 	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
 	
@@ -475,7 +475,7 @@ int arm720t_register_commands(struct command_context_s *cmd_ctx)
 		
 	retval = arm7tdmi_register_commands(cmd_ctx);
 	
-	arm720t_cmd = register_command(cmd_ctx, NULL, "arm720t", NULL, COMMAND_ANY, NULL);
+	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>");
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index 6bb801254f05ca330f94a9f7e0984cdd1f9da12c..904d0ca0faea7be2d31c0965370d050825cf0dcc 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -1987,7 +1987,7 @@ int arm7_9_register_commands(struct command_context_s *cmd_ctx)
 {
 	command_t *arm7_9_cmd;
 	
-	arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, NULL);
+	arm7_9_cmd = register_command(cmd_ctx, NULL, "arm7_9", NULL, COMMAND_ANY, "arm7/9 specific commands");
 	
 	register_command(cmd_ctx, arm7_9_cmd, "write_xpsr", handle_arm7_9_write_xpsr_command, COMMAND_EXEC, "write program status register <value> <not cpsr|spsr>");
 	register_command(cmd_ctx, arm7_9_cmd, "write_xpsr_im8", handle_arm7_9_write_xpsr_im8_command, COMMAND_EXEC, "write program status register <8bit immediate> <rotate> <not cpsr|spsr>");
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
index f6f0cef71cdb135b32eb71270919f0b3ba5a20f7..5f16f71ffcc0af094502f56130d83832409140aa 100644
--- a/src/target/arm7tdmi.c
+++ b/src/target/arm7tdmi.c
@@ -644,11 +644,11 @@ void arm7tdmi_build_reg_cache(target_t *target)
 	}
 		
 	if (arch_info->has_monitor_mode)
-		(*cache_p)->next->reg_list[0].size = 6;
+		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 6;
 	else
-		(*cache_p)->next->reg_list[0].size = 3;
+		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 3;
 	
-	(*cache_p)->next->reg_list[1].size = 5;
+	(*cache_p)->next->reg_list[EICE_DBG_STAT].size = 5;
 
 }
 
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index ac0b6a6ad268667e8094fa9b39fc20a28f78bee8..d68ca2e441237e368dc84f0d5c11795029887e5e 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -716,7 +716,7 @@ int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **
 	chain_pos = strtoul(args[3], NULL, 0);
 	
 	if (argc >= 5)
-		variant = strdup(args[4]);
+		variant = args[4];
 	
 	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
 	
diff --git a/src/target/arm966e.c b/src/target/arm966e.c
new file mode 100644
index 0000000000000000000000000000000000000000..b7cfea8051be02c810e8f6a12922b6ce09f1dd99
--- /dev/null
+++ b/src/target/arm966e.c
@@ -0,0 +1,461 @@
+/***************************************************************************
+ *   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_deassert_reset(target_t *target);
+int arm966e_assert_reset(target_t *target);
+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,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm966e_assert_reset,
+	.deassert_reset = arm966e_deassert_reset,
+	.soft_reset_halt = arm7_9_soft_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,
+
+	.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_assert_reset(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;
+	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]);
+	
+	if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
+	{
+		/* assert SRST and TRST */
+		/* system would get ouf sync if we didn't reset test-logic, too */
+		if ((retval = jtag_add_reset(1, 1)) != ERROR_OK)
+		{
+			if (retval == ERROR_JTAG_RESET_CANT_SRST)
+			{
+				WARNING("can't assert srst");
+				return retval;
+			}
+			else
+			{
+				ERROR("unknown error");
+				exit(-1);
+			}
+		}
+		jtag_add_sleep(5000);
+		if ((retval = jtag_add_reset(0, 1)) != ERROR_OK)
+		{
+			if (retval == ERROR_JTAG_RESET_WOULD_ASSERT_TRST)
+			{
+				WARNING("srst resets test logic, too");
+				retval = jtag_add_reset(1, 1);
+				trst_asserted_with_srt = 1;
+			}
+		}
+	}
+	else
+	{
+		if ((retval = jtag_add_reset(0, 1)) != ERROR_OK)
+		{
+			if (retval == ERROR_JTAG_RESET_WOULD_ASSERT_TRST)
+			{
+				WARNING("srst resets test logic, too");
+				retval = jtag_add_reset(1, 1);
+				trst_asserted_with_srt = 1;
+			}
+			
+			if (retval == ERROR_JTAG_RESET_CANT_SRST)
+			{
+				WARNING("can't assert srst");
+				return retval;
+			}
+			else if (retval != ERROR_OK)
+			{
+				ERROR("unknown error");
+				exit(-1);
+			}
+		}
+	}
+	
+	target->state = TARGET_RESET;
+	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;
+}
+
+int arm966e_deassert_reset(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;
+	arm966e_common_t *arm966e = arm9tdmi->arch_info;
+	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
+	
+	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;
+}
+
+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;
+	
+	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+	arm9tdmi->arch_info = arm966e;
+	arm966e->common_magic = ARM966E_COMMON_MAGIC;
+	
+	arm9tdmi->has_single_step = 0;
+	arm9tdmi->has_monitor_mode = 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);
+
+	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_value = (u8*)value;
+
+	jtag_add_dr_scan(3, fields, -1);
+
+	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;
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = (u8*)&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 = 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);
+
+	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 = arm7_9_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;
+}
diff --git a/src/target/arm966e.h b/src/target/arm966e.h
new file mode 100644
index 0000000000000000000000000000000000000000..dee06765229d965f2ecda87f20fabe993064f56c
--- /dev/null
+++ b/src/target/arm966e.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ *   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 ARM966E_H
+#define ARM966E_H
+
+#include "target.h"
+#include "register.h"
+#include "embeddedice.h"
+#include "arm_jtag.h"
+#include "arm9tdmi.h"
+
+#define	ARM966E_COMMON_MAGIC 0x20f920f9
+
+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 04ea676ba3ec7f44bb5758428c1b10a70e1624c7..be01dd604a9abca7a15c01f649f75f6972dc4437 100644
--- a/src/target/arm9tdmi.c
+++ b/src/target/arm9tdmi.c
@@ -719,11 +719,11 @@ void arm9tdmi_build_reg_cache(target_t *target)
 	arm7_9->eice_cache = (*cache_p)->next;
 	
 	if (arm9tdmi->has_monitor_mode)
-		(*cache_p)->next->reg_list[0].size = 6;
+		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 6;
 	else
-		(*cache_p)->next->reg_list[0].size = 4;
+		(*cache_p)->next->reg_list[EICE_DBG_CTRL].size = 4;
 	
-	(*cache_p)->next->reg_list[1].size = 5;
+	(*cache_p)->next->reg_list[EICE_DBG_STAT].size = 5;
 
 }
 
@@ -808,7 +808,10 @@ int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int c
 			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);
 	
@@ -831,7 +834,7 @@ int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char *
 	chain_pos = strtoul(args[3], NULL, 0);
 	
 	if (argc >= 5)
-		variant = strdup(args[4]);
+		variant = args[4];
 	
 	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
 	
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index 2ee34e29c4c540b6bdc3465c8bbf4f812140487c..9ee0577d657300024cafa3ed31ff5131b08680d8 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -428,7 +428,7 @@ int armv4_5_register_commands(struct command_context_s *cmd_ctx)
 {
 	command_t *armv4_5_cmd;
 
-	armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, NULL);
+	armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands");
 	
 	register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers");
 	register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state <arm|thumb>");
diff --git a/src/target/embeddedice.h b/src/target/embeddedice.h
index 0062153f15f39d3382356b45ad4015fe442172ef..e038f92d06cd13bd88ce9a7814875b5258f4f29c 100644
--- a/src/target/embeddedice.h
+++ b/src/target/embeddedice.h
@@ -46,6 +46,8 @@ enum
 
 enum
 {
+	EICE_DBG_CONTROL_ICEDIS = 5,
+	EICE_DBG_CONTROL_MONEN = 4,	
 	EICE_DBG_CONTROL_INTDIS = 2,
 	EICE_DBG_CONTROL_DBGRQ = 1,
 	EICE_DBG_CONTROL_DBGACK = 0,
@@ -73,6 +75,12 @@ enum
 	EICE_W_CTRL_nRW = 0x1
 };
 
+enum
+{
+	EICE_COMM_CTRL_WBIT = 1,
+	EICE_COMM_CTRL_RBIT = 0
+};
+
 typedef struct embeddedice_reg_s
 {
 	int addr;
diff --git a/src/target/target.c b/src/target/target.c
index 8b9939af7e30ea22d4b97988f5c1948466034ef7..e88fb196729b2dc7b5cb660af8e6269667c466a4 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -21,6 +21,7 @@
 #include "config.h"
 #endif
 
+#include "replacements.h"
 #include "target.h"
 
 #include "log.h"
@@ -74,6 +75,7 @@ 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;
 
 target_type_t *target_types[] =
 {
@@ -81,6 +83,7 @@ target_type_t *target_types[] =
 	&arm9tdmi_target,
 	&arm920t_target,
 	&arm720t_target,
+	&arm966e_target,
 	NULL,
 };
 
@@ -692,6 +695,7 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
 		if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
 			return retval;
 		
+		buffer += unaligned;
 		address += unaligned;
 		size -= unaligned;
 	}
@@ -704,6 +708,7 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
 		if ((retval = target->type->read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
 			return retval;
 		
+		buffer += aligned;
 		address += aligned;
 		size -= aligned;
 	}