From fc92d9810d9d6a3c1fa2aab20c9adb8998a15834 Mon Sep 17 00:00:00 2001
From: rliebscher <rliebscher@81a1dc3b-b13d-400b-aceb-764788c761c2>
Date: Tue, 10 Jan 2012 18:19:40 +0000
Subject: [PATCH] bug #35261 avrftdi uses wrong interface in
 avrftdi_paged_(write|load) * avrftdi.c: Fixed interface and implementation of
 avrftdi_paged_(write|load) patch #7672 adding support for O-Link (FTDI based
 JTAG) as programmer * avrdude.conf.in: added o-link entry

git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1039 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ChangeLog       |  7 +++++
 avrdude.conf.in | 57 ++++++++++++++++++++++++++++---------
 avrftdi.c       | 74 +++++++++++++++++++++++--------------------------
 3 files changed, 85 insertions(+), 53 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 85ca76a1..71156513 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2012-01-10  Rene Liebscher <R.Liebscher@gmx.de>
+
+	bug #35261 avrftdi uses wrong interface in avrftdi_paged_(write|load)
+	* avrftdi.c: Fixed interface and implementation of avrftdi_paged_(write|load)
+	patch #7672 adding support for O-Link (FTDI based JTAG) as programmer
+	* avrdude.conf.in: added o-link entry
+
 2012-01-10  Rene Liebscher <R.Liebscher@gmx.de>
 
 	patch #7699 Read additional config files
diff --git a/avrdude.conf.in b/avrdude.conf.in
index 7d61700e..8fde144f 100644
--- a/avrdude.conf.in
+++ b/avrdude.conf.in
@@ -366,9 +366,9 @@ programmer
 # And fill that in here.
 
 programmer
-  id	= "avrftdi";
-  desc	= "FT2232D based generic programmer";
-  type	= avrftdi;
+  id         = "avrftdi";
+  desc       = "FT2232D based generic programmer";
+  type       = avrftdi;
   usbvid     = 0x0403;
   usbpid     = 0x6010;
   usbvendor  = "";
@@ -393,15 +393,15 @@ programmer
 # understood (by avrdude) to be active low, so there's no
 # need to invert the bits.
 programmer
-  id	= "2232HIO";
-  desc	= "FT2232H based generic programmer";
-  type	= avrftdi;
+  id         = "2232HIO";
+  desc       = "FT2232H based generic programmer";
+  type       = avrftdi;
   usbvid     = 0x0403;
 # Note: This PID is reserved for generic H devices and 
 # should be programmed into the EEPROM
 #  usbpid     = 0x8A48;
-   usbpid    = 0x6010;
-  usbdev = "A";
+  usbpid     = 0x6010;
+  usbdev     = "A";
   usbvendor  = "";
   usbproduct = "";
   usbsn      = "";
@@ -419,13 +419,13 @@ programmer
 ;
 
 programmer
-  id    = "jtagkey";
-  desc  = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2";
-  type  = avrftdi;
+  id         = "jtagkey";
+  desc       = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2";
+  type       = avrftdi;
   usbvid     = 0x0403;
 # Note: This PID is used in all JTAGKey variants
-  usbpid    = 0xCFF8;
-  usbdev = "A";
+  usbpid     = 0xCFF8;
+  usbdev     = "A";
   usbvendor  = "";
   usbproduct = "";
   usbsn      = "";
@@ -441,6 +441,37 @@ programmer
 # from Amontec
 ;
 
