diff --git a/avrdude/ChangeLog b/avrdude/ChangeLog
index 2c1225ef..4f3930aa 100644
--- a/avrdude/ChangeLog
+++ b/avrdude/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-29  Hannes Weisbach <hannes_weisbach@gmx.net>
+
+	* avrftdi.c: bugfixes (synchronisation) and maintenance (paged programming,
+	nicer output, separation of parameter checking and actual code)
+
 2012-07-25  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
 
 	* jtagmkII.c (jtagmkII_memtype): return MTYPE_FLASH rather than
diff --git a/avrdude/avrftdi.c b/avrdude/avrftdi.c
index fdfa7077..2d32e2bf 100644
--- a/avrdude/avrftdi.c
+++ b/avrdude/avrftdi.c
@@ -32,11 +32,15 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <stdarg.h>
 
 #include "avrdude.h"
 #include "avr.h"
 #include "pgm.h"
 #include "avrftdi.h"
+#include "avrpart.h"
+#include "tpi.h"
+#include "usbasp.h"
 
 #ifdef HAVE_LIBUSB
 #ifdef HAVE_LIBFTDI
@@ -50,37 +54,33 @@
 #  error "libusb needs either <usb.h> or <lusb0_usb.h>"
 #endif
 
-#define SCK 0x01
-#define SDO 0x02
-#define SDI 0x04
+enum { FTDI_SCK = 1, FTDI_MOSI, FTDI_MISO, FTDI_RESET };
+#define FTDI_DEFAULT_MASK ( (1 << (FTDI_SCK - 1)) | (1 << (FTDI_MOSI - 1)) )
 
