From ef139a3a5e41fbcbabdf4be0ecbbb5591448ad2e Mon Sep 17 00:00:00 2001
From: drath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Fri, 23 Jun 2006 07:54:01 +0000
Subject: [PATCH] - added support for AT91SAM7A3 flash (patch from andre
 renaud, thanks) - fix trunk build for mac os x (patch from Lauri Leukkunen,
 thanks) - added check for host endianness, defines WORDS_BIGENDIAN on a
 big-endian host (e.g. mac os-x) - fixed bug where endianness of memory
 accesses could be swapped on BE hosts - added space for zero termination of
 ftd2xx_layout string (from Magnus Ludin, tahnks)

git-svn-id: svn://svn.berlios.de/openocd/trunk@73 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 configure.in               |  4 +++
 src/flash/at91sam7.c       | 32 ++++++++++++++++++------
 src/helper/types.h         | 51 +++++++++++++++++++++++++++++++++++++-
 src/jtag/ftd2xx.c          |  2 +-
 src/jtag/jtag.h            |  2 +-
 src/server/gdb_server.c    |  5 +++-
 src/target/arm7_9_common.c | 30 ++++++++--------------
 src/target/target.c        | 36 +++++++++++++++++++++++++++
 src/target/target.h        |  5 ++++
 9 files changed, 137 insertions(+), 30 deletions(-)

diff --git a/configure.in b/configure.in
index db378068d..8de2b832a 100644
--- a/configure.in
+++ b/configure.in
@@ -4,6 +4,10 @@ AC_SEARCH_LIBS([ioperm], [ioperm])
 
 AC_CANONICAL_HOST
 
+AC_C_BIGENDIAN
+
+AC_CHECK_FUNCS(strndup)
+
 build_bitbang=no
 is_cygwin=no
 
diff --git a/src/flash/at91sam7.c b/src/flash/at91sam7.c
index 8a602a3f6..348a8652d 100644
--- a/src/flash/at91sam7.c
+++ b/src/flash/at91sam7.c
@@ -244,7 +244,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
 	at91sam7_info->lockbits = status>>16;
 	at91sam7_info->securitybit = (status>>4)&0x01;
 	
