From 71328b1824b9a3246a8072121ceab18c06e86740 Mon Sep 17 00:00:00 2001 From: Rutger Hofman Date: Sun, 24 May 2009 19:53:11 +0000 Subject: [PATCH] readmem() and writemem() return a status. Patch their error handling git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1626 b68d4a1b-bc3d-0410-92ed-d4ac073336b7 --- urjtag/ChangeLog | 7 +++ urjtag/include/urjtag/bus.h | 12 ++--- urjtag/include/urjtag/bus_driver.h | 2 +- urjtag/include/urjtag/error.h | 8 +-- urjtag/src/bus/readmem.c | 55 +++++++++++-------- urjtag/src/bus/writemem.c | 84 +++++++++++++++++------------- urjtag/src/cmd/cmd_readmem.c | 5 +- urjtag/src/cmd/cmd_writemem.c | 5 +- urjtag/src/global/urjtag.c | 4 +- urjtag/src/svf/svf.c | 6 +-- 10 files changed, 112 insertions(+), 76 deletions(-) diff --git a/urjtag/ChangeLog b/urjtag/ChangeLog index d038265e..2683021f 100644 --- a/urjtag/ChangeLog +++ b/urjtag/ChangeLog @@ -1,3 +1,10 @@ +2009-05-24 Rutger Hofman + + * src/bus/readmem.c, src/bus/writemem.c, include/urjtag/bus.h, + src/cmd/cmd_readmem.c, src/cmd/cmd_writemem.c: readmem() and + writemem() now return an error condition. Patch up error handling + in readmem() and writemem(). + 2009-05-23 Arnim Laeuger * src/bsdl/bsdl_msg.h, src/bsdl/vhdl_flex.l, src/bsdl/vhdl_bison.y, diff --git a/urjtag/include/urjtag/bus.h b/urjtag/include/urjtag/bus.h index db30dfa1..abb581a3 100644 --- a/urjtag/include/urjtag/bus.h +++ b/urjtag/include/urjtag/bus.h @@ -33,10 +33,10 @@ extern urj_bus_t *urj_bus; -/* @@@@ RFHH return status */ -void urj_bus_readmem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len); -/* @@@@ RFHH return status */ -void urj_bus_writemem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len); +/** @return URJ_STATUS_OK on success; URJ_STATUS_FAIL on error */ +int urj_bus_readmem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len); +/** @return URJ_STATUS_OK on success; URJ_STATUS_FAIL on error */ +int urj_bus_writemem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len); typedef struct { @@ -49,9 +49,9 @@ extern urj_buses_t urj_buses; extern const urj_bus_driver_t *urj_bus_drivers[]; void urj_bus_buses_free (void); -/* @@@@ RFHH return status */ +/** @return URJ_STATUS_OK on success; URJ_STATUS_FAIL on error */ void urj_bus_buses_add (urj_bus_t *abus); -/* @@@@ RFHH return status? */ +/** @return URJ_STATUS_OK on success; URJ_STATUS_FAIL on error */ void urj_bus_buses_delete (urj_bus_t *abus); /** set active bus diff --git a/urjtag/include/urjtag/bus_driver.h b/urjtag/include/urjtag/bus_driver.h index 78cadf16..883e8adb 100644 --- a/urjtag/include/urjtag/bus_driver.h +++ b/urjtag/include/urjtag/bus_driver.h @@ -82,7 +82,7 @@ struct urj_bus const urj_bus_driver_t *driver; }; -#define URJ_BUS_PRINTINFO(ll, bus) (bus)->driver->printinfo(ll, bus) +#define URJ_BUS_PRINTINFO(ll,bus) (bus)->driver->printinfo(ll,bus) #define URJ_BUS_PREPARE(bus) (bus)->driver->prepare(bus) #define URJ_BUS_AREA(bus,adr,a) (bus)->driver->area(bus,adr,a) #define URJ_BUS_READ_START(bus,adr) (bus)->driver->read_start(bus,adr) diff --git a/urjtag/include/urjtag/error.h b/urjtag/include/urjtag/error.h index cc57eaa5..c8c5bcfb 100644 --- a/urjtag/include/urjtag/error.h +++ b/urjtag/include/urjtag/error.h @@ -45,14 +45,16 @@ typedef enum urj_error URJ_ERROR_NO_BUS_DRIVER, URJ_ERROR_BUFFER_EXHAUSTED, URJ_ERROR_ILLEGAL_STATE, + URJ_ERROR_ILLEGAL_TRANSITION, URJ_ERROR_OUT_OF_BOUNDS, URJ_ERROR_TIMEOUT, URJ_ERROR_UNSUPPORTED, URJ_ERROR_SYNTAX, + URJ_ERROR_FILEIO, /**< I/O error from fread/fwrite */ - URJ_ERROR_IO, /**< I/O error from OS */ - URJ_ERROR_FTD, /**< error from ftdi/ftd2xx */ - URJ_ERROR_USB, /**< error from libusb */ + URJ_ERROR_IO, /**< I/O error from OS */ + URJ_ERROR_FTD, /**< error from ftdi/ftd2xx */ + URJ_ERROR_USB, /**< error from libusb */ URJ_ERROR_BUS, URJ_ERROR_BUS_DMA, diff --git a/urjtag/src/bus/readmem.c b/urjtag/src/bus/readmem.c index 38dbc079..3af4505f 100644 --- a/urjtag/src/bus/readmem.c +++ b/urjtag/src/bus/readmem.c @@ -34,17 +34,17 @@ #include #include +#include #include #include #include -// @@@@ RFHH return status -void +int urj_bus_readmem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) { uint32_t step; - uint32_t a; - int bc = 0; + uint64_t a; + size_t bc = 0; #define BSIZE 4096 uint8_t b[BSIZE]; urj_bus_area_t area; @@ -52,23 +52,27 @@ urj_bus_readmem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) if (!bus) { - printf (_("Error: Missing bus driver!\n")); - return; + urj_error_set (URJ_ERROR_NO_BUS_DRIVER, _("Missing bus driver")); + return URJ_STATUS_FAIL; } URJ_BUS_PREPARE (bus); if (URJ_BUS_AREA (bus, addr, &area) != URJ_STATUS_OK) - { - printf (_("Error: Bus width detection failed\n")); - return; - } + return URJ_STATUS_FAIL; + step = area.width / 8; if (step == 0) { - printf (_("Unknown bus width!\n")); - return; + urj_error_set (URJ_ERROR_INVALID, _("Unknown bus width")); + return URJ_STATUS_FAIL; + } + if (BSIZE % step != 0) + { + urj_error_set (URJ_ERROR_INVALID, "step %lu must divide BSIZE %d", + (long unsigned) step, BSIZE); + return URJ_STATUS_FAIL; } addr = addr & (~(step - 1)); @@ -81,21 +85,23 @@ urj_bus_readmem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) if (len == 0) { - printf (_("length is 0.\n")); - return; + urj_error_set (URJ_ERROR_INVALID, _("length is 0")); + return URJ_STATUS_FAIL; } a = addr; end = a + len; urj_log (URJ_LOG_LEVEL_NORMAL, _("reading:\n")); - // @@@@ RFHH check status - URJ_BUS_READ_START (bus, addr); + + if (URJ_BUS_READ_START (bus, addr) != URJ_STATUS_OK) + return URJ_STATUS_FAIL; + for (a += step; a <= end; a += step) { uint32_t data; int j; - if (a < addr + len) + if (a < end) data = URJ_BUS_READ_NEXT (bus, a); else data = URJ_BUS_READ_END (bus); @@ -111,13 +117,20 @@ urj_bus_readmem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) if ((bc >= BSIZE) || (a >= end)) { - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08lX"), - (long unsigned) a); - urj_log (URJ_LOG_LEVEL_NORMAL, "\r"); - fwrite (b, bc, 1, f); + urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08llX\r"), + (long long unsigned) a); + if (fwrite (b, bc, 1, f) != bc) + { + urj_error_set (URJ_ERROR_FILEIO, "fwrite fails"); + urj_error_state.sys_errno = ferror(f); + clearerr(f); + return URJ_STATUS_FAIL; + } bc = 0; } } urj_log (URJ_LOG_LEVEL_NORMAL, _("\nDone.\n")); + + return URJ_STATUS_OK; } diff --git a/urjtag/src/bus/writemem.c b/urjtag/src/bus/writemem.c index 3b116746..6f400b54 100644 --- a/urjtag/src/bus/writemem.c +++ b/urjtag/src/bus/writemem.c @@ -27,17 +27,17 @@ #include #include +#include #include #include #include -// @@@@ RFHH return status -void +int urj_bus_writemem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) { uint32_t step; - uint32_t a; - int bc = 0; + uint64_t a; + size_t bc = 0; int bidx = 0; #define BSIZE 4096 uint8_t b[BSIZE]; @@ -46,23 +46,27 @@ urj_bus_writemem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) if (!bus) { - printf (_("Error: Missing bus driver!\n")); - return; + urj_error_set (URJ_ERROR_NO_BUS_DRIVER, _("Missing bus driver")); + return URJ_STATUS_FAIL; } URJ_BUS_PREPARE (bus); if (URJ_BUS_AREA (bus, addr, &area) != URJ_STATUS_OK) - { - printf (_("Error: Bus width detection failed\n")); - return; - } + return URJ_STATUS_FAIL; + step = area.width / 8; if (step == 0) { - printf (_("Unknown bus width!\n")); - return; + urj_error_set (URJ_ERROR_INVALID, _("Unknown bus width")); + return URJ_STATUS_FAIL; + } + if (BSIZE % step != 0) + { + urj_error_set (URJ_ERROR_INVALID, "step %lu must divide BSIZE %d", + (long unsigned) step, BSIZE); + return URJ_STATUS_FAIL; } addr = addr & (~(step - 1)); @@ -75,8 +79,8 @@ urj_bus_writemem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) if (len == 0) { - urj_log (URJ_LOG_LEVEL_NORMAL, _("length is 0.\n")); - return; + urj_error_set (URJ_ERROR_INVALID, _("length is 0")); + return URJ_STATUS_FAIL; } a = addr; @@ -89,49 +93,55 @@ urj_bus_writemem (urj_bus_t *bus, FILE *f, uint32_t addr, uint32_t len) int j; /* Read one block of data */ - if (bc < step) + if (bc == 0) { - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08lX"), - (long unsigned) a); - urj_log (URJ_LOG_LEVEL_NORMAL, "\r"); - fflush (stdout); - if (bc != 0) - printf (_("Data not on word boundary, NOT SUPPORTED!")); - if (feof (f)) - { - printf (_("Unexpected end of file!\n")); - printf (_("Addr: 0x%08lX\n"), (long unsigned) a); - break; - } + urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08llX\r"), + (long long unsigned) a); bc = fread (b, 1, BSIZE, f); - if (!bc) + if (bc != BSIZE) { - printf (_("Short read: bc=0x%X\n"), bc); + urj_log (URJ_LOG_LEVEL_NORMAL, _("Short read: bc=0x%zX\n"), bc); + if (bc < step) + { + // Not even enough for one step. Something is wrong. Check + // the file state and bail out. + if (feof (f)) + urj_error_set (URJ_ERROR_FILEIO, + _("Unexpected end of file; Addr: 0x%08llX\n"), + (long long unsigned) a); + else + { + urj_error_set (URJ_ERROR_FILEIO, "fread fails"); + urj_error_state.sys_errno = ferror(f); + clearerr(f); + } + + return URJ_STATUS_FAIL; + } + /* else, process what we have read, then return to fread() to + * meet the error condition (again) */ } bidx = 0; - } - /* Write a word at time */ + /* Write a word at a time */ data = 0; - for (j = step; j > 0; j--) + for (j = step; j > 0 && bc > 0; j--) { if (urj_big_endian) { data |= b[bidx++]; data <<= 8; - bc--; } else - { data |= (b[bidx++] << ((step - j) * 8)); - bc--; - } + bc--; } URJ_BUS_WRITE (bus, a, data); - } urj_log (URJ_LOG_LEVEL_NORMAL, _("\nDone.\n")); + + return URJ_STATUS_OK; } diff --git a/urjtag/src/cmd/cmd_readmem.c b/urjtag/src/cmd/cmd_readmem.c index 241d9e2d..96c353c2 100644 --- a/urjtag/src/cmd/cmd_readmem.c +++ b/urjtag/src/cmd/cmd_readmem.c @@ -41,6 +41,7 @@ cmd_readmem_run (urj_chain_t *chain, char *params[]) { long unsigned adr; long unsigned len; + int r; FILE *f; if (urj_cmd_params (params) != 4) @@ -67,10 +68,10 @@ cmd_readmem_run (urj_chain_t *chain, char *params[]) urj_error_IO_set (_("Unable to create file `%s'"), params[3]); return URJ_STATUS_FAIL; } - urj_bus_readmem (urj_bus, f, adr, len); + r = urj_bus_readmem (urj_bus, f, adr, len); fclose (f); - return URJ_STATUS_OK; + return r; } static void diff --git a/urjtag/src/cmd/cmd_writemem.c b/urjtag/src/cmd/cmd_writemem.c index 7e95d070..73feb936 100644 --- a/urjtag/src/cmd/cmd_writemem.c +++ b/urjtag/src/cmd/cmd_writemem.c @@ -40,6 +40,7 @@ cmd_writemem_run (urj_chain_t *chain, char *params[]) long unsigned adr; long unsigned len; FILE *f; + int r; if (urj_cmd_params (params) != 4) { @@ -65,10 +66,10 @@ cmd_writemem_run (urj_chain_t *chain, char *params[]) urj_error_IO_set (_("Unable to open file `%s'"), params[3]); return URJ_STATUS_FAIL; } - urj_bus_writemem (urj_bus, f, adr, len); + r = urj_bus_writemem (urj_bus, f, adr, len); fclose (f); - return URJ_STATUS_OK; + return r; } static void diff --git a/urjtag/src/global/urjtag.c b/urjtag/src/global/urjtag.c index ee46c86d..8f9db1a2 100644 --- a/urjtag/src/global/urjtag.c +++ b/urjtag/src/global/urjtag.c @@ -107,11 +107,13 @@ urj_error_string (urj_error_t err) case URJ_ERROR_NOTFOUND: return "not found"; case URJ_ERROR_NO_BUS_DRIVER: return "no bus driver"; case URJ_ERROR_BUFFER_EXHAUSTED: return "buffer exhausted"; - case URJ_ERROR_ILLEGAL_STATE: return "illegal state transition"; + case URJ_ERROR_ILLEGAL_STATE: return "illegal state"; + case URJ_ERROR_ILLEGAL_TRANSITION: return "illegal state transition"; case URJ_ERROR_OUT_OF_BOUNDS: return "out of bounds"; case URJ_ERROR_TIMEOUT: return "timeout"; case URJ_ERROR_UNSUPPORTED: return "unsupported"; case URJ_ERROR_SYNTAX: return "syntax"; + case URJ_ERROR_FILEIO: return "file I/O"; case URJ_ERROR_IO: return "I/O error from OS"; case URJ_ERROR_FTD: return "ftdi/ftd2xx error"; diff --git a/urjtag/src/svf/svf.c b/urjtag/src/svf/svf.c index 39b932ef..aab67cf7 100644 --- a/urjtag/src/svf/svf.c +++ b/urjtag/src/svf/svf.c @@ -1007,7 +1007,7 @@ urj_svf_trst (urj_chain_t *chain, urj_svf_parser_priv_t *priv, int trst_mode) if (priv->svf_trst_absent) { - urj_error_set (URJ_ERROR_ILLEGAL_STATE, + urj_error_set (URJ_ERROR_ILLEGAL_TRANSITION, _("Error %s: no further TRST command allowed after mode ABSENT"), "svf"); return URJ_STATUS_FAIL; @@ -1030,7 +1030,7 @@ urj_svf_trst (urj_chain_t *chain, urj_svf_parser_priv_t *priv, int trst_mode) if (priv->svf_state_executed) { - urj_error_set (URJ_ERROR_ILLEGAL_STATE, + urj_error_set (URJ_ERROR_ILLEGAL_TRANSITION, _("Error %s: TRST ABSENT must not be issued after a STATE command"), "svf"); return URJ_STATUS_FAIL; @@ -1038,7 +1038,7 @@ urj_svf_trst (urj_chain_t *chain, urj_svf_parser_priv_t *priv, int trst_mode) if (priv->sir_params.params.number > 0.0 || priv->sdr_params.params.number > 0.0) { - urj_error_set (URJ_ERROR_ILLEGAL_STATE, + urj_error_set (URJ_ERROR_ILLEGAL_TRANSITION, _("Error %s: TRST ABSENT must not be issued after an SIR or SDR command"), "svf"); }