+# On the adapter you can read "O-Link". On the PCB is printed "OpenJTAG v3.1"
+# You can find it as "OpenJTAG ARM JTAG USB" in the internet. 
+# (But there are also several projects called Open JTAG, eg. 
+# http://www.openjtag.org, which are completely different.)
+#   http://www.100ask.net/shop/english.html (website seems to be outdated)
+#   http://item.taobao.com/item.htm?id=1559277013
+#   http://www.micro4you.com/store/openjtag-arm-jtag-usb.html (schematics!)
+# some other sources which call it O-Link
+#   http://www.andahammer.com/olink/
+#   http://www.developmentboard.net/31-o-link-debugger.html
+#   http://armwerks.com/catalog/o-link-debugger-copy/
+# or just have a look at ebay ...
+# It is basically the same entry as jtagkey with different usb ids.
+programmer
+  id         = "o-link";
+  desc       = "O-Link, OpenJTAG from www.100ask.net";
+  type       = avrftdi;
+  usbvid     = 0x1457;
+  usbpid     = 0x5118;
+  usbdev     = "A";
+  usbvendor  = "www.100ask.net";
+  usbproduct = "USB<=>JTAG&RS232";
+  usbsn      = "";
+# for pin connections see jtagkey
+  reset  = 4;
+  sck    = 1;
+  mosi   = 2;
+  miso   = 3;
+  buff   = 5;
+;
+
 programmer
   id    = "avrisp";
   desc  = "Atmel AVR ISP";
diff --git a/avrftdi.c b/avrftdi.c
index 982298c4..b968e93f 100644
--- a/avrftdi.c
+++ b/avrftdi.c
@@ -468,6 +468,7 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
 			memset(serial, 0, 255);
 			devlist_ptr = devlist_ptr->next;
 		} while (devlist_ptr);
+		ftdi_list_free(&devlist);
 	} else {
 		fprintf(stderr,
 			"%s: No devices with Vendor-ID:Product-ID %04x:%04x found.\n",
@@ -479,7 +480,6 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
 		fprintf(stderr,
 			"%s: No devices with VID:PID %04x:%04x and SN '%s' found.\n",
 			progname, vid, pid, pgm->usbsn);
-		ftdi_list_free(&devlist);
 		return -1;
 	}
 	if (verbose) {
@@ -709,7 +709,7 @@ static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
 
 
 /* Load extended address byte command */
-static int avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, int address)
+static int avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address)
 {
 	unsigned char buf[] = {0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
 
@@ -727,15 +727,15 @@ static int avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, int address)
 }
 
 static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
-				int page_size, int len)
+		unsigned int page_size, unsigned int addr, unsigned int len)
 {
 	unsigned char cmd[4];
 	unsigned char *data = m->buf;
-	int add;
+	unsigned int add;
 
 	avr_set_bits(m->op[AVR_OP_WRITE], cmd);
 
-	for (add = 0; add < len; add++)
+	for (add = addr; add < addr + len; add++)
 	{
 		avr_set_addr(m->op[AVR_OP_WRITE], cmd, add);
 		avr_set_input(m->op[AVR_OP_WRITE], cmd, *data++);
@@ -748,16 +748,15 @@ static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
 }
 
 static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
-			       int page_size, int len)
+		unsigned int page_size, unsigned int addr, unsigned int len)
 {
 	unsigned char cmd[4];
 	unsigned char buffer[len], *bufptr = buffer;
-
-	int add;
+	unsigned int add;
 
 	memset(buffer, 0, sizeof(buffer));
 
-	for (add = 0; add < len; add++)
+	for (add = addr; add < addr + len; add++)
 	{
 		avr_set_bits(m->op[AVR_OP_READ], cmd);
 		avr_set_addr(m->op[AVR_OP_READ], cmd, add);
@@ -767,33 +766,24 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
 		avr_get_output(m->op[AVR_OP_READ], cmd, bufptr++);
 	}
 
-	memcpy(m->buf, buffer, len);
+	memcpy(m->buf + addr, buffer, len);
 	return len;
 }
 
 static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