-#define RX 0x20
-#define TX 0x11
+#define E(x, ftdi)                                                  \
+	do {                                                              \
+		if ((x))                                                        \
+		{                                                               \
+			fprintf(stderr, "%s:%d %s() %s: %s (%d)\n\t%s\n",             \
+					__FILE__, __LINE__, __FUNCTION__,                         \
+					#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
+			return -1;                                                    \
+		}                                                               \
+	} while(0);
 
-#define TRX (RX | TX)
+#define E_VOID(x, ftdi)                                             \
+	do {                                                              \
+		if ((x))                                                        \
+		{                                                               \
+			fprintf(stderr, "%s:%d %s() %s: %s (%d)\n\t%s\n",             \
+					__FILE__, __LINE__, __FUNCTION__,                         \
+	 			 #x, strerror(errno), errno, ftdi_get_error_string(ftdi));  \
+		}                                                               \
+	} while(0);
 
-#define TYPE_C_D 0x500
-#define TYPE_H   0x700
-#define TYPE_4H  0x800
-
-#define E(x, ftdi) if ((x)) { fprintf(stdout, "%s:%d %s() %s: %s (%d)\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, \
-	#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); return -1; }
-
-#define E_VOID(x, ftdi) if ((x)) { fprintf(stdout, "%s:%d %s() %s: %s (%d)\n\t%s\n", __FILE__, __LINE__, __FUNCTION__, \
-	#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); }
-
-typedef struct avrftdi_s {
-	struct ftdi_context* ftdic;
-	uint16_t pin_value;
-	uint16_t pin_direction;
-	uint16_t pin_inversion;
-	uint16_t led_mask;
-	int type;  /**type is  bcdDevice. C/D is 0x500 H is 0x700 4H is 0x800*/
-	int ftype; /** is from FTDI. Use TYPE_2232C, TYPE_2232H, or TYPE_4232H*/
-} avrftdi_t;
 
 #define to_pdata(pgm) \
-	(avrftdi_t *)((pgm)->cookie)
+	((avrftdi_t *)((pgm)->cookie))
 
 /* This is for running the code without having a FTDI-device.
  * The generated code is useless! For debugging purposes only.
@@ -90,6 +90,79 @@ typedef struct avrftdi_s {
  */
 //#define DRYRUN
 
+typedef struct avrftdi_s {
+	/* pointer to struct maintained by libftdi to identify the device */
+	struct ftdi_context* ftdic; 
+	/* bitmask of values for pins. bit 0 represents pin 0 ([A|B]DBUS0) */
+	uint16_t pin_value;
+	/* bitmask of pin direction. a '1' make a pin an output.
+	 * bit 0 corresponds to pin 0. */
+	uint16_t pin_direction;
+	/* don't know. not useful. someone put it in. */
+	uint16_t led_mask;
+	/* total number of pins supported by a programmer. varies with FTDI chips */
+	int pin_limit;
+} avrftdi_t;
+
+static int write_flush(avrftdi_t *);
+
+/*
+ * returns a human-readable name for a pin number. the name should match with
+ * the pin names used in FTDI datasheets.
+ */
+static char*
+ftdi_pin_name(avrftdi_t* pdata, int pin)
+{
+	static char pin_name[16];
+
+	char interface = '@';
+	char port;
+
+	/* INTERFACE_ANY is zero, so @ is used
+	 * INTERFACE_A is one, so '@' + 1 = 'A'
+	 * and so forth ...
+	 * be aware, there is an 'interface' member in ftdi_context,
+	 * however, we really want the 'index' member here.
+	 */
+	interface += pdata->ftdic->index;
+
+	/* This is FTDI's naming scheme.
+	 * probably 'D' is for data and 'C' for control
+	 */
+	if(pin < 8)
+		port = 'D';
+	else
+		port = 'C';
+
+	snprintf(pin_name, sizeof(pin_name), "%c%cBUS%d", interface, port, pin-1);
+
+	return pin_name;
+}
+
+/*
+ * output function, to save if(vebose>level)-constructs. also prefixes output
+ * with "avrftdi" to identify were messages came from.
+ * TODO: make this a macro, so that __LINE_ and __func__ macros can be used.
+ */
+static void
+avrftdi_print(int level, const char * fmt, ...)
+{
+	va_list ap;
+	if(verbose > level)
+	{
+		fprintf(stderr, "avrftdi: ");
+		va_start(ap, fmt);
+		vfprintf(stderr, fmt, ap);
+		va_end(ap);
+	}
+}
+
+/*
+ * helper function to print a binary buffer *buf of size len. begin and end of
+ * the dump are enclosed in the string contained in *desc. offset denotes the
+ * number of bytes which are printed on the first line (may be 0). after that
+ * width bytes are printed on each line
+ */
 static void buf_dump(unsigned char *buf, int len, char *desc,
 		     int offset, int width)
 {
@@ -106,6 +179,10 @@ static void buf_dump(unsigned char *buf, int len, char *desc,
 	fprintf(stderr, "%s end\n", desc);
 }
 
+/*
+ * calculates the so-called 'divisor'-value from a given frequency.
+ * the divisor is sent to the chip.
+ */
 static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
 {
 	uint32_t divisor;
@@ -131,12 +208,10 @@ static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
 		divisor = 65535;
 	}
 
-	if(verbose)
-		fprintf(stderr,
-			"%s info: clock divisor: 0x%04x\n",
-			progname, divisor);
+	avrftdi_print(0, "frequency: %d\n", 6000000/(divisor+1));
+	avrftdi_print(1, "clock divisor: 0x%04x\n", divisor);
 
-	buf[0] = 0x86;
+	buf[0] = TCK_DIVISOR;
 	buf[1] = (uint8_t)(divisor & 0xff);
 	buf[2] = (uint8_t)((divisor >> 8) & 0xff);
 
@@ -147,232 +222,275 @@ static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
 	return 0;
 }
 
-static int
-pin_limit(avrftdi_t* pdata)
-{
-	if(TYPE_4232H == pdata->ftype)
-		return 7;
-	else if(TYPE_2232C==pdata->ftype)
-		return 11;
-	else if(TYPE_2232H == pdata->ftype)
-		return 15;
-	else{
-		fprintf(stderr, "Unknown type %d (0x%x)\n",
-			pdata->ftype, pdata->ftype);
-		return 15;
-	}
-
-}
-
-/*   Add a single pin (by pin number) to the pin masks (or to pins),
- *   update pinmask[pinfunc]  */
+/*
+ * Adds a single pin to the direction mask and sets the pin state inactive in
+ * the value mask. the value of 'inactive' is chosen according to the pin
+ * configuration (high or low active).
+ */
 static int add_pin(PROGRAMMER *pgm, int pinfunc)
 {
-	int pin, inversion_mask, mlim;
+	int pin, pin_mask, inverted, fail;
 	avrftdi_t* pdata = to_pdata(pgm);
-
-	pin = pgm->pinno[pinfunc];
-	if (verbose)
-		fprintf(stderr,
-			"add_pin: %d: bit 0x%04x inv=0x%04x\n",
-			pinfunc, pin,
-			(pin & PIN_INVERSE)? (1<< ((pin&PIN_MASK) - 1)): 0);
-
-	/* non-existent definitions, go away */
-	if (pin == 0)
-		return 0;
-
-	/* see if pin should be inverted */
-	if(pin & PIN_INVERSE) {
-		pin &= PIN_MASK;
-		inversion_mask = 1 << (pin - 1);
-	} else {
-		inversion_mask = 0;
-	}
 	
-	mlim = pin_limit(pdata);
+	fail = 0;
+	pin = pgm->pinno[pinfunc] & PIN_MASK;
+	inverted = pgm->pinno[pinfunc] & PIN_INVERSE;
+	pin_mask = (1 << (pin - 1));
+
+	/* not configured */
+	if(!pin)
+	{
+		avrftdi_print(0, "Pin %s not configured\n", avr_pin_name(pinfunc));
+		return 0;
+	}
 
 	/* check that the pin number is in range */
-	if (pin > mlim) {
+	if (pin > pdata->pin_limit)
+	{
 		fprintf(stderr,
-			"%s failure: invalid pin definition (pin no > %d) in config file\n",
-			progname, mlim);
-		fprintf(stderr,
-			"pin function no %d, pin no: 0x%x\n",
-			pinfunc, pin);
-		return -1;
+			"%s invalid pin definition for pin %s. Configured as pin %d, but highest pin is %d.\n",
+			progname, avr_pin_name(pinfunc), pin, pdata->pin_limit);
+		fail = 1;
 	}
 
-	/* create the mask and check that the pin is available */
-	if (pdata->pin_direction & (1 << (pin -1)) ) {
+	/* check if the pin is still available */
+	if (pdata->pin_direction & pin_mask)
+	{
 		fprintf(stderr,
-			"%s failure: pin %d has two definitions in config file\n",
-			progname, pin);
-		return -1;
-	} else {
-		pdata->pin_direction |= (1 << (pin - 1));
-		pdata->pin_inversion |= inversion_mask;
+			"%s failure: pin %d (%s) is used twice. The second use is %s.\n",
+			progname, pin, ftdi_pin_name(pdata, pin), avr_pin_name(pinfunc));
+		fail = 1;
 	}
+
+	/* 
+	 * No need to fail for a wrongly configured led.
+	 * MISO, MOSI and SCK are fixed and correctly set during setup.
+	 * Maybe we should fail for wrongly configured VCC or BUFF pins?
+	 */
+	if(fail)
+	{
+		if(pinfunc == PIN_AVR_RESET)
+		{
+			fprintf(stderr, "Aborting, since the reset pin is wrongly configured\n");
+			return -1;
+		}
+		else
+		{
+			fprintf(stdout, "Ignoring wrongly configured pin.\n");
+			return 0;
+		}
+	}
+
+	/* all checks passed - do actual work */
+	avrftdi_print(0, "Configure pin %d (%s) as %s (%s active)\n",
+			pin, ftdi_pin_name(pdata, pin),
+			avr_pin_name(pinfunc), (inverted) ? "low": "high");
+
+	{
+		/* create mask */
+		pdata->pin_direction |= pin_mask;
+		/* and set default value */
+		if(inverted)
+			pdata->pin_value |= pin_mask;
+		else
+			pdata->pin_value &= ~(pin_mask);
+	}
+
 	if(PIN_LED_ERR == pinfunc ||
-	   PIN_LED_VFY == pinfunc ||
-	   PIN_LED_RDY == pinfunc ||
-	   PIN_LED_PGM == pinfunc) {
-		pdata->led_mask|=(1 << (pin - 1));
+		 PIN_LED_VFY == pinfunc ||
+		 PIN_LED_RDY == pinfunc ||
+		 PIN_LED_PGM == pinfunc) {
+		pdata->led_mask |= pin_mask;
 	}
-
+	
 	return 0;
 }
 
-/*   Add pins by pin mask    */
-
+/*
+ * Add pins by pin mask
+ * Check an entire mask for correctness and plausibility. Performed checks are
+ * the pin number is lower that the total number of pins and the pin is not
+ * configured yet.
+ * If at least one test fails, the entire mask is discarded.
+ * These basic tests could possibly moved to avrdude core, since it does not
+ * contain any tests (as far as I can tell).
+ */
 static int add_pins(PROGRAMMER *pgm, int pinfunc)
 {
-	int i, pin, mlim;
-	uint32_t mask, inversion_mask=0;
+	int pin, inverted, fail;
+	uint32_t pin_mask, pin_bit;
 	avrftdi_t* pdata = to_pdata(pgm);
 
-	pin = pgm->pinno[pinfunc];
+	pin_mask = (pgm->pinno[pinfunc] & PIN_MASK) >> 1;
+	/* FIXME: I think you cannot inverse these multi-pin options */
+	inverted = pgm->pinno[pinfunc] & PIN_INVERSE;
 
-	if(pin & PIN_INVERSE){
-		pin &= PIN_MASK;
-		inversion_mask = pin >>1;
-	}
-	pin >>= 1;
-	if (verbose)
-		fprintf(stderr,
-			"add_pins: %d: 0x%04x, inv=0x%04x\n",
-			pinfunc, pin, inversion_mask);
-	mask = pin;
-	
-	mlim = pin_limit(pdata);
-	
-	if (mask >= 1 << mlim) {
-		fprintf(stderr,
-			"%s failure: pin list has pins out of range (%x>%x): ",
-			progname, mask, 1 << mlim);
-		mask &= ~(1 << mlim) - 1;
-	}
-	else if (mask & pdata->pin_direction) {
-		fprintf(stderr,
-			"%s failure: conflicting pins in pin list: ",
-			progname);
-		mask &= pdata->pin_direction;
-	}
-	else {
-		pdata->pin_direction |= (uint16_t)mask;
-		pdata->pin_inversion |= inversion_mask;
+	if(!pin_mask)
+	{
+		avrftdi_print(0, "Pins for %s not configured.\n", avr_pin_name(pinfunc));
 		return 0;
 	}
 
-	/* print the list of pins, if needed */
-	i = 0;
-	while (mask > 1) {
-		if (mask & 1)
-			fprintf(stderr, "%d, ", i);
-		mask >>= 1;
-		i++;
-	}
-	if (mask > 0)
-		fprintf(stderr, "%d\n", i);
-	return -1;
-}
+	fail = 0;
+	/* check every configured pin */
+	for(pin = 0; (1 << pin) & (PIN_MASK); pin++)
+	{
+		pin_bit = 1 << pin;
+		
+		/* skip, if this pin is not in the mask to be configured */
+		if(!(pin_bit & pin_mask))
+			continue;
+		
 
-
-static int write_flush(avrftdi_t* pdata)
-{
-	unsigned char buf[6];
-	if(verbose > 2)
-		fprintf(stderr,
-			"%s info: direction: 0x%04x, value: 0x%04x, inversion: 0x%04x\n",
-			progname, pdata->pin_direction, pdata->pin_value, pdata->pin_inversion);
-
-	buf[0] = 0x80;
-	buf[1] = (pdata->pin_value) & 0xff;
-	buf[2] = (pdata->pin_direction) & 0xff;
-	buf[3] = 0x82;
-	buf[4] = ((pdata->pin_value) >> 8) & 0xff;
-	buf[5] = ((pdata->pin_direction) >> 8) & 0xff;
-
-#ifndef DRYRUN
-	E(ftdi_write_data(pdata->ftdic, buf, 6) != 6, pdata->ftdic);
-
-#endif
-
-	if (verbose > 3)
-		fprintf(stderr, "FTDI LOG: %02x %02x %02x %02x %02x %02x\n",
-		       buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
-
-	/* we need to flush here, because set_pin is used as reset.
-	 * if we want to sleep reset periods, we must be certain the
-	 * avr has got the reset signal when we start sleeping.
-	 * (it may be stuck in the USB stack or some USB hub)
-	 */
-#ifndef DRYRUN
-	E(ftdi_usb_purge_buffers(pdata->ftdic), pdata->ftdic);
-#endif
-
-	return 0;
-
-}
-
-/* this function sets or clears a GPIO pin */
-static int set_pin(avrftdi_t* pdata, int pin, int value)
-{
-	int bit;
-	uint16_t tval;
-	if (0 == pin){
-		if(verbose > 2)
+		/* 0 is not a valid pin, see above, we use 1 << (pin - 1) to create pin_bit */
+		if(pin + 1 > pdata->pin_limit)
+		{
 			fprintf(stderr,
-				"%s info: Pin is zero val %d!\n",
-				progname, value);
-		return 1;
-	}
-	--pin;
-	bit= 1 << (pin);
-	if (pdata->pin_inversion & bit) {
-		value = !value;
-	}
-	if (value)
-		value = bit;
+				"%s invalid pin definition for pin %s. Configured as pin %d, but highest pin is %d.\n",
+				progname, avr_pin_name(pinfunc), pin + 1, pdata->pin_limit);
+			fail = 1;
+		}
+
+		if(pin_bit & pdata->pin_direction)
+		{
+			fprintf(stderr,
+				"%s failure: pin %d (%s) is used twice. The second use is %s.\n",
+				progname, pin, ftdi_pin_name(pdata, pin), avr_pin_name(pinfunc));
+			fail = 1;
+		}
+
+	}
+
+	/* we can ignore those, because only VCC and BUFF pins, can have multiples.
+	 * VCC and BUFF are not essential
+	 */
+	if(fail)
+	{
+			fprintf(stdout, "Ignoring wrongly configured pins.\n");
+			return 0;
+	}
+
+	/* conditional output */
+	for(pin = 0; (1 << pin) & (PIN_MASK); pin++)
+	{
+		pin_bit = 1 << pin;
+
+		/* skip if pin is not set */
+		if(!(pin_bit & pin_mask))
+			continue;
+
+		/* remember, we count from 1, not 0 */
+		avrftdi_print(0, "Configured pin %d (%s) as %s (%s active)\n",
+			pin+1, ftdi_pin_name(pdata, pin+1),
+			avr_pin_name(pinfunc), (inverted) ? "low": "high");
+	}
+
+	/* do the work */
+	pdata->pin_direction |= (uint16_t)pin_mask;
+	if(inverted)
+		pdata->pin_value |= pin_mask;
+	else
+		pdata->pin_value &= ~pin_mask;
 
-	if (verbose > 1)
-		fprintf(stderr,
-			"%s info: pin %04x bit %04x value 0x%04x\n",
-			progname, pin + 1, bit, value);
-	/* set bits depending on value */
-	/*pin_value ^= (-value ^ pin_value) & (1 << (pin - 1));  */
-	tval = (pdata->pin_value & (~bit)) | value;
-	if (tval != pdata->pin_value) {
-		pdata->pin_value = tval;
-		return write_flush(pdata);
-	} else if (verbose > 1)
-	    fprintf(stderr, "SameVal\n");
 	return 0;
-
 }
 
-/* this function sets or clears one or more GPIO pin these are bit-mapped */
-static int set_pins(avrftdi_t* pdata, int pin, int value)
+/*
+ * This function sets or clears any pin, except SCK, MISO and MOSI. Depending
+ * on the pin configuration, a non-zero value sets the pin in the 'active'
+ * state (high active, low active) and a zero value sets the pin in the
+ * inactive state.
+ * Because we configured the pin direction mask earlier, nothing bad can happen
+ * here.
+ */
+static int set_pin(PROGRAMMER * pgm, int pinfunc, int value)
 {
-	if (0 == pin) {
-		if(verbose > 2)
-			fprintf(stderr,"%s info: Pins is zero!\n",progname);
+	
+	int pin, pin_mask;
+	int inverted;
+	
+	avrftdi_t* pdata = to_pdata(pgm);
+
+	pin = pgm->pinno[pinfunc] & PIN_MASK;
+	inverted = pgm->pinno[pinfunc] & PIN_INVERSE;
+
+	pin_mask = 1 << (pin - 1);
+
+	/* make value 0 or 1 and invert, if necessary */
+	value = (inverted) ? !value : !!value;
+
+	if (!pin) {
+		/* this error message is really annoying, maybe use a ratelimit? */
+	/*
+		avrftdi_print(2, "%s info: Pin is zero, value: %d!\n",
+				progname, value);
+	*/
 		return 1;
 	}
-	pin >>=1;
-	if (pdata->pin_inversion & pin) {
-		value = !value;
-	}
-	if (value)
-		value = pin;
 
-	if (verbose)
-		fprintf(stderr,
-			"%s info: pin %04x value %d\n",
-			progname, pin, value);
+	if (value)
+		value = pin_mask;
+
+	avrftdi_print(1, "Setting pin %d (%s) as %s: %s (%s active)\n", pin,
+			ftdi_pin_name(pdata, pin), avr_pin_name(pinfunc),
+			(value) ? "high" : "low", (inverted) ? "low" : "high");
+
+	/* set bits depending on value */
+	//tval = (pdata->pin_value & (~pin_mask)) | pin_mask;
+	pdata->pin_value ^= (-value ^ pdata->pin_value) & pin_mask;
+	//fprintf(stderr, "%x %x\n", tval, pdata->pin_value);
+	
+	return write_flush(pdata);
+}
+
+/*
+ * This function sets or clears a group of pins - VCC or BUFF.
+ * the semantics are the same as for single pins, described above.
+ */
+static int set_pins(PROGRAMMER * pgm, int pinfunc, int value)
+{
+	int pin, pin_mask;
+	int inverted;
+	int pin_bit;
+	
+	avrftdi_t* pdata = to_pdata(pgm);
+
+	pin = pgm->pinno[pinfunc] & PIN_MASK;
+	inverted = pgm->pinno[pinfunc] & PIN_INVERSE;
+
+	pin_mask = pin >> 1;
+	
+	value = (inverted) ? !value : !!value;
+
+	if (!pin) {
+		/* dito above */
+		return 1;
+	}
+
+	if(value)
+		value = pin_mask;
+
+	/* conditional output */
+	for(pin = 0; (1 << pin) & (PIN_MASK); pin++)
+	{
+		pin_bit = 1 << pin;
+
+		/* skip if pin is not set */
+		if(!(pin_bit & pin_mask))
+			continue;
+
+		/* remember, we count from 1, not 0 */
+		avrftdi_print(0, "Setting pin %d (%s) as %s: %s (%s active)\n",
+			pin+1, ftdi_pin_name(pdata, pin+1), avr_pin_name(pinfunc),
+			(value) ? "high" : "low", (inverted) ? "low": "high");
+	}
+
 	/* set bits depending on value */
 	/*pin_value ^= (-value ^ pin_value) & (1 << (pin - 1));  */
-	pdata->pin_value = (pdata->pin_value & (~pin)) | value;
+	pdata->pin_value ^= (-value ^ pdata->pin_value) & pin_mask;
+
+	/*pdata->pin_value = (pdata->pin_value & (~pin_mask)) | value;*/
+	
 	return write_flush(pdata);
 }
 
@@ -381,22 +499,22 @@ static int set_pins(avrftdi_t* pdata, int pin, int value)
  */
 static int set_led_pgm(struct programmer_t * pgm, int value)
 {
-	return set_pin(to_pdata(pgm), pgm->pinno[PIN_LED_PGM], value);
+	return set_pin(pgm, PIN_LED_PGM, value);
 }
 
 static int set_led_rdy(struct programmer_t * pgm, int value)
 {
-	return set_pin(to_pdata(pgm), pgm->pinno[PIN_LED_RDY], value);
+	return set_pin(pgm, PIN_LED_RDY, value);
 }
 
 static int set_led_err(struct programmer_t * pgm, int value)
 {
-	return set_pin(to_pdata(pgm), pgm->pinno[PIN_LED_ERR], value);
+	return set_pin(pgm, PIN_LED_ERR, value);
 }
 
 static int set_led_vfy(struct programmer_t * pgm, int value)
 {
-	return set_pin(to_pdata(pgm), pgm->pinno[PIN_LED_VFY], value);
+	return set_pin(pgm, PIN_LED_VFY, value);
 }
 
 static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char *cmd,
@@ -406,8 +524,8 @@ static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char
 	int n;
 	unsigned char buf[4 + buf_size];
 
-	if (mode & TX) {
-		buf[0] = mode;
+	if (mode & MPSSE_DO_WRITE) {
+		buf[0] = mode | MPSSE_WRITE_NEG;
 		buf[1] = ((buf_size - 1) & 0xff);
 		buf[2] = (((buf_size - 1) >> 8) & 0xff);
 
@@ -419,7 +537,7 @@ static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char
 #endif
 	}
 
-	if (mode & RX) {
+	if (mode & MPSSE_DO_READ) {
 		memset(buf, 0, sizeof(buf));
 		do {
 #ifndef DRYRUN
@@ -437,6 +555,57 @@ static int avrftdi_transmit(avrftdi_t* pdata, unsigned char mode, unsigned char
 	return k;
 }
 
+static int write_flush(avrftdi_t* pdata)
+{
+	unsigned char buf[6];
+
+	avrftdi_print(2, 
+			"%s info: direction: 0x%04x, value: 0x%04x\n",
+			progname, pdata->pin_direction, pdata->pin_value);
+
+	buf[0] = SET_BITS_LOW;
+	buf[1] = (pdata->pin_value) & 0xff;
+	buf[2] = (pdata->pin_direction) & 0xff;
+	buf[3] = SET_BITS_HIGH;
+	buf[4] = ((pdata->pin_value) >> 8) & 0xff;
+	buf[5] = ((pdata->pin_direction) >> 8) & 0xff;
+
+#ifndef DRYRUN
+	E(ftdi_write_data(pdata->ftdic, buf, 6) != 6, pdata->ftdic);
+
+#endif
+
+	avrftdi_print(3, "FTDI LOG: %02x %02x %02x %02x %02x %02x\n",
+		       buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+	/* we need to flush here, because set_pin is used as reset.
+	 * if we want to sleep reset periods, we must be certain the
+	 * avr has got the reset signal when we start sleeping.
+	 * (it may be stuck in the USB stack or some USB hub)
+	 *
+	 * Add.: purge does NOT flush. It clears. Also, it is unkown, when the purge
+	 * command actually arrives at the chip.
+	 * Use read-pin-status command as sync.
+	 */
+#ifndef DRYRUN
+	//E(ftdi_usb_purge_buffers(pdata->ftdic), pdata->ftdic);
+
+	unsigned char cmd[] = { GET_BITS_LOW, SEND_IMMEDIATE };
+	unsigned int n;
+	int num = 0;
+	E(ftdi_write_data(pdata->ftdic, cmd, sizeof(cmd)) != sizeof(cmd), pdata->ftdic);
+	do
+	{
+		n = ftdi_read_data(pdata->ftdic, cmd, 1);
+		E(n < 0, pdata->ftdic);
+	} while(n < 1);
+	
+#endif
+
+	return 0;
+}
+
+
 static int avrftdi_open(PROGRAMMER * pgm, char *port)
 {
 	int vid, pid, interface, snfound;
@@ -447,10 +616,15 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
 	
 	avrftdi_t* pdata = to_pdata(pgm);
 
+	/************************
+	 * parameter validation *
+	 ************************/
+
 	/* use vid/pid in following priority: config,
 	 * defaults. cmd-line is currently not supported */
 	snfound = 0;
 	foundsn = NULL;
+	memset(serial, 0, sizeof(serial));
 
 	if (pgm->usbvid)
 		vid = pgm->usbvid;
@@ -475,30 +649,30 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
 			progname, pgm->usbdev);
 		interface = INTERFACE_A;
 	}
+
+	/**************
+	 * USB lookup *
+	 **************/
+
 #ifndef DRYRUN
 	found_dev = NULL;
 	if (ftdi_usb_find_all(pdata->ftdic, &devlist, vid, pid)) {
 		devlist_ptr = devlist;
 		do {
 			ftdi_usb_get_strings(pdata->ftdic, devlist_ptr->dev,
-					     NULL, 0, NULL, 0, serial, 255);
+					     NULL, 0, NULL, 0, serial, sizeof(serial));
 
-			if (verbose)
-				fprintf(stderr,
-					"%s: device: %s, serial number: %s type 0x%04x found\n",
-					progname, devlist_ptr->dev->filename,
-					serial, devlist_ptr->dev->descriptor.bcdDevice);
+			avrftdi_print(1, "%s: device: %s, serial number: %s type 0x%04x found\n",
+					progname, devlist_ptr->dev->filename,	serial,
+					devlist_ptr->dev->descriptor.bcdDevice);
 
 			if (!snfound) {
 				if (strcmp(pgm->usbsn, serial) == 0){
 					foundsn = strdup(serial);
 					snfound = 1;
 					found_dev = devlist_ptr->dev;
-					pdata->type = devlist_ptr->dev->descriptor.bcdDevice;
 				}
 			}else {
-				if (0 == pdata->type)	/**we assume it will attach to first found.  */
-					pdata->type = devlist_ptr->dev->descriptor.bcdDevice;
 				if (NULL == found_dev)
 					found_dev = devlist_ptr->dev;
 				if (NULL == foundsn)
@@ -521,87 +695,30 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
 			progname, vid, pid, pgm->usbsn);
 		return -1;
 	}
-	if (verbose) {
-		fprintf(stderr,
-			"%s: Using device VID:PID %04x:%04x type 0x%04x(",
-			progname, vid, pid, pdata->type);
-		switch (pdata->type) {
-			case TYPE_C_D:
-			    fprintf(stderr,"C/D"); break;
-			case TYPE_H:
-			    fprintf(stderr,"H"); break;
-			case TYPE_4H:
-			    fprintf(stderr,"4H"); break;
-			default:
-			    fprintf(stderr,"unknown %04x",pdata->type); break;
-		}
 
-		fprintf(stderr,") and SN '%s'.\n", foundsn);
-	}
-	if (pdata->type == TYPE_C_D && INTERFACE_B == interface){
-		fprintf(stderr,
-			"%s: Type C/D found. Setting interface to A\n",
-			progname);
-		interface = INTERFACE_A;
-	}
-	/*must be A for mpsse if C/D, can be A/B for H */
-	if (verbose)
-		fprintf(stderr,
-			"%s: Using USB Interface %c\n",
-			progname, INTERFACE_A == interface? 'A': 'B');
+	avrftdi_print(1,
+			"%s: Using device VID:PID %04x:%04x and SN '%s' on interface %c.\n",
+			progname, vid, pid, foundsn, INTERFACE_A == interface? 'A': 'B');
+	
 	free(foundsn);
+#endif
+
+	/****************
+	 * Device setup *
+	 ****************/
+
 	E(ftdi_set_interface(pdata->ftdic, interface) < 0, pdata->ftdic);
 	E(ftdi_usb_open_dev(pdata->ftdic,found_dev) <0, pdata->ftdic);
-/*	E(ftdi_usb_open_desc(&ftdic, vid,pid,NULL,0==pgm->usbsn[0]?NULL:pgm->usbsn) < 0);  */
-	pdata->ftype=pdata->ftdic->type;
-#endif
+	E(ftdi_usb_reset(pdata->ftdic) < 0, pdata->ftdic);
+	ftdi_set_latency_timer(pdata->ftdic, 1);
 
-
-	if (SCK != (1 << (pgm->pinno[PIN_AVR_SCK] - 1))
-		|| SDO != (1 << (pgm->pinno[PIN_AVR_MOSI] - 1))
-		|| SDI != (1 << (pgm->pinno[PIN_AVR_MISO] - 1))) {
-		fprintf(stderr,
-			"%s failure: pinning for FTDI MPSSE must be:\n"
-			"\tSCK: 1, SDO: 2, SDI: 3(is: %d,%d,%d)\n",
-			progname,
-			pgm->pinno[PIN_AVR_SCK],
-			pgm->pinno[PIN_AVR_MOSI],
-			pgm->pinno[PIN_AVR_MISO]);
-		fprintf(stderr, "Setting pins accordingly ...\n");
-			pgm->pinno[PIN_AVR_SCK] = 1;
-			pgm->pinno[PIN_AVR_MOSI] = 2;
-			pgm->pinno[PIN_AVR_MISO] = 3;
-
-	}
-	if(verbose)
-		fprintf(stderr,
-			"%s info: reset pin value: %x\n",
-			progname, pgm->pinno[PIN_AVR_RESET]-1);
-	if (pgm->pinno[PIN_AVR_RESET] < 4 || pgm->pinno[PIN_AVR_RESET] == 0) {
-		fprintf(stderr,
-			"%s failure: RESET pin clashes with data pin or is not set.\n",
-			progname);
-		fprintf(stderr, "Setting to default-value 4\n");
-		pgm->pinno[PIN_AVR_RESET] = 4;
-	}
-	
-	pdata->pin_direction = (0x3 | (1 << (pgm->pinno[PIN_AVR_RESET] - 1)));
-
-	/* gather the rest of the pins */
-	if (add_pins(pgm, PPI_AVR_VCC)) return -1;
-	if (add_pins(pgm, PPI_AVR_BUFF)) return -1;
-	if (add_pin(pgm, PIN_LED_ERR)) return -1;
-	if (add_pin(pgm, PIN_LED_RDY)) return -1;
-	if (add_pin(pgm, PIN_LED_PGM)) return -1;
-	if (add_pin(pgm, PIN_LED_VFY)) return -1;
 #ifndef DRYRUN
-	E(ftdi_set_bitmode(pdata->ftdic, pdata->pin_direction & 0xff, BITMODE_MPSSE) < 0, pdata->ftdic);	/*set SPI */
-	write_flush(pdata);
+	/* set SPI mode */
+	E(ftdi_set_bitmode(pdata->ftdic, 0, BITMODE_RESET) < 0, pdata->ftdic);
+	E(ftdi_set_bitmode(pdata->ftdic, pdata->pin_direction & 0xff, BITMODE_MPSSE) < 0, pdata->ftdic);
+	E(ftdi_usb_purge_buffers(pdata->ftdic), pdata->ftdic);
+
 #endif
-	if (verbose > 1) {
-		fprintf(stderr, "pin direction mask: %04x\n", pdata->pin_direction);
-		fprintf(stderr, "pin value mask: %04x\n", pdata->pin_value);
-	}
 
 	if (pgm->baudrate) {
 		set_frequency(pdata, pgm->baudrate);
@@ -610,9 +727,78 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
 	} else {
 		set_frequency(pdata, pgm->baudrate ? pgm->baudrate : 150000);
 	}
-	/**set the ready LED, if we have one .. and set our direction up */
+
+	/*************
+	 * pin setup *
+	 *************/
+
+	if ( FTDI_SCK != pgm->pinno[PIN_AVR_SCK]
+		|| FTDI_MOSI != pgm->pinno[PIN_AVR_MOSI]
+		|| FTDI_MISO != pgm->pinno[PIN_AVR_MISO])
+	{
+		fprintf(stderr, "%s failure: pinning for FTDI MPSSE must be:\n", progname);
+		fprintf(stderr, "\t%s: 1, %s: 2, %s: 3(is: %d,%d,%d)\n",
+			avr_pin_name(PIN_AVR_SCK), avr_pin_name(PIN_AVR_MOSI),
+			avr_pin_name(PIN_AVR_MISO), pgm->pinno[PIN_AVR_SCK],
+			pgm->pinno[PIN_AVR_MOSI],	pgm->pinno[PIN_AVR_MISO]);
+
+		fprintf(stderr, "Setting pins accordingly ...\n");
+			pgm->pinno[PIN_AVR_SCK] = FTDI_SCK;
+			pgm->pinno[PIN_AVR_MOSI] = FTDI_MOSI;
+			pgm->pinno[PIN_AVR_MISO] = FTDI_MISO;
+	}
+	
+	avrftdi_print(1, "reset pin value: %x\n", pgm->pinno[PIN_AVR_RESET]-1);
+
+	if ( pgm->pinno[PIN_AVR_RESET] < FTDI_RESET
+		|| pgm->pinno[PIN_AVR_RESET] == 0)
+	{
+		fprintf(stderr,
+			"%s failure: RESET pin clashes with data pin or is not set.\n",
+			progname);
+		fprintf(stderr, "Setting to default-value 4\n");
+		pgm->pinno[PIN_AVR_RESET] = FTDI_RESET;
+	}
+	
+	//pdata->pin_direction = (0x3 | (1 << (pgm->pinno[PIN_AVR_RESET] - 1)));
+
+	/* set pin limit depending on chip type */
+	switch(pdata->ftdic->type) {
+		case TYPE_2232C:
+			pdata->pin_limit = 15;
+			break;
+		case TYPE_2232H:
+			pdata->pin_limit = 11;
+			break;
+		case TYPE_4232H:
+		default:
+			pdata->pin_limit = 7;
+	}
+	
+	/* add SCK, MOSI and RESET as output pins - MISO needs no configuration */
+	if (add_pin(pgm, PIN_AVR_SCK)) return -1;
+	if (add_pin(pgm, PIN_AVR_MOSI)) return -1;
+	if (add_pin(pgm, PIN_AVR_RESET)) return -1;
+
+
+	/* gather the rest of the pins */
+	if (add_pins(pgm, PPI_AVR_VCC)) return -1;
+	if (add_pins(pgm, PPI_AVR_BUFF)) return -1;
+	if (add_pin(pgm, PIN_LED_ERR)) return -1;
+	if (add_pin(pgm, PIN_LED_RDY)) return -1;
+	if (add_pin(pgm, PIN_LED_PGM)) return -1;
+	if (add_pin(pgm, PIN_LED_VFY)) return -1;
+
+	avrftdi_print(1, "pin direction mask: %04x\n", pdata->pin_direction);
+	avrftdi_print(1, "pin value mask: %04x\n", pdata->pin_value);
+
+	/**********************************************
+	 * set the ready LED and set our direction up *
+	 **********************************************/
+
 	set_led_rdy(pgm,0);
-	set_led_rdy(pgm,1);
+	set_led_pgm(pgm,1);
+
 	return 0;
 }
 
@@ -621,17 +807,19 @@ static void avrftdi_close(PROGRAMMER * pgm)
 	avrftdi_t* pdata = to_pdata(pgm);
 
 	if(pdata->ftdic->usb_dev) {
-		set_pins(pdata, pgm->pinno[PPI_AVR_BUFF], ON);
-		set_pin(pdata, pgm->pinno[PIN_AVR_RESET], ON);
+		set_pins(pgm, PPI_AVR_BUFF, ON);
+		set_pin(pgm, PIN_AVR_RESET, ON);
 		/**Stop driving the pins - except for the LEDs */
-		if (verbose > 1)
-			fprintf(stderr,
-				"LED Mask=0x%04x value =0x%04x &=0x%04x\n",
+		
+		avrftdi_print(1, "LED Mask=0x%04x value =0x%04x &=0x%04x\n",
 				pdata->led_mask, pdata->pin_value, pdata->led_mask & pdata->pin_value);
+		
 		pdata->pin_direction = pdata->led_mask;
 		pdata->pin_value &= pdata->led_mask;
 		write_flush(pdata);
 #ifndef DRYRUN
+		/* reset state recommended by FTDI */
+		ftdi_set_bitmode(pdata->ftdic, 0, BITMODE_RESET);
 		E_VOID(ftdi_usb_close(pdata->ftdic), pdata->ftdic);
 #endif
 	}
@@ -639,24 +827,23 @@ static void avrftdi_close(PROGRAMMER * pgm)
 	return;
 }
 
-
 static int avrftdi_initialize(PROGRAMMER * pgm, AVRPART * p)
 {
 	avrftdi_t* pdata = to_pdata(pgm);
 
-	set_pin(pdata, pgm->pinno[PIN_AVR_RESET], OFF);
-	set_pins(pdata, pgm->pinno[PPI_AVR_BUFF], OFF);
-	set_pin(pdata, pgm->pinno[PIN_AVR_SCK], OFF);
+	set_pin(pgm, PIN_AVR_RESET, OFF);
+	set_pins(pgm, PPI_AVR_BUFF, OFF);
+	set_pin(pgm, PIN_AVR_SCK, OFF);
 	/*use speed optimization with CAUTION*/
 	usleep(20 * 1000);
 
 	/* giving rst-pulse of at least 2 avr-clock-cycles, for
 	 * security (2us @ 1MHz) */
-	set_pin(pdata, pgm->pinno[PIN_AVR_RESET], ON);
+	set_pin(pgm, PIN_AVR_RESET, ON);
 	usleep(20 * 1000);
 
 	/*setting rst back to 0 */
-	set_pin(pdata, pgm->pinno[PIN_AVR_RESET], OFF);
+	set_pin(pgm, PIN_AVR_RESET, OFF);
 	/*wait at least 20ms bevor issuing spi commands to avr */
 	usleep(20 * 1000);
 
@@ -683,7 +870,7 @@ static int avrftdi_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res
 {
 	/* Do not use 'sizeof(cmd)'. => message from cppcheck:
 	   Using sizeof for array given as function argument returns the size of pointer. */
-	return avrftdi_transmit(to_pdata(pgm), TRX, cmd, res, 4);
+	return avrftdi_transmit(to_pdata(pgm), MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, res, 4);
 }
 
 
@@ -691,7 +878,6 @@ static int avrftdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
 {
 	int i;
 	unsigned char buf[4];
-	avrftdi_t* pdata = to_pdata(pgm);
 
 	memset(buf, 0, sizeof(buf));
 
@@ -708,9 +894,9 @@ static int avrftdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
 		pgm->cmd(pgm, buf, buf);
 		if (buf[p->pollindex-1] != p->pollvalue) {
 			//try resetting
-			set_pin(pdata, pgm->pinno[PIN_AVR_RESET], ON);
+			set_pin(pgm, PIN_AVR_RESET, ON);
 			usleep(20);
-			set_pin(pdata, pgm->pinno[PIN_AVR_RESET], OFF);
+			set_pin(pgm, PIN_AVR_RESET, OFF);
 			avr_set_bits(p->op[AVR_OP_PGM_ENABLE], buf);
 		} else
 			return 0;
@@ -747,9 +933,11 @@ static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
 
 
 /* Load extended address byte command */
-static int avrftdi_lext(avrftdi_t* pdata, AVRPART *p, AVRMEM *m, unsigned int address)
+static int
+avrftdi_lext(avrftdi_t* pdata, AVRPART *p, AVRMEM *m, unsigned int address)
 {
-	unsigned char buf[] = {0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
+	unsigned char buf[] =
+			{ MPSSE_DO_WRITE | MPSSE_WRITE_NEG, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 	avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], &buf[3]);
 	avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], &buf[3], address);
@@ -759,7 +947,8 @@ static int avrftdi_lext(avrftdi_t* pdata, AVRPART *p, AVRMEM *m, unsigned int ad
 			 "load extended address command", 0, 16 * 3);
 
 #ifndef DRYRUN
-	E(ftdi_write_data(pdata->ftdic, buf, sizeof(buf)) != sizeof(buf), pdata->ftdic);
+	E(ftdi_write_data(pdata->ftdic, buf, sizeof(buf)) != sizeof(buf),
+			pdata->ftdic);
 #endif
 	return 0;
 }
@@ -767,18 +956,20 @@ static int avrftdi_lext(avrftdi_t* pdata, AVRPART *p, AVRMEM *m, unsigned int ad
 static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
 		unsigned int page_size, unsigned int addr, unsigned int len)
 {
-	unsigned char cmd[4];
+	unsigned char cmd[] =
+			{ MPSSE_DO_WRITE | MPSSE_WRITE_NEG, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	unsigned char *data = &m->buf[addr];
 	unsigned int add;
 
-	avr_set_bits(m->op[AVR_OP_WRITE], cmd);
+	avr_set_bits(m->op[AVR_OP_WRITE], &cmd[3]);
 
 	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++);
+		avr_set_addr(m->op[AVR_OP_WRITE], &cmd[3], add);
+		avr_set_input(m->op[AVR_OP_WRITE], &cmd[3], *data++);
 
-		avrftdi_transmit(to_pdata(pgm), TX, cmd, cmd, 4);
+		E(ftdi_write_data(to_pdata(pgm)->ftdic, cmd, sizeof(cmd)) != sizeof(cmd),
+				to_pdata(pgm)->ftdic);
 
 		usleep((m->max_write_delay));
 	}
@@ -793,13 +984,13 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
 	unsigned int add;
 
 	memset(buffer, 0, sizeof(buffer));
-
 	for (add = addr; add < addr + len; add++)
 	{
+		memset(cmd, 0, sizeof(cmd));
 		avr_set_bits(m->op[AVR_OP_READ], cmd);
 		avr_set_addr(m->op[AVR_OP_READ], cmd, add);
 
-		avrftdi_transmit(to_pdata(pgm), TRX, cmd, cmd, 4);
+		avrftdi_transmit(to_pdata(pgm), MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, cmd, 4);
 
 		avr_get_output(m->op[AVR_OP_READ], cmd, bufptr++);
 	}
@@ -811,16 +1002,17 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
 static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 		unsigned int page_size, unsigned int addr, unsigned int len)
 {
-	int i;
-	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[4*len+4], *bufptr = buf;
+	
+	unsigned int word;
+	unsigned int poll_index;
+	unsigned int buf_size;
+
+	unsigned char poll_byte;
 	unsigned char *buffer = &m->buf[addr];
-	unsigned char byte;
+	unsigned char buf[4*len+4], *bufptr = buf;
+
+	memset(buf, 0, sizeof(buf));
 
 	/* pre-check opcodes */
 	if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
@@ -836,113 +1028,121 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 		return -1;
 	}
 
-	//page_size = (page_size > m->page_size) ? m->page_size : page_size - 8;
+	if(page_size != m->page_size) {
+		fprintf(stderr,
+			"%s: Something funny is going on. Parameter"
+			"page_size is %d, buf m->page_size is %d. Using"
+			"the latter.\n", progname, page_size, m->page_size);
+	}
+
 	page_size = m->page_size;
 
-	while (bytes) {
-		if (bytes > page_size) {
-			blocksize = (page_size)/2;
-			bytes -= (page_size);
-		} else {
-			blocksize = bytes/2;
-			bytes = 0;
-		}
-
-		if(verbose > 2)
-			fprintf(stderr,
-				"-< bytes = %d of %d, blocksize = %d of %d\n",
-				len - bytes, len, blocksize, m->page_size / 2);
-
-		/* if we do cross a 64k word boundary (or write the
-		 * first page), we need to issue a 'load extended
-		 * address byte' command, which is defined as 0x4d
-		 * 0x00 <address byte> 0x00.  As far as i know, this
-		 * is only available on 256k parts.  64k word is 128k
-		 * bytes.
-		 */
-		if(use_lext_address && ((address & 0xffff0000) != (address_prev_block & 0xffff0000))) {
-			avrftdi_lext(to_pdata(pgm), p, m, address);
-		}
-		address_prev_block = address;
-
-		for (i = 0; i < blocksize; i++) {
-			/*setting word*/
-			avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], bufptr);
-			avr_set_addr(m->op[AVR_OP_LOADPAGE_LO], bufptr, address);
-			avr_set_input(m->op[AVR_OP_LOADPAGE_LO], bufptr, *buffer++);
-			bufptr += 4;
-			avr_set_bits(m->op[AVR_OP_LOADPAGE_HI], bufptr);
-			avr_set_addr(m->op[AVR_OP_LOADPAGE_HI], bufptr, address);
-			avr_set_input(m->op[AVR_OP_LOADPAGE_HI], bufptr, *buffer++);
-			bufptr += 4;
-			address++;
-		}
-
-		if (verbose > 2)
-			fprintf(stderr,
-				"address = %d, page_size = %d\n",
-				address, m->page_size);
-
-		if (((address * 2) % m->page_size) == 0 || bytes == 0) {
-			if (m->op[AVR_OP_WRITEPAGE] == NULL) {
-				fprintf(stderr,
-					"%s failure: Write Page (WRITEPAGE) command not defined for %s\n",
-					progname, p->desc);
-				exit(1);
-			} else {
-				avr_set_bits(m->op[AVR_OP_WRITEPAGE], bufptr);
-			}
-			/* setting page address highbyte */
-			avr_set_addr(m->op[AVR_OP_WRITEPAGE],
-				     bufptr, address - 1);
-			bufptr += 4;
-		}
-
-		buf_size = bufptr - buf;
-
-		if(verbose > 3)
-			buf_dump(buf, buf_size, "command buffer", 0, 16*3);
-		if(verbose > 2)
-			fprintf(stderr,
-				"%s info: buffer size: %d\n",
-				progname, buf_size);
-
-		avrftdi_transmit(to_pdata(pgm), TX, buf, buf, buf_size);
-
-		bufptr = buf;
-		if (((address * 2) % m->page_size) == 0 || bytes == 0) {
-			do {
-				pgm->read_byte(pgm, p, m,
-					       (address * 2) - 1, &byte);
-			} while (m->buf[(address*2) - 1] != byte);
-		}
-
-		if (verbose < 3)
-			report_progress(2 * address - addr, len, NULL);
+	/* if we do cross a 64k word boundary (or write the
+	 * first page), we need to issue a 'load extended
+	 * address byte' command, which is defined as 0x4d
+	 * 0x00 <address byte> 0x00.  As far as i know, this
+	 * is only available on 256k parts.  64k word is 128k
+	 * bytes.
+	 * write the command only once.
+	 */
+	if(use_lext_address && (((addr/2) & 0xffff0000))) {
+		avrftdi_lext(to_pdata(pgm), p, m, addr/2);
 	}
+	
+	/* prepare the command stream for the whole page */
+	/* addr is in bytes, but we program in words. addr/2 should be something
+	 * like addr >> WORD_SHIFT, though */
+	for(word = addr/2; word < (len + addr)/2; word++)
+	{
+		avrftdi_print(2, "-< bytes = %d of %d\n", word * 2, len + addr);
+
+		/*setting word*/
+		avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], bufptr);
+		/* here is the second byte increment, just if you're wondering */
+		avr_set_addr(m->op[AVR_OP_LOADPAGE_LO], bufptr, word);
+		avr_set_input(m->op[AVR_OP_LOADPAGE_LO], bufptr, *buffer++);
+		bufptr += 4;
+		avr_set_bits(m->op[AVR_OP_LOADPAGE_HI], bufptr);
+		avr_set_addr(m->op[AVR_OP_LOADPAGE_HI], bufptr, word);
+		avr_set_input(m->op[AVR_OP_LOADPAGE_HI], bufptr, *buffer++);
+		bufptr += 4;
+	}
+
+	/* issue write page command, if available */
+	if (m->op[AVR_OP_WRITEPAGE] == NULL) {
+		fprintf(stderr,
+			"%s failure: Write Page (WRITEPAGE) command not defined for %s\n",
+			progname, p->desc);
+		//FIXME: maybe not exit but return error code
+		exit(1);
+	} else {
+		avr_set_bits(m->op[AVR_OP_WRITEPAGE], bufptr);
+		/* setting page address highbyte */
+		avr_set_addr(m->op[AVR_OP_WRITEPAGE],
+					 bufptr, addr/2);
+		bufptr += 4;
+	}
+
+	buf_size = bufptr - buf;
+
+	if(verbose > 3)
+		buf_dump(buf, buf_size, "command buffer", 0, 16*2);
+
+	avrftdi_print(2, "%s info: buffer size: %d\n", progname, buf_size);
+
+	avrftdi_transmit(to_pdata(pgm), MPSSE_DO_WRITE, buf, buf, buf_size);
+
+	bufptr = buf;
+	/* find a poll byte. we cannot poll a value of 0xff, so look
+	 * for a value != 0xff
+	 */
+	for(poll_index = addr+len-1; poll_index > addr-1; poll_index--)
+		if(m->buf[poll_index] != 0xff)
+			break;
+
+	if((poll_index < addr + len) && m->buf[poll_index] != 0xff)
+	{
+		avrftdi_print(2, "%s: using m->buf[%d] = 0x%02x as polling value ",
+				progname, poll_index, m->buf[poll_index]);
+		/* poll page write ready */
+		do {
+			avrftdi_print(2, ".");
+
+			pgm->read_byte(pgm, p, m, poll_index, &poll_byte);
+		} while (m->buf[poll_index] != poll_byte);
+
+		avrftdi_print(2, "\n");
+	}
+	else
+	{
+		fprintf(stderr,	"%s: no suitable byte (!=0xff) for polling found.\n", progname);
+		fprintf(stderr, "%s: trying to sleep, but programming errors may occur.\n", progname);
+		fprintf(stderr, "%s: be sure to verify programmed memory (no -V option)\n", progname);
+		/* TODO sync write */
+		/* sleep */
+		usleep((m->max_write_delay));
+	}
+	
 	return len;
 }
 
+/*
+ *Reading from flash
+ */
 static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 		unsigned int page_size, unsigned int addr, unsigned int len)
 {
-	/*
-	 *Reading from flash
-	 */
+	OPCODE * readop;
+	int byte, word;
 	int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
-	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];
 	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;
+
+	unsigned char o_buf[4*len+4];
+	unsigned char i_buf[4*len+4];
+	unsigned int index;
 
 	memset(o_buf, 0, sizeof(o_buf));
 	memset(i_buf, 0, sizeof(i_buf));
-	memset(buffer, 0, sizeof(buffer));
 
 	/* pre-check opcodes */
 	if (m->op[AVR_OP_READ_LO] == NULL) {
@@ -957,55 +1157,56 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
 			progname, "AVR_OP_READ_HI", p->desc);
 		return -1;
 	}
