Signed-off-by: Stefan Tauner <[email protected]>
---
 bitbang_spi.c   |    2 ++
 buspirate_spi.c |   15 ++++++++++++++-
 dediprog.c      |   24 ++++++++++++++++--------
 dummyflasher.c  |    2 ++
 ft2232_spi.c    |   15 ++++++++++++++-
 ichspi.c        |   12 ++++++++++++
 it85spi.c       |    2 ++
 it87spi.c       |   30 +++++++++++++++++++++++-------
 linux_spi.c     |   32 ++++++++++++++++++++++++--------
 programmer.h    |   10 ++++++++++
 sb600spi.c      |   52 +++++++++++++++++++++++++++++-----------------------
 serprog.c       |   33 ++++++++++++++++++++++-----------
 spi.c           |   30 ++++++++++++++++++++++++++++--
 wbsio_spi.c     |   11 +++++++++++
 14 files changed, 209 insertions(+), 61 deletions(-)

diff --git a/bitbang_spi.c b/bitbang_spi.c
index 11d2de1..5631ab0 100644
--- a/bitbang_spi.c
+++ b/bitbang_spi.c
@@ -67,6 +67,8 @@ static const struct spi_programmer spi_programmer_bitbang = {
        .type           = SPI_CONTROLLER_BITBANG,
        .max_data_read  = MAX_DATA_READ_UNLIMITED,
        .max_data_write = MAX_DATA_WRITE_UNLIMITED,
+       .check_trans    = default_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = bitbang_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = default_spi_read,
diff --git a/buspirate_spi.c b/buspirate_spi.c
index 054b4ff..deefdd4 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -129,6 +129,14 @@ static int buspirate_wait_for_string(unsigned char *buf, 
char *key)
        return ret;
 }
 
+static int buspirate_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                 const unsigned char *writearr)
+{
+       if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
+               return SPI_INVALID_LENGTH;
+       return 0;
+}
+
 static int buspirate_spi_send_command(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
                                      const unsigned char *writearr, unsigned 
char *readarr);
 