-			       int page_size, int len)
+		unsigned int page_size, unsigned int addr, unsigned int len)
 {
 	int i;
-	int address = 0, buf_size;
-	int bytes = len;
-	int blocksize;
+	unsigned int address = addr/2, buf_size;
+	unsigned int address_prev_block = ~address; /* start address of previous block,
+	                                            init to different than address */
+	unsigned int bytes = len;
+	unsigned int blocksize;
 	int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
-	unsigned char *buf, *bufptr;
+	unsigned char buf[4*len+4], *bufptr = buf;
 	unsigned char *buffer = m->buf;
 	unsigned char byte;
 
-
-	buf = (unsigned char*) malloc(4 * len + 4);
-	if (buf == NULL) {
-		fprintf(stderr,
-			"%s (avrftdi_flash_write): error allocating memory\n",
-			p->desc);
-		exit (-1);
-	}
-
-	bufptr = buf;
-
 	/* pre-check opcodes */
 	if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
 		fprintf(stderr,
@@ -832,9 +822,10 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 		 * is only available on 256k parts.  64k word is 128k
 		 * bytes.
 		 */
-		if (use_lext_address && !(bytes & 0x1ffff)) {
+		if(use_lext_address && ((address & 0xffff0000) != (address_prev_block & 0xffff0000))) {
 			avrftdi_lext(pgm, p, m, address);
 		}
+		address_prev_block = address;
 
 		for (i = 0; i < blocksize; i++) {
 			/*setting word*/
@@ -889,13 +880,13 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 		}
 
 		if (verbose < 3)
-			report_progress(2 * address, len, NULL);
+			report_progress(2 * address - addr, len, NULL);
 	}
 	return len;
 }
 
 static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
-			      int page_size, int len)
+		unsigned int page_size, unsigned int addr, unsigned int len)
 {
 	/*
 	 *Reading from flash
@@ -904,9 +895,11 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 	int i, buf_index, buf_size = 0, psize = m->page_size;
 	unsigned char o_buf[4*len+4], *o_ptr = o_buf;
 	unsigned char i_buf[4*len+4];
-	int address = 0;
-	int bytes = len;
-	int blocksize;
+	unsigned int address = addr/2;
+	unsigned int address_prev_block = ~address; /* start address of previous block,
+	                                            init to different than address */
+	unsigned int bytes = len;
+	unsigned int blocksize;
 	unsigned char buffer[m->size], *bufptr = buffer;
 
 	memset(o_buf, 0, sizeof(o_buf));
@@ -936,9 +929,10 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 			bytes = 0;
 		}
 
-		if(use_lext_address && !(bytes & 0x1ffff)) {
+		if(use_lext_address && ((address & 0xffff0000) != (address_prev_block & 0xffff0000))) {
 			avrftdi_lext(pgm, p, m, address);
 		}
+		address_prev_block = address;
 
 		for(i = 0; i < blocksize; i++) {
 			if(verbose > 3)
@@ -973,29 +967,29 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 			}
 		}
 	}
-	memcpy(m->buf, buffer, sizeof(buffer));
+	memcpy(m->buf + addr, buffer, len);
 
 	return len;
 }
 
 static int avrftdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
-			       int page_size, int n_bytes)
+		unsigned int page_size, unsigned int addr, unsigned int n_bytes)
 {
 	if (strcmp(m->desc, "flash") == 0)
-		return avrftdi_flash_write(pgm, p, m, page_size, n_bytes);
+		return avrftdi_flash_write(pgm, p, m, page_size, addr, n_bytes);
 	else if (strcmp(m->desc, "eeprom") == 0)
-		return avrftdi_eeprom_write(pgm, p, m, page_size, n_bytes);
+		return avrftdi_eeprom_write(pgm, p, m, page_size, addr, n_bytes);
 	else
 		return -2;
 }
 
 static int avrftdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
-			      int page_size, int n_bytes)
+		unsigned int page_size, unsigned int addr, unsigned int n_bytes)
 {
 	if (strcmp(m->desc, "flash") == 0)
-		return avrftdi_flash_read(pgm, p, m, page_size, n_bytes);
+		return avrftdi_flash_read(pgm, p, m, page_size, addr, n_bytes);
 	else if(strcmp(m->desc, "eeprom") == 0)
-		return avrftdi_eeprom_read(pgm, p, m, page_size, n_bytes);
+		return avrftdi_eeprom_read(pgm, p, m, page_size, addr, n_bytes);
 	else
 		return -2;
 }