Index: flashrom-buspirate_newcommands/buspirate_spi.c
===================================================================
--- flashrom-buspirate_newcommands/buspirate_spi.c	(Revision 1130)
+++ flashrom-buspirate_newcommands/buspirate_spi.c	(Arbeitskopie)
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <unistd.h>
 #include "flash.h"
 #include "chipdrivers.h"
 #include "programmer.h"
@@ -45,6 +46,8 @@
 #define sp_flush_incoming(...) 0
 #endif
 
+static int buspirate_interface_version;
+
 static int buspirate_sendrecv(unsigned char *buf, unsigned int writecnt, unsigned int readcnt)
 {
 	int i, ret = 0;
@@ -130,7 +133,13 @@
 		return ret;
 	free(dev);
 
-	/* This is the brute force version, but it should work. */
+	/* This is the brute force version, but it should work.
+	 * It is guaranteed to fail if a previous flashrom run was aborted
+	 * during a write with the new SPI commands in firmware v4.6 because
+	 * that firmware may wait for up to 4096 bytes of input before
+	 * responding to 0x00 again. The obvious workaround may cause startup
+	 * penalties of more than one second.
+	 */
 	for (i = 0; i < 19; i++) {
 		/* Enter raw bitbang mode */
 		buf[0] = 0x00;
@@ -141,6 +150,20 @@
 		/* Read any response and discard it. */
 		sp_flush_incoming();
 	}
+	/* USB is slow. The Bus Pirate is even slower. Apparently the flush
+	 * action above is too fast or too early. Some stuff still remains in
+	 * the pipe after the flush above, and one additional flush is not
+	 * sufficient either. Use a 1.5 ms delay inside the loop to make
+	 * mostly sure that at least one USB frame had time to arrive.
+	 * Looping only 5 times is not sufficient and causes the
+	 * ocassional failure.
+	 * Folding the delay into the loop above is not reliable either.
+	 */
+	for (i = 0; i < 10; i++) {
+		usleep(1500);
+		/* Read any response and discard it. */
+		sp_flush_incoming();
+	}
 	/* Enter raw bitbang mode */
 	buf[0] = 0x00;
 	ret = buspirate_sendrecv(buf, 1, 5);
@@ -148,6 +171,8 @@
 		return ret;
 	if (memcmp(buf, "BBIO", 4)) {
 		msg_perr("Entering raw bitbang mode failed!\n");
+		msg_pdbg("Got %02x%02x%02x%02x%02x\n",
+			 buf[0], buf[1], buf[2], buf[3], buf[4]);
 		return 1;
 	}
 	msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
@@ -159,8 +184,12 @@
 	/* Enter raw SPI mode */
 	buf[0] = 0x01;
 	ret = buspirate_sendrecv(buf, 1, 4);
+	if (ret)
+		return ret;
 	if (memcmp(buf, "SPI", 3)) {
 		msg_perr("Entering raw SPI mode failed!\n");
+		msg_pdbg("Got %02x%02x%02x%02x\n",
+			 buf[0], buf[1], buf[2], buf[3]);
 		return 1;
 	}
 	msg_pdbg("Raw SPI mode version %c\n", buf[3]);
@@ -210,6 +239,34 @@
 		return 1;
 	}
 
+	/* Test combined SPI write/read, length 0. */
+	buf[0] = 0x04;
+	buf[1] = 0;
+	buf[2] = 0;
+	buf[3] = 0;
+	buf[4] = 0;
+	ret = buspirate_sendrecv(buf, 5, 1);
+	if (ret)
+		return 1;
+	if (buf[0] != 0x01) {
+		msg_pdbg("SPI command set v2 not available, using old commands "
+			 "present in firmware vX.Y or later\n");
+
+		/* FIXME: Check the error code? */
+		/* We sent 4 bytes of 0x00, so we expect 4 BBIO1 responses. */
+		buspirate_sendrecv(buf, 0, 4 * 5);
+
+		/* Enter raw SPI mode again. */
+		buf[0] = 0x01;
+		/* FIXME: Check the error code? */
+		buspirate_sendrecv(buf, 1, 4);
+
+		buspirate_interface_version = 1;
+	} else {
+		msg_pdbg("Using SPI command set v2.\n"); 
+		buspirate_interface_version = 2;
+	}
+
 	buses_supported = CHIP_BUSTYPE_SPI;
 	spi_controller = SPI_CONTROLLER_BUSPIRATE;
 