@@ -136,6 +144,8 @@ static const struct spi_programmer spi_programmer_buspirate 
= {
        .type           = SPI_CONTROLLER_BUSPIRATE,
        .max_data_read  = 12,
        .max_data_write = 12,
+       .check_trans    = buspirate_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = buspirate_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = default_spi_read,
@@ -421,8 +431,11 @@ static int buspirate_spi_send_command(struct flashctx 
*flash,
        unsigned int i = 0;
        int ret = 0;
 
-       if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
+       if (buspirate_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) 
{
+               msg_pspew("%s called with an unsupported transaction layout: 
readcnt = %d, writecnt = %d.\n",
+                         __func__, readcnt, writecnt);
                return SPI_INVALID_LENGTH;
+       }
 
        /* 3 bytes extra for CS#, len, CS#. */
        if (buspirate_commbuf_grow(writecnt + readcnt + 3))
diff --git a/dediprog.c b/dediprog.c
index a81cf83..ff30fb9 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -439,6 +439,17 @@ static int dediprog_spi_write_aai(struct flashctx *flash, 
uint8_t *buf, unsigned
        return dediprog_spi_write(flash, buf, start, len, 
DEDI_SPI_CMD_AAIWRITE);
 }
 
+static int dediprog_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                   const unsigned char *writearr, unsigned 
char *readarr)
+{
+       /* Paranoid, but I don't want to be blamed if anything explodes. */
+       if (writecnt > 16)
+               return 1;
+       /* 16 byte reads should work. */
+       if (readcnt > 16)
+               return -1;
+}
+
 static int dediprog_spi_send_command(struct flashctx *flash,
                                     unsigned int writecnt,
                                     unsigned int readcnt,
@@ -448,14 +459,9 @@ static int dediprog_spi_send_command(struct flashctx 
*flash,
        int ret;
 
        msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
-       /* Paranoid, but I don't want to be blamed if anything explodes. */
-       if (writecnt > 16) {
-               msg_perr("Untested writecnt=%i, aborting.\n", writecnt);
-               return 1;
-       }
-       /* 16 byte reads should work. */
-       if (readcnt > 16) {
-               msg_perr("Untested readcnt=%i, aborting.\n", readcnt);
+       if (dediprog_spi_check_trans(flash, writecnt, readcnt, writearr, 
readarr) != 0) {
+               msg_perr("%s called with an unsupported transaction layout: 
readcnt = %d, writecnt = %d.\n",
+                         __func__, readcnt, writecnt);
                return 1;
        }
        
@@ -740,6 +746,8 @@ static const struct spi_programmer spi_programmer_dediprog 
= {
        .type           = SPI_CONTROLLER_DEDIPROG,
        .max_data_read  = MAX_DATA_UNSPECIFIED,
        .max_data_write = MAX_DATA_UNSPECIFIED,
+       .check_trans    = dediprog_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = dediprog_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = dediprog_spi_read,
diff --git a/dummyflasher.c b/dummyflasher.c
index 655b678..edd5714 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -123,6 +123,8 @@ static const struct spi_programmer 
spi_programmer_dummyflasher = {
        .type           = SPI_CONTROLLER_DUMMY,
        .max_data_read  = MAX_DATA_READ_UNLIMITED,
        .max_data_write = MAX_DATA_UNSPECIFIED,
+       .check_trans    = default_spi_check_trans, /* FIXME */
+       .check_transs   = default_spi_check_transs,
        .command        = dummy_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = default_spi_read,
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 31a6c5c..75fd01c 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -139,6 +139,14 @@ static int get_buf(struct ftdi_context *ftdic, const 
unsigned char *buf,
        return 0;
 }
 
+static int ft2232_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                 const unsigned char *writearr)
+{
+       if (writecnt > 65536 || readcnt > 65536)
+               return SPI_INVALID_LENGTH;
+       return 0;
+}
+
 static int ft2232_spi_send_command(struct flashctx *flash,
                                   unsigned int writecnt, unsigned int readcnt,
                                   const unsigned char *writearr,
@@ -148,6 +156,8 @@ static const struct spi_programmer spi_programmer_ft2232 = {
        .type           = SPI_CONTROLLER_FT2232,
        .max_data_read  = 64 * 1024,
        .max_data_write = 256,
+       .check_trans    = ft2232_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = ft2232_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = default_spi_read,
@@ -407,8 +417,11 @@ static int ft2232_spi_send_command(struct flashctx *flash,
        int bufsize;
        static int oldbufsize = 0;
 
-       if (writecnt > 65536 || readcnt > 65536)
+       if (ft2232_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+               msg_pspew("%s called with an unsupported transaction layout: 
readcnt = %d, writecnt = %d.\n",
+                         __func__, readcnt, writecnt);
                return SPI_INVALID_LENGTH;
+       }
 
        /* buf is not used for the response from the chip. */
        bufsize = max(writecnt + 9, 260 + 9);
diff --git a/ichspi.c b/ichspi.c
index 142a122..c2e54ae 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1077,6 +1077,12 @@ static int prepare_opcode(struct flashctx *flash, 
unsigned int writecnt, unsigne
        return 0;
 }
 
+static int ich_spi_check_trans(struct flashctx *flash, unsigned int writecnt, 
unsigned int readcnt,
+                              const unsigned char *writearr)
+{
+       return prepare_opcode(flash, writecnt, readcnt, writearr, (1 << 
ICH_DRYRUN), NULL);
+}
+
 static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
                                unsigned int readcnt,
                                const unsigned char *writearr,
@@ -1553,6 +1559,8 @@ static const struct spi_programmer spi_programmer_ich7 = {
        .type = SPI_CONTROLLER_ICH7,
        .max_data_read = 64,
        .max_data_write = 64,
+       .check_trans    = default_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command = ich_spi_send_command,
        .multicommand = ich_spi_send_multicommand,
        .read = default_spi_read,
@@ -1564,6 +1572,8 @@ static const struct spi_programmer spi_programmer_ich9 = {
        .type = SPI_CONTROLLER_ICH9,
        .max_data_read = 64,
        .max_data_write = 64,
+       .check_trans    = ich_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command = ich_spi_send_command,
        .multicommand = ich_spi_send_multicommand,
        .read = default_spi_read,
@@ -1873,6 +1883,8 @@ static const struct spi_programmer spi_programmer_via = {
        .type = SPI_CONTROLLER_VIA,
        .max_data_read = 16,
        .max_data_write = 16,
+       .check_trans    = default_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command = ich_spi_send_command,
        .multicommand = ich_spi_send_multicommand,
        .read = default_spi_read,
diff --git a/it85spi.c b/it85spi.c
index 0b074eb..555a600 100644
--- a/it85spi.c
+++ b/it85spi.c
@@ -280,6 +280,8 @@ static const struct spi_programmer spi_programmer_it85xx = {
        .type           = SPI_CONTROLLER_IT85XX,
        .max_data_read  = 64,
        .max_data_write = 64,
+       .check_trans    = default_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = it85xx_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = default_spi_read,
diff --git a/it87spi.c b/it87spi.c
index a35ddc0..68a21c3 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -104,6 +104,8 @@ void probe_superio_ite(void)
        return;
 }
 
+static int it8716f_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                  const unsigned char *writearr);
 static int it8716f_spi_send_command(struct flashctx *flash,
                                    unsigned int writecnt, unsigned int readcnt,
                                    const unsigned char *writearr,
@@ -117,6 +119,8 @@ static const struct spi_programmer spi_programmer_it87xx = {
        .type           = SPI_CONTROLLER_IT87XX,
        .max_data_read  = MAX_DATA_UNSPECIFIED,
        .max_data_write = MAX_DATA_UNSPECIFIED,
+       .check_trans    = it8716f_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = it8716f_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = it8716f_spi_chip_read,
@@ -242,6 +246,18 @@ int init_superio_ite(void)
        return ret;
 }
 
+static int it8716f_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                  const unsigned char *writearr)
+{
+       if (readcnt > 3) {
+               return -1;
+       }
+       if (writecnt != 1 && writecnt != 2 && writecnt != 4 && writecnt != 5) {
+               return 1;
+       }
+       return 0;
+}
+
 /*
  * The IT8716F only supports commands with length 1,2,4,5 bytes including
  * command byte and can not read more than 3 bytes from the device.
@@ -259,14 +275,16 @@ static int it8716f_spi_send_command(struct flashctx 
*flash,
        uint8_t busy, writeenc;
        int i;
 
+       if (it8716f_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+               msg_pspew("%s called with an unsupported transaction layout: 
readcnt = %d, writecnt = %d.\n",
+                         __func__, readcnt, writecnt);
+               return SPI_INVALID_LENGTH;
+       }
+
        do {
                busy = INB(it8716f_flashport) & 0x80;
        } while (busy);
-       if (readcnt > 3) {
-               msg_pinfo("%s called with unsupported readcnt %i.\n",
-                         __func__, readcnt);
-               return SPI_INVALID_LENGTH;
-       }
+
        switch (writecnt) {
        case 1:
                OUTB(writearr[0], it8716f_flashport + 1);
@@ -293,8 +311,6 @@ static int it8716f_spi_send_command(struct flashctx *flash,
                writeenc = 0x3;
                break;
        default:
-               msg_pinfo("%s called with unsupported writecnt %i.\n",
-                         __func__, writecnt);
                return SPI_INVALID_LENGTH;
        }
        /*
diff --git a/linux_spi.c b/linux_spi.c
index 2f46463..66e2a30 100644
--- a/linux_spi.c
+++ b/linux_spi.c
@@ -37,6 +37,8 @@
 static int fd = -1;
 
 static int linux_spi_shutdown(void *data);
+static int linux_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                const unsigned char *writearr);
 static int linux_spi_send_command(struct flashctx *flash, unsigned int 
writecnt,
                                  unsigned int readcnt,
                                  const unsigned char *txbuf,
@@ -50,6 +52,8 @@ static const struct spi_programmer spi_programmer_linux = {
        .type           = SPI_CONTROLLER_LINUX,
        .max_data_read  = MAX_DATA_UNSPECIFIED, /* TODO? */
        .max_data_write = MAX_DATA_UNSPECIFIED, /* TODO? */
+       .check_trans    = linux_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = linux_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = linux_spi_read,
@@ -129,29 +133,41 @@ static int linux_spi_shutdown(void *data)
        return 0;
 }
 
+static int linux_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                const unsigned char *writearr)
+{
+       /* The implementation currently does not support requests that
+          don't start with sending a command. */
+       if (writecnt == 0)
+               return SPI_INVALID_LENGTH;
+       return 0;
+}
+
 static int linux_spi_send_command(struct flashctx *flash, unsigned int 
writecnt,
                                  unsigned int readcnt,
-                                 const unsigned char *txbuf,
-                                 unsigned char *rxbuf)
+                                 const unsigned char *writearr,
+                                 unsigned char *readarr)
 {
        int iocontrol_code;
        struct spi_ioc_transfer msg[2] = {
                {
-                       .tx_buf = (uint64_t)(ptrdiff_t)txbuf,
+                       .tx_buf = (uint64_t)(ptrdiff_t)writearr,
                        .len = writecnt,
                },
                {
-                       .rx_buf = (uint64_t)(ptrdiff_t)rxbuf,
+                       .rx_buf = (uint64_t)(ptrdiff_t)readarr,
                        .len = readcnt,
                },
        };
 
+       int ret = linux_spi_check_trans(flash, writecnt, readcnt, writearr);
+       if (ret != 0)
+               msg_perr("%s called with an unsupported transaction layout: 
readcnt = %d, writecnt = %d.\n",
+                         __func__, readcnt, writecnt);
+               return ret;
+
        if (fd == -1)
                return -1;
-       /* The implementation currently does not support requests that
-          don't start with sending a command. */
-       if (writecnt == 0)
-               return SPI_INVALID_LENGTH;
 
        /* Just submit the first (write) request in case there is nothing
           to read. Otherwise submit both requests. */
diff --git a/programmer.h b/programmer.h
index dedec67..a438ec6 100644
--- a/programmer.h
+++ b/programmer.h
@@ -529,9 +529,19 @@ struct spi_programmer {
        int (*read)(struct flashctx *flash, uint8_t *buf, unsigned int start, 
unsigned int len);
        int (*write_256)(struct flashctx *flash, uint8_t *buf, unsigned int 
start, unsigned int len);
        int (*write_aai)(struct flashctx *flash, uint8_t *buf, unsigned int 
start, unsigned int len);
+       /* Returns 0 if the supplied data can be sent by this programmer. 
Possible error codes include:
+        * SPI_INVALID_LENGTH   if readcnt, writecnt or their combination is 
not allowed
+        * negative values      if readcnt is too big
+        * positive values      if writecnt is too big */
+       int (*check_trans)(struct flashctx *flash, unsigned int writecnt, 
unsigned int readcnt,
+                  const unsigned char *writearr);
+       int (*check_transs)(struct flashctx *flash, struct spi_command *cmds);
        const void *data;
 };
 
+int default_spi_check_trans(struct flashctx *flash, unsigned int writecnt, 
unsigned int readcnt,
+          const unsigned char *writearr);
+int default_spi_check_transs(struct flashctx *flash, struct spi_command *cmds);
 int default_spi_send_command(struct flashctx *flash, unsigned int writecnt, 
unsigned int readcnt,
                             const unsigned char *writearr, unsigned char 
*readarr);
 int default_spi_send_multicommand(struct flashctx *flash, struct spi_command 
*cmds);
diff --git a/sb600spi.c b/sb600spi.c
index fe60aa9..74ce40b 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -89,33 +89,37 @@ static void execute_command(void)
                ;
 }
 
+static int sb600_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                const unsigned char *writearr)
+{
+       /* we expect 1 opcode byte plus up to 8 data bytes (in any direction):
+        * the opcode has its own register, the data bytes are sent via an 8 
byte FIFO. */
+       if ((writecnt == 0) || (writecnt - 1 + readcnt > 8)) {
+               return SPI_INVALID_LENGTH;
+       }
+       return 0;
+}
+
+
 static int sb600_spi_send_command(struct flashctx *flash, unsigned int 
writecnt,
                                  unsigned int readcnt,
                                  const unsigned char *writearr,
                                  unsigned char *readarr)
 {
        int count;
-       /* First byte is cmd which can not being sent through FIFO. */
-       unsigned char cmd = *writearr++;
+       unsigned char cmd = *writearr;
        unsigned int readoffby1;
        unsigned char readwrite;
 
-       writecnt--;
-
-       msg_pspew("%s, cmd=%x, writecnt=%x, readcnt=%x\n",
-                 __func__, cmd, writecnt, readcnt);
-
-       if (readcnt > 8) {
-               msg_pinfo("%s, SB600 SPI controller can not receive %d bytes, "
-                      "it is limited to 8 bytes\n", __func__, readcnt);
+       if (sb600_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+               msg_perr("%s called with an unsupported transaction layout: 
readcnt = %d, writecnt = %d.\n",
+                         __func__, readcnt, writecnt);
                return SPI_INVALID_LENGTH;
        }
 
-       if (writecnt > 8) {
-               msg_pinfo("%s, SB600 SPI controller can not send %d bytes, "
-                      "it is limited to 8 bytes\n", __func__, writecnt);
-               return SPI_INVALID_LENGTH;
-       }
+       /* First byte is cmd which can not be sent through FIFO. */
+       writecnt--;
+       writearr++;
 
        /* This is a workaround for a bug in SB600 and SB700. If we only send
         * an opcode and no additional data/address, the SPI controller will
@@ -123,7 +127,7 @@ static int sb600_spi_send_command(struct flashctx *flash, 
unsigned int writecnt,
         * the chip response is discarded and will not end up in the FIFO.
         * It is unclear if the CS# line is set high too early as well.
         */
-       readoffby1 = (writecnt) ? 0 : 1;
+       readoffby1 = (writecnt == 0) ? 1 : 0;
        readwrite = (readcnt + readoffby1) << 4 | (writecnt);
        mmio_writeb(readwrite, sb600_spibar + 1);
        mmio_writeb(cmd, sb600_spibar + 0);
@@ -196,13 +200,15 @@ static int sb600_spi_send_command(struct flashctx *flash, 
unsigned int writecnt,
 
 static const struct spi_programmer spi_programmer_sb600 = {
        .type = SPI_CONTROLLER_SB600,
-       .max_data_read = 8,
-       .max_data_write = 5,
-       .command = sb600_spi_send_command,
-       .multicommand = default_spi_send_multicommand,
-       .read = default_spi_read,
-       .write_256 = default_spi_write_256,
-       .write_aai = default_spi_write_aai,
+       .max_data_read  = 8,
+       .max_data_write = 5,
+       .check_trans    = sb600_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
+       .command        = sb600_spi_send_command,
+       .multicommand   = default_spi_send_multicommand,
+       .read           = default_spi_read,
+       .write_256      = default_spi_write_256,
+       .write_aai      = default_spi_write_aai,
 };
 
 int sb600_probe_spi(struct pci_dev *dev)
diff --git a/serprog.c b/serprog.c
index b179ea4..cd67a94 100644
--- a/serprog.c
+++ b/serprog.c
@@ -234,31 +234,31 @@ err_out:
        return 1;
 }
 
-static int sp_check_commandavail(uint8_t command)
+static int sp_check_commandavail(uint8_t cmd)
 {
        int byteoffs, bitoffs;
-       byteoffs = command / 8;
-       bitoffs = command % 8;
+       byteoffs = cmd / 8;
+       bitoffs = cmd % 8;
        return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
 }
 
 static int sp_automatic_cmdcheck(uint8_t cmd)
 {
-       if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
-               msg_pdbg("Warning: Automatic command availability check failed "
-                        "for cmd 0x%x - won't execute cmd\n", cmd);
+       if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0))
                return 1;
-               }
        return 0;
 }
 
-static int sp_docommand(uint8_t command, uint32_t parmlen,
+static int sp_docommand(uint8_t cmd, uint32_t parmlen,
                        uint8_t *params, uint32_t retlen, void *retparms)
 {
        unsigned char c;
-       if (sp_automatic_cmdcheck(command))
+       if (sp_automatic_cmdcheck(cmd)) {
+               msg_pdbg("Warning: Automatic command availability check failed "
+                        "for cmd 0x%x - won't execute cmd\n", cmd);
                return 1;
-       if (write(sp_fd, &command, 1) != 1) {
+       }
+       if (write(sp_fd, &cmd, 1) != 1) {
                msg_perr("Error: cannot write op code: %s\n", strerror(errno));
                return 1;
        }
@@ -316,8 +316,11 @@ static void sp_flush_stream(void)
 static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t * parms)
 {
        uint8_t *sp;
-       if (sp_automatic_cmdcheck(cmd))
+       if (sp_automatic_cmdcheck(cmd)) {
+               msg_pdbg("Warning: Automatic command availability check failed "
+                        "for cmd 0x%x - won't execute cmd\n", cmd);
                return 1;
+       }
        sp = malloc(1 + parmlen);
        if (!sp) sp_die("Error: cannot malloc command buffer");
        sp[0] = cmd;
@@ -332,6 +335,12 @@ static int sp_stream_buffer_op(uint8_t cmd, uint32_t 
parmlen, uint8_t * parms)
        return 0;
 }
 
+static int serprog_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                  const unsigned char *writearr)
+{
+               return sp_automatic_cmdcheck(S_CMD_O_SPIOP);
+}
+
 static int serprog_spi_send_command(struct flashctx *flash,
                                    unsigned int writecnt, unsigned int readcnt,
                                    const unsigned char *writearr,
@@ -342,6 +351,8 @@ static struct spi_programmer spi_programmer_serprog = {
        .type           = SPI_CONTROLLER_SERPROG,
        .max_data_read  = MAX_DATA_READ_UNLIMITED,
        .max_data_write = MAX_DATA_WRITE_UNLIMITED,
+       .check_trans    = serprog_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command        = serprog_spi_send_command,
        .multicommand   = default_spi_send_multicommand,
        .read           = serprog_spi_read,
diff --git a/spi.c b/spi.c
index 94a76a7..eefdabb 100644
--- a/spi.c
+++ b/spi.c
@@ -30,16 +30,42 @@
 #include "programmer.h"
 #include "spi.h"
 
+int default_spi_check_trans(struct flashctx *flash, unsigned int writecnt, 
unsigned int readcnt,
+          const unsigned char *writearr)
+{
+       /* FIXME: even this trivial check does not work yet, because too many 
programmers specify MAX_DATA_*. */
+       /* return flash->pgm->spi.max_data_write >= writecnt && 
flash->pgm->spi.max_data_read >= readcnt; */
+       return 0;
+}
+
+int default_spi_check_transs(struct flashctx *flash, struct spi_command *cmds)
+{
+       int result = 0;
+       for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) {
+               result = flash->pgm->spi.check_trans(flash, cmds->writecnt, 
cmds->readcnt, cmds->writearr);
+       }
+       return result;
+}
+
 int spi_send_command(struct flashctx *flash, unsigned int writecnt,
                     unsigned int readcnt, const unsigned char *writearr,
                     unsigned char *readarr)
 {
-       return flash->pgm->spi.command(flash, writecnt, readcnt, writearr,
-                                      readarr);
+       int ret = flash->pgm->spi.check_trans(flash, writecnt, readcnt, 
writearr);
+       if (ret) {
+               msg_pspew("%s: check_trans failed with %d\n", __func__, ret);
+               return ret;
+       }
+       return flash->pgm->spi.command(flash, writecnt, readcnt, writearr, 
readarr);
 }
 
 int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds)
 {
+       int ret = flash->pgm->spi.check_transs(flash, cmds);
+       if (ret) {
+               msg_pspew("%s: check_trans failed with %d\n", __func__, ret);
+               return ret;
+       }
        return flash->pgm->spi.multicommand(flash, cmds);
 }
 
diff --git a/wbsio_spi.c b/wbsio_spi.c
index 778b983..66f9e51 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -108,6 +108,15 @@ static uint8_t determine_mode(struct flashctx *flash, 
unsigned int writecnt, uns
        return 0;
 }
 
+static int wbsio_spi_check_trans(struct flashctx *flash, unsigned int 
writecnt, unsigned int readcnt,
+                                const unsigned char *writearr)
+{
+       if (determine_mode(flash, writecnt, readcnt, writearr) == 0)
+               return SPI_INVALID_LENGTH;
+
+       return 0;
+}
+
 static int wbsio_spi_send_command(struct flashctx *flash, unsigned int 
writecnt,
                                  unsigned int readcnt,
                                  const unsigned char *writearr,
@@ -119,6 +128,8 @@ static const struct spi_programmer spi_programmer_wbsio = {
        .type = SPI_CONTROLLER_WBSIO,
        .max_data_read = MAX_DATA_UNSPECIFIED,
        .max_data_write = MAX_DATA_UNSPECIFIED,
+       .check_trans    = wbsio_spi_check_trans,
+       .check_transs   = default_spi_check_transs,
        .command = wbsio_spi_send_command,
        .multicommand = default_spi_send_multicommand,
        .read = wbsio_spi_read,
-- 
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to