diff options
Diffstat (limited to 'buspirate_spi.c')
-rw-r--r-- | buspirate_spi.c | 450 |
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, +}; |