aboutsummaryrefslogtreecommitdiffstats
path: root/buspirate_spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'buspirate_spi.c')
-rw-r--r--buspirate_spi.c450
1 files changed, 258 insertions, 192 deletions
diff --git a/buspirate_spi.c b/buspirate_spi.c
index 826bd841..72c28b0a 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <strings.h>
#include <string.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
@@ -50,26 +51,28 @@ static int buspirate_serialport_setup(char *dev)
#define sp_flush_incoming(...) 0
#endif
-static unsigned char *bp_commbuf = NULL;
-static int bp_commbufsize = 0;
+struct bp_spi_data {
+ unsigned char *commbuf;
+ int commbufsize;
+};
-static int buspirate_commbuf_grow(int bufsize)
+static int buspirate_commbuf_grow(int bufsize, unsigned char **bp_commbuf, int *bp_commbufsize)
{
unsigned char *tmpbuf;
/* Never shrink. realloc() calls are expensive. */
- if (bufsize <= bp_commbufsize)
+ if (bufsize <= *bp_commbufsize)
return 0;
- tmpbuf = realloc(bp_commbuf, bufsize);
+ tmpbuf = realloc(*bp_commbuf, bufsize);
if (!tmpbuf) {
/* Keep the existing buffer because memory is already tight. */
msg_perr("Out of memory!\n");
return ERROR_OOM;
}
- bp_commbuf = tmpbuf;
- bp_commbufsize = bufsize;
+ *bp_commbuf = tmpbuf;
+ *bp_commbufsize = bufsize;
return 0;
}
@@ -128,20 +131,56 @@ static int buspirate_wait_for_string(unsigned char *buf, const char *key)
return ret;
}
-static int buspirate_spi_send_command_v1(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr);
-static int buspirate_spi_send_command_v2(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr);
+static int buspirate_spi_shutdown(void *data)
+{
+ struct bp_spi_data *bp_data = data;
+ unsigned char *const bp_commbuf = bp_data->commbuf;
+ int ret = 0, ret2 = 0;
+ /* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */
+
+ /* Exit raw SPI mode (enter raw bitbang mode) */
+ bp_commbuf[0] = 0x00;
+ if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
+ goto out_shutdown;
+ if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
+ goto out_shutdown;
+ if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
+ goto out_shutdown;
+ msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
+ if (bp_commbuf[0] != '1') {
+ msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
+ ret = 1;
+ goto out_shutdown;
+ }
+ /* Reset Bus Pirate (return to user terminal) */
+ bp_commbuf[0] = 0x0f;
+ ret = buspirate_sendrecv(bp_commbuf, 1, 0);
+
+out_shutdown:
+ /* Shut down serial port communication */
+ ret2 = serialport_shutdown(NULL);
+ /* Keep the oldest error, it is probably the best indicator. */
+ if (ret2 && !ret)
+ ret = ret2;
+
+ free(bp_commbuf);
+ if (ret)
+ msg_pdbg("Bus Pirate shutdown failed.\n");
+ else
+ msg_pdbg("Bus Pirate shutdown completed.\n");
+
+ free(data);
+ return ret;
+}
static struct spi_master spi_master_buspirate = {
.features = SPI_MASTER_4BA,
.max_data_read = MAX_DATA_UNSPECIFIED,
.max_data_write = MAX_DATA_UNSPECIFIED,
.command = NULL,
- .multicommand = default_spi_send_multicommand,
.read = default_spi_read,
.write_256 = default_spi_write_256,
- .write_aai = default_spi_write_aai,
+ .shutdown = buspirate_spi_shutdown,
};
static const struct buspirate_speeds spispeeds[] = {
@@ -165,42 +204,101 @@ static const struct buspirate_speeds serialspeeds[] = {
{NULL, 0}
};
-static int buspirate_spi_shutdown(void *data)
+static int buspirate_spi_send_command_v1(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
{
- int ret = 0, ret2 = 0;
- /* No need to allocate a buffer here, we know that bp_commbuf is at least DEFAULT_BUFSIZE big. */
+ unsigned int i = 0;
+ int ret = 0;
+ struct bp_spi_data *bp_data = flash->mst->spi.data;
- /* Exit raw SPI mode (enter raw bitbang mode) */
- bp_commbuf[0] = 0x00;
- if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
- goto out_shutdown;
- if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
- goto out_shutdown;
- if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
- goto out_shutdown;
- msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
- if (bp_commbuf[0] != '1') {
- msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
- ret = 1;
- goto out_shutdown;
+ if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
+ return SPI_INVALID_LENGTH;
+
+ /* 3 bytes extra for CS#, len, CS#. */
+ if (buspirate_commbuf_grow(writecnt + readcnt + 3, &bp_data->commbuf, &bp_data->commbufsize))
+ return ERROR_OOM;
+
+ unsigned char *const bp_commbuf = bp_data->commbuf;
+
+ /* Assert CS# */
+ bp_commbuf[i++] = 0x02;
+
+ bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1);
+ memcpy(bp_commbuf + i, writearr, writecnt);
+ i += writecnt;
+ memset(bp_commbuf + i, 0, readcnt);
+
+ i += readcnt;
+ /* De-assert CS# */
+ bp_commbuf[i++] = 0x03;
+
+ ret = buspirate_sendrecv(bp_commbuf, i, i);
+
+ if (ret) {
+ msg_perr("Bus Pirate communication error!\n");
+ return SPI_GENERIC_ERROR;
}
- /* Reset Bus Pirate (return to user terminal) */
- bp_commbuf[0] = 0x0f;
- ret = buspirate_sendrecv(bp_commbuf, 1, 0);
-out_shutdown:
- /* Shut down serial port communication */
- ret2 = serialport_shutdown(NULL);
- /* Keep the oldest error, it is probably the best indicator. */
- if (ret2 && !ret)
- ret = ret2;
- bp_commbufsize = 0;
- free(bp_commbuf);
- bp_commbuf = NULL;
- if (ret)
- msg_pdbg("Bus Pirate shutdown failed.\n");
- else
- msg_pdbg("Bus Pirate shutdown completed.\n");
+ if (bp_commbuf[0] != 0x01) {
+ msg_perr("Protocol error while lowering CS#!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ if (bp_commbuf[1] != 0x01) {
+ msg_perr("Protocol error while reading/writing SPI!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ if (bp_commbuf[i - 1] != 0x01) {
+ msg_perr("Protocol error while raising CS#!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ /* Skip CS#, length, writearr. */
+ memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
+
+ return ret;
+}
+
+static int buspirate_spi_send_command_v2(const struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, unsigned char *readarr)
+{
+ int i = 0, ret = 0;
+ struct bp_spi_data *bp_data = flash->mst->spi.data;
+
+ 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.
+ */
+ if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1), &bp_data->commbuf, &bp_data->commbufsize))
+ return ERROR_OOM;
+
+ unsigned char *const bp_commbuf = bp_data->commbuf;
+
+ /* Combined SPI write/read. */
+ bp_commbuf[i++] = 0x04;
+ bp_commbuf[i++] = (writecnt >> 8) & 0xff;
+ bp_commbuf[i++] = writecnt & 0xff;
+ bp_commbuf[i++] = (readcnt >> 8) & 0xff;
+ bp_commbuf[i++] = readcnt & 0xff;
+ memcpy(bp_commbuf + i, writearr, writecnt);
+
+ ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt);
+
+ if (ret) {
+ msg_perr("Bus Pirate communication error!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ if (bp_commbuf[0] != 0x01) {
+ msg_perr("Protocol error while sending SPI write/read!\n");
+ return SPI_GENERIC_ERROR;
+ }
+
+ /* Skip Ack. */
+ memcpy(readarr, bp_commbuf + 1, readcnt);
return ret;
}
@@ -214,7 +312,7 @@ out_shutdown:
*/
#define BP_DIVISOR(baud) ((4000000/(baud)) - 1)
-int buspirate_spi_init(void)
+static int buspirate_spi_init(const struct programmer_cfg *cfg)
{
char *tmp;
char *dev;
@@ -227,9 +325,13 @@ int buspirate_spi_init(void)
int spispeed = 0x7;
int serialspeed_index = -1;
int ret = 0;
- int pullup = 0;
+ bool pullup = false;
+ bool psu = false;
+ bool aux = true;
+ unsigned char *bp_commbuf;
+ int bp_commbufsize;
- dev = extract_programmer_param("dev");
+ dev = extract_programmer_param_str(cfg, "dev");
if (dev && !strlen(dev)) {
free(dev);
dev = NULL;
@@ -239,7 +341,7 @@ int buspirate_spi_init(void)
return 1;
}
- tmp = extract_programmer_param("spispeed");
+ tmp = extract_programmer_param_str(cfg, "spispeed");
if (tmp) {
for (i = 0; spispeeds[i].name; i++) {
if (!strncasecmp(spispeeds[i].name, tmp, strlen(spispeeds[i].name))) {
@@ -253,7 +355,7 @@ int buspirate_spi_init(void)
free(tmp);
/* Extract serialspeed parameter */
- tmp = extract_programmer_param("serialspeed");
+ tmp = extract_programmer_param_str(cfg, "serialspeed");
if (tmp) {
for (i = 0; serialspeeds[i].name; i++) {
if (!strncasecmp(serialspeeds[i].name, tmp, strlen(serialspeeds[i].name))) {
@@ -266,10 +368,10 @@ int buspirate_spi_init(void)
}
free(tmp);
- tmp = extract_programmer_param("pullups");
+ tmp = extract_programmer_param_str(cfg, "pullups");
if (tmp) {
if (strcasecmp("on", tmp) == 0)
- pullup = 1;
+ pullup = true;
else if (strcasecmp("off", tmp) == 0)
; // ignore
else
@@ -277,11 +379,32 @@ int buspirate_spi_init(void)
}
free(tmp);
+ tmp = extract_programmer_param_str(cfg, "psus");
+ if (tmp) {
+ if (strcasecmp("on", tmp) == 0)
+ psu = true;
+ else if (strcasecmp("off", tmp) == 0)
+ ; // ignore
+ else
+ msg_perr("Invalid psus state, not enabling.\n");
+ }
+ free(tmp);
+
+ tmp = extract_programmer_param_str(cfg, "aux");
+ if (tmp) {
+ if (strcasecmp("high", tmp) == 0)
+ ; /* Default */
+ else if (strcasecmp("low", tmp) == 0)
+ aux = false;
+ else
+ msg_perr("Invalid AUX state, driving high by default.\n");
+ }
+ free(tmp);
+
/* Default buffer size is 19: 16 bytes data, 3 bytes control. */
#define DEFAULT_BUFSIZE (16 + 3)
bp_commbuf = malloc(DEFAULT_BUFSIZE);
if (!bp_commbuf) {
- bp_commbufsize = 0;
msg_perr("Out of memory!\n");
free(dev);
return ERROR_OOM;
@@ -291,18 +414,19 @@ int buspirate_spi_init(void)
ret = buspirate_serialport_setup(dev);
free(dev);
if (ret) {
- bp_commbufsize = 0;
free(bp_commbuf);
- bp_commbuf = NULL;
return ret;
}
- if (register_shutdown(buspirate_spi_shutdown, NULL) != 0) {
- bp_commbufsize = 0;
+
+ struct bp_spi_data *bp_data = calloc(1, sizeof(*bp_data));
+ if (!bp_data) {
+ msg_perr("Unable to allocate space for SPI master data\n");
free(bp_commbuf);
- bp_commbuf = NULL;
return 1;
}
+ bp_data->commbuf = bp_commbuf;
+ bp_data->commbufsize = bp_commbufsize;
/* This is the brute force version, but it should work.
* It is likely to fail if a previous flashrom run was aborted during a write with the new SPI commands
@@ -315,7 +439,7 @@ int buspirate_spi_init(void)
/* Send the command, don't read the response. */
ret = buspirate_sendrecv(bp_commbuf, 1, 0);
if (ret)
- return ret;
+ goto init_err_cleanup_exit;
/* The old way to handle responses from a Bus Pirate already in BBIO mode was to flush any
* response which came in over serial. Unfortunately that does not work reliably on Linux
* with FTDI USB-serial.
@@ -328,19 +452,19 @@ int buspirate_spi_init(void)
}
/* We know that 20 commands of \0 should elicit at least one BBIO1 response. */
if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
- return ret;
+ goto init_err_cleanup_exit;
/* Reset the Bus Pirate. */
bp_commbuf[0] = 0x0f;
/* Send the command, don't read the response. */
if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
- return ret;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_wait_for_string(bp_commbuf, "irate ")))
- return ret;
+ goto init_err_cleanup_exit;
/* Read the hardware version string. Last byte of the buffer is reserved for \0. */
for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) {
if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1)))
- return ret;
+ goto init_err_cleanup_exit;
if (strchr("\r\n\t ", bp_commbuf[i]))
break;
}
@@ -361,11 +485,11 @@ int buspirate_spi_init(void)
msg_pdbg("\n");
if ((ret = buspirate_wait_for_string(bp_commbuf, "irmware ")))
- return ret;
+ goto init_err_cleanup_exit;
/* Read the firmware version string. Last byte of the buffer is reserved for \0. */
for (i = 0; i < DEFAULT_BUFSIZE - 1; i++) {
if ((ret = buspirate_sendrecv(bp_commbuf + i, 0, 1)))
- return ret;
+ goto init_err_cleanup_exit;
if (strchr("\r\n\t ", bp_commbuf[i]))
break;
}
@@ -386,21 +510,26 @@ int buspirate_spi_init(void)
msg_pdbg("\n");
if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>")))
- return ret;
+ goto init_err_cleanup_exit;
/* Tell the user about missing SPI binary mode in firmware 2.3 and older. */
if (BP_FWVERSION(fw_version_major, fw_version_minor) < BP_FWVERSION(2, 4)) {
msg_pinfo("Bus Pirate firmware 2.3 and older does not support binary SPI access.\n");
msg_pinfo("Please upgrade to the latest firmware (at least 2.4).\n");
- return SPI_PROGRAMMER_ERROR;
+ ret = SPI_PROGRAMMER_ERROR;
+ goto init_err_cleanup_exit;
}
/* Use fast SPI mode in firmware 5.5 and newer. */
if (BP_FWVERSION(fw_version_major, fw_version_minor) >= BP_FWVERSION(5, 5)) {
msg_pdbg("Using SPI command set v2.\n");
/* Sensible default buffer size. */
- if (buspirate_commbuf_grow(260 + 5))
- return ERROR_OOM;
+ if (buspirate_commbuf_grow(260 + 5, &bp_commbuf, &bp_commbufsize)) {
+ ret = ERROR_OOM;
+ goto init_err_cleanup_exit;
+ }
+ bp_data->commbuf = bp_commbuf;
+ bp_data->commbufsize = bp_commbufsize;
spi_master_buspirate.max_data_read = 2048;
spi_master_buspirate.max_data_write = 256;
spi_master_buspirate.command = buspirate_spi_send_command_v2;
@@ -409,8 +538,12 @@ int buspirate_spi_init(void)
msg_pinfo("Reading/writing a flash chip may take hours.\n");
msg_pinfo("It is recommended to upgrade to firmware 5.5 or newer.\n");
/* Sensible default buffer size. */
- if (buspirate_commbuf_grow(16 + 3))
- return ERROR_OOM;
+ if (buspirate_commbuf_grow(16 + 3, &bp_commbuf, &bp_commbufsize)) {
+ ret = ERROR_OOM;
+ goto init_err_cleanup_exit;
+ }
+ bp_data->commbuf = bp_commbuf;
+ bp_data->commbufsize = bp_commbufsize;
spi_master_buspirate.max_data_read = 12;
spi_master_buspirate.max_data_write = 12;
spi_master_buspirate.command = buspirate_spi_send_command_v1;
@@ -450,37 +583,37 @@ int buspirate_spi_init(void)
/* Enter baud rate configuration mode */
cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "b\n");
if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0)))
- return ret;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_wait_for_string(bp_commbuf, ">")))
- return ret;
+ goto init_err_cleanup_exit;
/* Enter manual clock divisor entry mode */
cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "10\n");
if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0)))
- return ret;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_wait_for_string(bp_commbuf, ">")))
- return ret;
+ goto init_err_cleanup_exit;
/* Set the clock divisor to the value calculated from the user's input */
cnt = snprintf((char *)bp_commbuf, DEFAULT_BUFSIZE, "%d\n",
BP_DIVISOR(serialspeeds[serialspeed_index].speed));
if ((ret = buspirate_sendrecv(bp_commbuf, cnt, 0)))
- return ret;
+ goto init_err_cleanup_exit;
sleep(1);
/* Reconfigure the host's serial baud rate to the new value */
if ((ret = serialport_config(sp_fd, serialspeeds[serialspeed_index].speed))) {
msg_perr("Unable to configure system baud rate to specified value.");
- return ret;
+ goto init_err_cleanup_exit;
}
/* Return to the main prompt */
bp_commbuf[0] = ' ';
if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
- return ret;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_wait_for_string(bp_commbuf, "HiZ>")))
- return ret;
+ goto init_err_cleanup_exit;
msg_pdbg("Serial speed is %d baud\n", serialspeeds[serialspeed_index].speed);
}
@@ -493,174 +626,107 @@ int buspirate_spi_init(void)
for (i = 0; i < 20; i++) {
bp_commbuf[0] = 0x00;
if ((ret = buspirate_sendrecv(bp_commbuf, 1, 0)))
- return ret;
+ goto init_err_cleanup_exit;
}
if ((ret = buspirate_wait_for_string(bp_commbuf, "BBIO")))
- return ret;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
- return ret;
+ goto init_err_cleanup_exit;
msg_pdbg("Raw bitbang mode version %c\n", bp_commbuf[0]);
if (bp_commbuf[0] != '1') {
msg_perr("Can't handle raw bitbang mode version %c!\n", bp_commbuf[0]);
- return 1;
+ ret = 1;
+ goto init_err_cleanup_exit;
}
/* Enter raw SPI mode */
bp_commbuf[0] = 0x01;
ret = buspirate_sendrecv(bp_commbuf, 1, 0);
if (ret)
- return 1;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_wait_for_string(bp_commbuf, "SPI")))
- return ret;
+ goto init_err_cleanup_exit;
if ((ret = buspirate_sendrecv(bp_commbuf, 0, 1)))
- return ret;
+ goto init_err_cleanup_exit;
msg_pdbg("Raw SPI mode version %c\n", bp_commbuf[0]);
if (bp_commbuf[0] != '1') {
msg_perr("Can't handle raw SPI mode version %c!\n", bp_commbuf[0]);
- return 1;
+ ret = 1;
+ goto init_err_cleanup_exit;
}
- /* Initial setup (SPI peripherals config): Enable power, CS high, AUX */
- bp_commbuf[0] = 0x40 | 0x0b;
- if (pullup == 1) {
+ /* Initial setup (SPI peripherals config): Enable power, CS high */
+ bp_commbuf[0] = 0x40 | 0x09;
+ if (pullup) {
bp_commbuf[0] |= (1 << 2);
msg_pdbg("Enabling pull-up resistors.\n");
}
+ if (psu) {
+ bp_commbuf[0] |= (1 << 3);
+ msg_pdbg("Enabling PSUs.\n");
+ }
+ if (aux) {
+ bp_commbuf[0] |= (1 << 1);
+ msg_pdbg("Driving AUX high.\n");
+ } else {
+ msg_pdbg("Driving AUX low.\n");
+ }
ret = buspirate_sendrecv(bp_commbuf, 1, 1);
if (ret)
- return 1;
+ goto init_err_cleanup_exit;
if (bp_commbuf[0] != 0x01) {
msg_perr("Protocol error while setting power/CS/AUX(/Pull-up resistors)!\n");
- return 1;
+ ret = 1;
+ goto init_err_cleanup_exit;
}
/* Set SPI speed */
bp_commbuf[0] = 0x60 | spispeed;
ret = buspirate_sendrecv(bp_commbuf, 1, 1);
if (ret)
- return 1;
+ goto init_err_cleanup_exit;
if (bp_commbuf[0] != 0x01) {
msg_perr("Protocol error while setting SPI speed!\n");
- return 1;
+ ret = 1;
+ goto init_err_cleanup_exit;
}
/* Set SPI config: output type, idle, clock edge, sample */
bp_commbuf[0] = 0x80 | 0xa;
- if (pullup == 1) {
+ if (pullup) {
bp_commbuf[0] &= ~(1 << 3);
msg_pdbg("Pull-ups enabled, so using HiZ pin output! (Open-Drain mode)\n");
}
ret = buspirate_sendrecv(bp_commbuf, 1, 1);
if (ret)
- return 1;
+ goto init_err_cleanup_exit;
if (bp_commbuf[0] != 0x01) {
msg_perr("Protocol error while setting SPI config!\n");
- return 1;
+ ret = 1;
+ goto init_err_cleanup_exit;
}
/* De-assert CS# */
bp_commbuf[0] = 0x03;
ret = buspirate_sendrecv(bp_commbuf, 1, 1);
if (ret)
- return 1;
+ goto init_err_cleanup_exit;
if (bp_commbuf[0] != 0x01) {
msg_perr("Protocol error while raising CS#!\n");
- return 1;
- }
-
- register_spi_master(&spi_master_buspirate);
-
- return 0;
-}
-
-static int buspirate_spi_send_command_v1(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- unsigned int i = 0;
- int ret = 0;
-
- if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
- return SPI_INVALID_LENGTH;
-
- /* 3 bytes extra for CS#, len, CS#. */
- if (buspirate_commbuf_grow(writecnt + readcnt + 3))
- return ERROR_OOM;
-
- /* Assert CS# */
- bp_commbuf[i++] = 0x02;
-
- bp_commbuf[i++] = 0x10 | (writecnt + readcnt - 1);
- memcpy(bp_commbuf + i, writearr, writecnt);
- i += writecnt;
- memset(bp_commbuf + i, 0, readcnt);
-
- i += readcnt;
- /* De-assert CS# */
- bp_commbuf[i++] = 0x03;
-
- ret = buspirate_sendrecv(bp_commbuf, i, i);
-
- if (ret) {
- msg_perr("Bus Pirate communication error!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (bp_commbuf[0] != 0x01) {
- msg_perr("Protocol error while lowering CS#!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (bp_commbuf[1] != 0x01) {
- msg_perr("Protocol error while reading/writing SPI!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (bp_commbuf[i - 1] != 0x01) {
- msg_perr("Protocol error while raising CS#!\n");
- return SPI_GENERIC_ERROR;
+ ret = 1;
+ goto init_err_cleanup_exit;
}
- /* Skip CS#, length, writearr. */
- memcpy(readarr, bp_commbuf + 2 + writecnt, readcnt);
+ return register_spi_master(&spi_master_buspirate, bp_data);
+init_err_cleanup_exit:
+ buspirate_spi_shutdown(bp_data);
return ret;
}
-static int buspirate_spi_send_command_v2(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
- const unsigned char *writearr, unsigned char *readarr)
-{
- 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.
- */
- if (buspirate_commbuf_grow(max(writecnt + 5, readcnt + 1)))
- return ERROR_OOM;
-
- /* Combined SPI write/read. */
- bp_commbuf[i++] = 0x04;
- bp_commbuf[i++] = (writecnt >> 8) & 0xff;
- bp_commbuf[i++] = writecnt & 0xff;
- bp_commbuf[i++] = (readcnt >> 8) & 0xff;
- bp_commbuf[i++] = readcnt & 0xff;
- memcpy(bp_commbuf + i, writearr, writecnt);
-
- ret = buspirate_sendrecv(bp_commbuf, i + writecnt, 1 + readcnt);
-
- if (ret) {
- msg_perr("Bus Pirate communication error!\n");
- return SPI_GENERIC_ERROR;
- }
-
- if (bp_commbuf[0] != 0x01) {
- msg_perr("Protocol error while sending SPI write/read!\n");
- return SPI_GENERIC_ERROR;
- }
-
- /* Skip Ack. */
- memcpy(readarr, bp_commbuf + 1, readcnt);
-
- return ret;
-}
+const struct programmer_entry programmer_buspirate_spi = {
+ .name = "buspirate_spi",
+ .type = OTHER,
+ /* FIXME */
+ .devs.note = "Dangerous Prototypes Bus Pirate\n",
+ .init = buspirate_spi_init,
+};