-
-	while (bytes) {
-		if (bytes > psize) {
-			blocksize = psize/2;
-			bytes -= psize;
-		} else {
-			blocksize = bytes/2;
-			bytes = 0;
-		}
-
-		if(use_lext_address && ((address & 0xffff0000) != (address_prev_block & 0xffff0000))) {
-			avrftdi_lext(to_pdata(pgm), p, m, address);
-		}
-		address_prev_block = address;
-
-		for(i = 0; i < blocksize; i++) {
-			if(verbose > 3)
-				fprintf(stderr,
-					"bufsize: %d, i: %d, add: %d\n",
-					buf_size, i, address);
-			avr_set_bits(m->op[AVR_OP_READ_LO], o_ptr);
-			avr_set_addr(m->op[AVR_OP_READ_LO], o_ptr, address);
-			o_ptr += 4;
-			avr_set_bits(m->op[AVR_OP_READ_HI], o_ptr);
-			avr_set_addr(m->op[AVR_OP_READ_HI], o_ptr, address);
-			o_ptr += 4;
-
-			address++;
-
-			//FIXME: why not program on per-page basis?
-			//maybe this covered a timing error in an earlier version?
-			buf_size = o_ptr - o_buf;
-
-			if((buf_size >= (page_size - 8)) || ( i == blocksize-1)) {
-				avrftdi_transmit(to_pdata(pgm), TRX, o_buf, i_buf, buf_size);
-
-				for(buf_index = 0; buf_index < buf_size; buf_index+=8) {
-					avr_get_output(m->op[AVR_OP_READ_LO], i_buf+buf_index, bufptr++);
-					avr_get_output(m->op[AVR_OP_READ_HI], i_buf+buf_index+4, bufptr++);
-				}
-
-				if(verbose > 3) {
-					buf_dump(i_buf, buf_size, "i_buf", 0, 16);
-				}
-				o_ptr = o_buf;
-			}
-		}
+	
+	if(use_lext_address && ((address & 0xffff0000))) {
+		avrftdi_lext(to_pdata(pgm), p, m, address);
 	}
-	memcpy(m->buf + addr, buffer, len);
+	
+	/* word addressing! */
+	for(word = addr/2, index = 0; word < (addr + len)/2; word++)
+	{
+		/* one byte is transferred via a 4-byte opcode.
+		 * TODO: reduce magic numbers
+		 */
+		avr_set_bits(m->op[AVR_OP_READ_LO], &o_buf[index*4]);
+		avr_set_addr(m->op[AVR_OP_READ_LO], &o_buf[index*4], word);
+		index++;
+		avr_set_bits(m->op[AVR_OP_READ_HI], &o_buf[index*4]);
+		avr_set_addr(m->op[AVR_OP_READ_HI], &o_buf[index*4], word);
+		index++;
+	}
+
+	/* transmit,
+	 * if there was an error, we did not see, memory validation will
+	 * subsequently fail.
+	 */
+	if(verbose > 2) {
+		buf_dump(o_buf, sizeof(o_buf), "o_buf", 0, 32);
+	}
+
+	avrftdi_transmit(to_pdata(pgm), MPSSE_DO_READ | MPSSE_DO_WRITE, o_buf, i_buf, len * 4);
+				
+	if(verbose > 2) {
+		buf_dump(i_buf, sizeof(i_buf), "i_buf", 0, 32);
+	}
+
+	memset(&m->buf[addr], 0, page_size);
+
+	/* every (read) op is 4 bytes in size and yields one byte of memory data */
+	for(byte = 0; byte < page_size; byte++) {
+		if(byte & 1)
+			readop = m->op[AVR_OP_READ_HI];
+		else
+			readop = m->op[AVR_OP_READ_LO];
+		
+		/* take 4 bytes and put the memory byte in the buffer at
+		 * offset addr + offset of the current byte
+		 */
+		avr_get_output(readop, &i_buf[byte*4], &m->buf[addr+byte]);
+	}
+	
+	if(verbose > 2)
+		buf_dump(&m->buf[addr], page_size, "page:", 0, 32);
 
 	return len;
 }
@@ -1052,10 +1253,7 @@ avrftdi_setup(PROGRAMMER * pgm)
 
 	pdata->pin_value = 0;
 	pdata->pin_direction = 0;
-	pdata->pin_inversion = 0;
 	pdata->led_mask = 0;
-	pdata->type = 0;
-	pdata->ftype = 0;
 }
 
 static void
@@ -1063,8 +1261,6 @@ avrftdi_teardown(PROGRAMMER * pgm)
 {
 	avrftdi_t* pdata = to_pdata(pgm);
 
-	/* reset state recommended by FTDI */
-	ftdi_set_bitmode(pdata->ftdic, 0, BITMODE_MPSSE);
 #ifndef DRYRUN
 	ftdi_deinit(pdata->ftdic);
 	ftdi_free(pdata->ftdic);