-	if (at91sam7_info->cidr_arch == 0x70 ) {
+	if (at91sam7_info->cidr_arch == 0x70 )
+	{
 		at91sam7_info->num_nvmbits = 2;
 		at91sam7_info->nvmbits = (status>>8)&0x03;
 		bank->base = 0x100000;
@@ -281,7 +282,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
 		return ERROR_OK;
 	}
 
-	if (at91sam7_info->cidr_arch == 0x71 ) {
+	if (at91sam7_info->cidr_arch == 0x71 )
+	{
 		at91sam7_info->num_nvmbits = 2;
 		at91sam7_info->nvmbits = (status>>8)&0x03;
 		bank->base = 0x100000;
@@ -304,7 +306,8 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
 		return ERROR_OK;
 	}
 	
-	if (at91sam7_info->cidr_arch == 0x75 ) {
+	if (at91sam7_info->cidr_arch == 0x75 )
+	{
 		at91sam7_info->num_nvmbits = 3;
 		at91sam7_info->nvmbits = (status>>8)&0x07;
 		bank->base = 0x100000;
@@ -327,11 +330,26 @@ int at91sam7_read_part_info(struct flash_bank_s *bank)
 		return ERROR_OK;
 	}
 	
-	if (at91sam7_info->cidr_arch != 0x70 ) 
+	if (at91sam7_info->cidr_arch == 0x60 )
 	{
-		   WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
+		at91sam7_info->num_nvmbits = 3;
+		at91sam7_info->nvmbits = (status>>8)&0x07;
+		bank->base = 0x100000;
+		bank->bus_width = 4;
+		
+		if (bank->size == 0x40000)  /* AT91SAM7A3 */
+		{
+			at91sam7_info->num_lockbits = 16;
+			at91sam7_info->pagesize = 256;
+			at91sam7_info->pages_in_lockregion = 64;
+			at91sam7_info->num_pages = 16*64;
+		}
+		return ERROR_OK;
 	}
-	return ERROR_OK;
+	
+   WARNING("at91sam7 flash only tested for AT91SAM7Sxx series");
+	
+   return ERROR_OK;
 }
 
 int at91sam7_erase_check(struct flash_bank_s *bank)
@@ -377,7 +395,7 @@ int at91sam7_protect_check(struct flash_bank_s *bank)
 
 int at91sam7_register_commands(struct command_context_s *cmd_ctx)
 {
-	command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "cfi", NULL, COMMAND_ANY, NULL);
+	command_t *at91sam7_cmd = register_command(cmd_ctx, NULL, "at91sam7", NULL, COMMAND_ANY, "at91sam7 specific commands");
 
 	return ERROR_OK;
 }
diff --git a/src/helper/types.h b/src/helper/types.h
index 6d49bbb0e..90f493963 100644
--- a/src/helper/types.h
+++ b/src/helper/types.h
@@ -17,10 +17,11 @@
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
-
 #ifndef TYPES_H
 #define TYPES_H
 
+#include "config.h"
+
 #ifndef u8
 typedef unsigned char u8;
 #endif
@@ -33,4 +34,52 @@ typedef unsigned short u16;
 typedef unsigned int u32;
 #endif
 
+#ifdef WORDS_BIGENDIAN /* big endian host */
+
+#define le_to_h_u32(x) (u32)(x[0] | x[1] << 8 | x[2] << 16 | x[3] << 24)
+#define le_to_h_u16(x) (u16)(x[0] | x[1] << 8)
+#define be_to_h_u32(x) (*(u32*)(x))
+#define be_to_h_u16(x) (*(u16*)(x))
+
+#define h_u32_to_le(buf, val) \
+	do { \
+		buf[3] = (val & 0xff000000) >> 24; \
+		buf[2] = (val & 0x00ff0000) >> 16; \
+		buf[1] = (val & 0x0000ff00) >> 8; \
+		buf[0] = (val & 0x000000ff); \
+	} while (0)
+
+#define h_u16_to_le(buf, val)  \
+	do { \
+		buf[0] = (val & 0xff000) >> 8; \
+		buf[1] = (val & 0x00ff); \
+	} while (0)
+
+#define h_u32_to_be(buf, val) do { *(u32*)(buf) = (val); } while (0)
+#define h_u16_to_be(buf, val) do { *(u16*)(buf) = (val); } while (0)
+
+#else /* little endian host */
+#define le_to_h_u32(x) (*(u32*)(x))
+#define le_to_h_u16(x) (*(u16*)(x))
+#define be_to_h_u32(x) (u32)(x[3] | x[2] << 8 | x[1] << 16 | x[0] << 24)
+#define be_to_h_u16(x) (u16)(x[1] | x[0] << 8)
+
+#define h_u32_to_le(buf, val) do { *(u32*)(buf) = (val); } while (0)
+#define h_u16_to_le(buf, val) do { *(u16*)(buf) = (val); } while (0)
+
+#define h_u32_to_be(buf, val) \
+	do { \
+		buf[0] = (val & 0xff000000) >> 24; \
+		buf[1] = (val & 0x00ff0000) >> 16; \
+		buf[2] = (val & 0x0000ff00) >> 8; \
+		buf[3] = (val & 0x000000ff); \
+	} while (0)
+
+#define h_u16_to_be(buf, val) \
+	do { \
+		buf[0] = (val & 0xff000) >> 8; \
+		buf[1] = (val & 0x00ff); \
+	} while (0)
+#endif
+
 #endif /* TYPES_H */
diff --git a/src/jtag/ftd2xx.c b/src/jtag/ftd2xx.c
index c73c8d58e..a14d03913 100644
--- a/src/jtag/ftd2xx.c
+++ b/src/jtag/ftd2xx.c
@@ -982,7 +982,7 @@ int ftd2xx_handle_layout_command(struct command_context_s *cmd_ctx, char *cmd, c
 	if (argc == 0)
 		return ERROR_OK;
 
-	ftd2xx_layout = malloc(strlen(args[0]));
+	ftd2xx_layout = malloc(strlen(args[0]) + 1);
 	strcpy(ftd2xx_layout, args[0]);
 
 	return ERROR_OK;
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index 124150ce7..a2cc01b0f 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/server/gdb_server.c b/src/server/gdb_server.c
index 125206dcb..e8664bb27 100644
--- a/src/server/gdb_server.c
+++ b/src/server/gdb_server.c
@@ -17,6 +17,8 @@
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
+#include "config.h"
+
 #include "gdb_server.h"
 
 #include "server.h"
@@ -31,7 +33,7 @@
 #include <stdlib.h>
 
 // -ino: 060521-1116
-#ifdef __FreeBSD__
+#ifndef HAVE_STRNDUP
 #include <stdio.h>
 char * strndup(char * str, int n) {
   unsigned char * tmp = malloc((size_t)n+1);
@@ -40,6 +42,7 @@ char * strndup(char * str, int n) {
   return tmp;
 }
 #endif
+
 #if 0
 #define _DEBUG_GDB_IO_
 #endif
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index d167041f8..e0ccd7a5e 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -1610,9 +1610,6 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 	u32 *reg_p[16];
 	int num_accesses = 0;
 	int thisrun_accesses;
-	u32 *buf32;
-	u16 *buf16;
-	u8 *buf8;
 	int i;
 	u32 cpsr;
 	int retval;
@@ -1645,7 +1642,6 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 	switch (size)
 	{
 		case 4:
-			buf32 = (u32*)buffer;
 			while (num_accesses < count)
 			{
 				u32 reg_list;
@@ -1662,13 +1658,13 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 				{
 					if (i > last_reg)
 						last_reg = i;
-					*(buf32++) = reg[i];
+					target_buffer_set_u32(target, buffer, reg[i]);
+					buffer += 4;
 				}
 				num_accesses += thisrun_accesses;
 			}	
 			break;
 		case 2:
-			buf16 = (u16*)buffer;
 			while (num_accesses < count)
 			{
 				u32 reg_list;
@@ -1688,13 +1684,13 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 				
 				for (i = 1; i <= thisrun_accesses; i++)
 				{
-					*(buf16++) = reg[i] & 0xffff;
+					target_buffer_set_u16(target, buffer, reg[i]);
+					buffer += 2;
 				}
 				num_accesses += thisrun_accesses;
 			}	
 			break;
 		case 1:
-			buf8 = buffer;
 			while (num_accesses < count)
 			{
 				u32 reg_list;
@@ -1714,7 +1710,7 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count
 				
 				for (i = 1; i <= thisrun_accesses; i++)
 				{
-					*(buf8++) = reg[i] & 0xff;
+					*(buffer++) = reg[i] & 0xff;
 				}
 				num_accesses += thisrun_accesses;
 			}	
@@ -1755,9 +1751,6 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 	u32 reg[16];
 	int num_accesses = 0;
 	int thisrun_accesses;
-	u32 *buf32;
-	u16 *buf16;
-	u8 *buf8;
 	int i;
 	u32 cpsr;
 	int retval;
@@ -1785,7 +1778,6 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 	switch (size)
 	{
 		case 4:
-			buf32 = (u32*)buffer;
 			while (num_accesses < count)
 			{
 				u32 reg_list;
@@ -1796,7 +1788,8 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 				{
 					if (i > last_reg)
 						last_reg = i;
-					reg[i] = *buf32++;
+					reg[i] = target_buffer_get_u32(target, buffer);
+					buffer += 4;
 				}
 				
 				arm7_9->write_core_regs(target, reg_list, reg);
@@ -1815,7 +1808,6 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 			}	
 			break;
 		case 2:
-			buf16 = (u16*)buffer;
 			while (num_accesses < count)
 			{
 				u32 reg_list;
@@ -1826,7 +1818,8 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 				{
 					if (i > last_reg)
 						last_reg = i;
-					reg[i] = *buf16++ & 0xffff;
+					reg[i] = target_buffer_get_u16(target, buffer) & 0xffff;
+					buffer += 2;
 				}
 				
 				arm7_9->write_core_regs(target, reg_list, reg);
@@ -1848,7 +1841,6 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 			}	
 			break;
 		case 1:
-			buf8 = buffer;
 			while (num_accesses < count)
 			{
 				u32 reg_list;
@@ -1859,7 +1851,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
 				{
 					if (i > last_reg)
 						last_reg = i;
-					reg[i] = *buf8++ & 0xff;
+					reg[i] = *buffer++ & 0xff;
 				}
 				
 				arm7_9->write_core_regs(target, reg_list, reg);
@@ -1955,7 +1947,7 @@ int arm7_9_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffe
 	
 	for (i = 0; i < count; i++)
 	{
-		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], buf_get_u32(buffer, 0, 32));
+		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], target_buffer_get_u32(target, buffer));
 		buffer += 4;
 	}
 	
diff --git a/src/target/target.c b/src/target/target.c
index 98407afb7..34dc60a70 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -111,6 +111,42 @@ 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)
 {
diff --git a/src/target/target.h b/src/target/target.h
index 6d3b6d172..dc6d8ce14 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -217,6 +217,11 @@ extern target_t *targets;
 extern target_event_callback_t *target_event_callbacks;
 extern target_timer_callback_t *target_timer_callbacks;
 
+extern u32 target_buffer_get_u32(target_t *target, u8 *buffer);
+extern u16 target_buffer_get_u16(target_t *target, u8 *buffer);
+extern void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value);
+extern void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value);
+
 #define ERROR_TARGET_INVALID	(-300)
 #define ERROR_TARGET_INIT_FAILED (-301)
 #define ERROR_TARGET_TIMEOUT	(-302)
-- 
GitLab