@@ -251,12 +308,56 @@
 	return 0;
 }
 
-int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+int buspirate_spi_send_command_v2(unsigned int writecnt, unsigned int readcnt,
 		const unsigned char *writearr, unsigned char *readarr)
 {
 	static unsigned char *buf = NULL;
 	int i = 0, ret = 0;
 
+	if (writecnt > 4096 || readcnt > 4096 || (readcnt + writecnt) > 4096)
+		return SPI_INVALID_LENGTH;
+
+	/* 5 bytes extra for command, writelen, readlen.
+	 * 1 byte extra for Ack/Nack.
+	 */
+	buf = realloc(buf, max(writecnt + 5, readcnt + 1));
+	if (!buf) {
+		msg_perr("Out of memory!\n");
+		exit(1); // -1
+	}
+
+	/* Combined SPI write/read. */
+	buf[i++] = 0x04;
+	buf[i++] = (writecnt >> 8) & 0xff;
+	buf[i++] = writecnt & 0xff;
+	buf[i++] = (readcnt >> 8) & 0xff;
+	buf[i++] = readcnt & 0xff;
+	memcpy(buf + i, writearr, writecnt);
+	
+	ret = buspirate_sendrecv(buf, i + writecnt, 1 + readcnt);
+
+	if (ret) {
+		msg_perr("Bus Pirate communication error!\n");
+		return SPI_GENERIC_ERROR;
+	}
+
+	if (buf[0] != 0x01) {
+		msg_perr("Protocol error while sending SPI write/read!\n");
+		return SPI_GENERIC_ERROR;
+	}
+
+	/* Skip Ack. */
+	memcpy(readarr, buf + 1, readcnt);
+
+	return ret;
+}
+
+int buspirate_spi_send_command_v1(unsigned int writecnt, unsigned int readcnt,
+		const unsigned char *writearr, unsigned char *readarr)
+{
+	static unsigned char *buf = NULL;
+	int i = 0, ret = 0;
+
 	if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
 		return SPI_INVALID_LENGTH;
 
@@ -307,6 +408,17 @@
 	return ret;
 }
 
+int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
+		const unsigned char *writearr, unsigned char *readarr)
+{
+	switch (buspirate_interface_version) {
+	case 2:
+		return buspirate_spi_send_command_v2(writecnt, readcnt, writearr, readarr);
+	default:
+		return buspirate_spi_send_command_v1(writecnt, readcnt, writearr, readarr);
+	}
+}
+
 int buspirate_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
 {
 	return spi_read_chunked(flash, buf, start, len, 12);
Index: flashrom-buspirate_newcommands/serial.c
===================================================================
--- flashrom-buspirate_newcommands/serial.c	(Revision 1130)
+++ flashrom-buspirate_newcommands/serial.c	(Arbeitskopie)
@@ -200,8 +200,10 @@
 #else
 		tmp = write(sp_fd, buf, writecnt);
 #endif
-		if (tmp == -1)
+		if (tmp == -1) {
+			msg_perr("Serial port write error!\n");
 			return 1;
+		}
 		if (!tmp)
 			msg_pdbg("Empty write\n");
 		writecnt -= tmp; 
@@ -221,8 +223,10 @@
 #else
 		tmp = read(sp_fd, buf, readcnt);
 #endif
-		if (tmp == -1)
+		if (tmp == -1) {
+			msg_perr("Serial port read error!\n");
 			return 1;
+		}
 		if (!tmp)
 			msg_pdbg("Empty read\n");
 		readcnt -= tmp;

