CMD_RY = 4,
CMD_DELAY = 5,
};
-#define PAR_MODE8 (1 << 4)
+#define PAR_MODE8 (1 << 4) /* but still drives noth LWR and UWR */
#define PAR_DEV_ID (1 << 5)
#define PAR_SINGE (1 << 6)
#define PAR_INC (1 << 7)
return 0;
}
-static void set_addr(int fd, uint32_t addr)
+/* addr arg is always byte address */
+static void set_addr8(int fd, uint32_t addr)
{
uint8_t cmd[6] = {
- CMD_ADDR, addr >> 17,
- CMD_ADDR, addr >> 9,
- CMD_ADDR, addr >> 1
+ CMD_ADDR, addr >> 16,
+ CMD_ADDR, addr >> 8,
+ CMD_ADDR, addr >> 0
+ };
+ write_serial(fd, cmd, sizeof(cmd));
+}
+
+static void set_addr16(int fd, uint32_t addr)
+{
+ set_addr8(fd, addr >> 1);
+}
+
+static uint16_t read_bus8(int fd, uint32_t addr)
+{
+ uint8_t cmd[7] = {
+ CMD_ADDR, addr >> 16,
+ CMD_ADDR, addr >> 8,
+ CMD_ADDR, addr >> 0,
+ CMD_RD | PAR_SINGE | PAR_MODE8
};
+ uint8_t r;
+
write_serial(fd, cmd, sizeof(cmd));
+ read_serial(fd, &r, sizeof(r));
+ return r;
}
-static uint16_t read_word(int fd, uint32_t addr)
+static uint16_t read_bus16(int fd, uint32_t addr)
{
uint8_t cmd[7] = {
CMD_ADDR, addr >> 17,
return ntohs(r);
}
-static void write_word(int fd, uint32_t addr, uint16_t d)
+static void write_bus8(int fd, uint32_t addr, uint16_t d)
+{
+ uint8_t cmd[8] = {
+ CMD_ADDR, addr >> 16,
+ CMD_ADDR, addr >> 8,
+ CMD_ADDR, addr >> 0,
+ CMD_WR | PAR_SINGE | PAR_MODE8,
+ d
+ };
+
+ write_serial(fd, cmd, sizeof(cmd));
+}
+
+static void write_bus16(int fd, uint32_t addr, uint16_t d)
{
uint8_t cmd[9] = {
CMD_ADDR, addr >> 17,
write_serial(fd, cmd, sizeof(cmd));
}
-static void read_block(int fd, void *dst, uint32_t size)
+static void read_block8(int fd, void *dst, uint32_t size)
{
+ // PAR_MODE8 does not work, so read as 16bit and throw away MSB
+ uint8_t tmp[0x10000], *d8 = dst;
uint8_t cmd[5] = {
- CMD_LEN, size >> 9,
- CMD_LEN, size >> 1,
+ CMD_LEN, size >> 8,
+ CMD_LEN, size >> 0,
CMD_RD | PAR_INC
};
+ int i;
assert(size <= 0x10000);
write_serial(fd, cmd, sizeof(cmd));
read_serial(fd, dst, size);
+ read_serial(fd, tmp, size);
+
+ for (i = 0; i < size / 2; i++)
+ d8[i] = d8[i * 2 + 1];
+ d8 += size / 2;
+ for (i = 0; i < size / 2; i++)
+ d8[i] = tmp[i * 2 + 1];
}
-static uint16_t flash_seq_r(int fd, uint8_t cmd, uint32_t addr)
+static void read_block16(int fd, void *dst, uint32_t size)
{
- // unlock
- write_word(fd, 0xaaa, 0xaa);
- write_word(fd, 0x555, 0x55);
+ uint8_t cmd[5] = {
+ CMD_LEN, size >> 9,
+ CMD_LEN, size >> 1,
+ CMD_RD | PAR_INC
+ };
- write_word(fd, 0xaaa, cmd);
- return read_word(fd, addr);
+ assert(size <= 0x10000);
+ write_serial(fd, cmd, sizeof(cmd));
+ read_serial(fd, dst, size);
}
-static void flash_seq_erase(int fd, uint32_t addr)
+static void flash_seq_write8(int fd, uint32_t addr, const uint8_t *d)
{
- // printf("erase %06x\n", addr);
- write_word(fd, 0xaaa, 0xaa);
- write_word(fd, 0x555, 0x55);
- write_word(fd, 0xaaa, 0x80);
+ uint8_t cmd[] = {
+ // unlock
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x0a,
+ CMD_ADDR, 0xaa,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0xaa,
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x05,
+ CMD_ADDR, 0x55,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0x55,
+ // program setup
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x0a,
+ CMD_ADDR, 0xaa,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0xa0,
+ // program data
+ CMD_ADDR, addr >> 16,
+ CMD_ADDR, addr >> 8,
+ CMD_ADDR, addr >> 0,
+ CMD_WR | PAR_SINGE | PAR_MODE8, *d,
+ CMD_RY
+ };
- write_word(fd, 0xaaa, 0xaa);
- write_word(fd, 0x555, 0x55);
- write_word(fd, addr, 0x30);
+ write_serial(fd, cmd, sizeof(cmd));
}
-static void flash_seq_write(int fd, uint32_t addr, uint8_t *d)
+static void flash_seq_write16(int fd, uint32_t addr, const uint8_t *d)
{
uint8_t cmd[] = {
// unlock
write_serial(fd, cmd, sizeof(cmd));
}
+// -- 8bit+LoROM --
+
+static uint32_t lorom_rom_addr(uint32_t a)
+{
+ return ((a & 0x7f8000) << 1) | 0x8000 | (a & 0x7fff);
+}
+
+static void set_addr8l(int fd, uint32_t a)
+{
+ set_addr8(fd, lorom_rom_addr(a));
+}
+
+static uint16_t read_bus8l(int fd, uint32_t a)
+{
+ return read_bus8(fd, lorom_rom_addr(a));
+}
+
+static void write_bus8l(int fd, uint32_t a, uint16_t d)
+{
+ write_bus8(fd, lorom_rom_addr(a), d);
+}
+
+static void flash_seq_write8l(int fd, uint32_t a, const uint8_t *d)
+{
+ a = lorom_rom_addr(a);
+ uint8_t cmd[] = {
+ // unlock
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x8a,
+ CMD_ADDR, 0xaa,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0xaa,
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x85,
+ CMD_ADDR, 0x55,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0x55,
+ // program setup
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x8a,
+ CMD_ADDR, 0xaa,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0xa0,
+ // program data
+ CMD_ADDR, a >> 16,
+ CMD_ADDR, a >> 8,
+ CMD_ADDR, a >> 0,
+ CMD_WR | PAR_SINGE | PAR_MODE8, *d,
+ CMD_RY
+ };
+
+ write_serial(fd, cmd, sizeof(cmd));
+}
+
+// -- 8bit+LoROM+adapter --
+
+static uint32_t do_flipflops(int fd, uint32_t a)
+{
+ static uint32_t abits_now = ~0u; // A23, A22, A21
+ uint32_t abits = (a >> 21) & 7;
+
+ if (abits != abits_now) {
+ // printf("flipflops: %x->%x\n", abits_now, abits);
+ write_bus16(fd, 0xa13000, abits);
+ abits_now = abits;
+ }
+ return a & 0x1fffff;
+}
+
+static void set_addr8la(int fd, uint32_t a)
+{
+ set_addr8(fd, do_flipflops(fd, lorom_rom_addr(a)));
+}
+
+static uint16_t read_bus8la(int fd, uint32_t a)
+{
+ return read_bus8(fd, do_flipflops(fd, lorom_rom_addr(a)));
+}
+
+static void write_bus8la(int fd, uint32_t a, uint16_t d)
+{
+ write_bus8(fd, do_flipflops(fd, lorom_rom_addr(a)), d);
+}
+
+static void flash_seq_write8la(int fd, uint32_t a, const uint8_t *d)
+{
+ // we should clear flipflops for the flash commands, but this
+ // doesn't seem to be necessary as the flash chip seems to
+ // ignore the upper bits when looking for commands, and this
+ // extra clearing would slow things down
+ a = do_flipflops(fd, lorom_rom_addr(a));
+ uint8_t cmd[] = {
+ // unlock
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x8a,
+ CMD_ADDR, 0xaa,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0xaa,
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x85,
+ CMD_ADDR, 0x55,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0x55,
+ // program setup
+ CMD_ADDR, 0,
+ CMD_ADDR, 0x8a,
+ CMD_ADDR, 0xaa,
+ CMD_WR | PAR_SINGE | PAR_MODE8, 0xa0,
+ // program data
+ CMD_ADDR, a >> 16,
+ CMD_ADDR, a >> 8,
+ CMD_ADDR, a >> 0,
+ CMD_WR | PAR_SINGE | PAR_MODE8, *d,
+ CMD_RY
+ };
+
+ write_serial(fd, cmd, sizeof(cmd));
+}
+
+// -- 8bit+LoROM+adapter+sram --
+
+static uint32_t lorom_sram_addr(uint32_t a)
+{
+ return a | 0x600000;
+}
+
+static void set_addr8las(int fd, uint32_t a)
+{
+ set_addr8(fd, do_flipflops(fd, lorom_sram_addr(a)));
+}
+
+static uint16_t read_bus8las(int fd, uint32_t a)
+{
+ return read_bus8(fd, do_flipflops(fd, lorom_sram_addr(a)));
+}
+
+static void write_bus8las(int fd, uint32_t a, uint16_t d)
+{
+ write_bus8(fd, do_flipflops(fd, lorom_sram_addr(a)), d);
+}
+
+static void flash_seq_write8las(int fd, uint32_t a, const uint8_t *d)
+{
+}
+
+#define N0 ""
+#define N1 "8bit"
+#define N2 "8bit+LoROM"
+#define N3 "8bit+LoROM+adapter"
+#define N4 "8bit+LoROM+adapter+sram"
+static const struct iof
+{
+ const char *name;
+ int addrs_remapped;
+ void (*set_addr)(int fd, uint32_t addr);
+ uint16_t (*read_bus)(int fd, uint32_t addr);
+ void (*write_bus)(int fd, uint32_t addr, uint16_t d);
+ void (*read_block)(int fd, void *dst, uint32_t size);
+ void (*flash_seq_write)(int fd, uint32_t addr, const uint8_t *d);
+}
+io_ops[] =
+{
+ { N0, 0, set_addr16, read_bus16, write_bus16, read_block16, flash_seq_write16 },
+ { N1, 0, set_addr8, read_bus8, write_bus8, read_block8, flash_seq_write8 },
+ { N2, 1, set_addr8l, read_bus8l, write_bus8l, read_block8, flash_seq_write8l },
+ { N3, 1, set_addr8la, read_bus8la, write_bus8la, read_block8, flash_seq_write8la },
+ { N4, 0, set_addr8las, read_bus8las, write_bus8las, read_block8, flash_seq_write8las },
+};
+
+static const struct iof *io = &io_ops[0];
+
+static uint16_t flash_seq_r(int fd, uint8_t cmd, uint32_t addr)
+{
+ // unlock
+ io->write_bus(fd, 0xaaa, 0xaa);
+ io->write_bus(fd, 0x555, 0x55);
+
+ io->write_bus(fd, 0xaaa, cmd);
+ return io->read_bus(fd, addr);
+}
+
+static void flash_seq_erase_d(int fd, uint32_t addr, uint8_t d)
+{
+ // printf("erase %06x\n", addr);
+ io->write_bus(fd, 0xaaa, 0xaa);
+ io->write_bus(fd, 0x555, 0x55);
+ io->write_bus(fd, 0xaaa, 0x80);
+
+ io->write_bus(fd, 0xaaa, 0xaa);
+ io->write_bus(fd, 0x555, 0x55);
+ io->write_bus(fd, addr, d);
+}
+
+static void flash_seq_erase(int fd, uint32_t addr)
+{
+ flash_seq_erase_d(fd, addr, 0x30);
+}
+
+static void flash_seq_erase_full(int fd)
+{
+ flash_seq_erase_d(fd, 0xaaa, 0x10);
+}
+
// status wait + dummy read to cause a wait?
static uint16_t ry_read(int fd)
{
uint32_t i, a;
info.mid = flash_seq_r(fd, 0x90, 0); // autoselect
- info.did = read_word(fd, 2);
+ info.did = io->read_bus(fd, 2);
// could enter CFI directly, but there seems to be a "stack"
// of modes, so 2 exits would be needed
- write_word(fd, 0, 0xf0);
+ io->write_bus(fd, 0, 0xf0);
- write_word(fd, 0xaa, 0x98); // CFI Query
- resp[0] = read_word(fd, 0x20);
- resp[1] = read_word(fd, 0x22);
- resp[2] = read_word(fd, 0x24);
+ io->write_bus(fd, 0xaa, 0x98); // CFI Query
+ resp[0] = io->read_bus(fd, 0x20);
+ resp[1] = io->read_bus(fd, 0x22);
+ resp[2] = io->read_bus(fd, 0x24);
if (memcmp(resp, qry, sizeof(resp))) {
fprintf(stderr, "unexpected CFI response: %04x %04x %04x\n",
resp[0], resp[1], resp[2]);
exit(1);
}
- info.size = 1u << read_word(fd, 0x4e);
- info.region_cnt = read_word(fd, 0x58);
+ info.size = 1u << io->read_bus(fd, 0x4e);
+ info.region_cnt = io->read_bus(fd, 0x58);
assert(0 < info.region_cnt && info.region_cnt <= 4);
for (i = 0, a = 0x5a; i < info.region_cnt; i++, a += 8) {
- info.region[i].block_count = read_word(fd, a + 0) + 1;
- info.region[i].block_count += read_word(fd, a + 2) << 8;
- info.region[i].block_size = read_word(fd, a + 4) << 8;
- info.region[i].block_size |= read_word(fd, a + 6) << 16;
+ info.region[i].block_count = io->read_bus(fd, a + 0) + 1;
+ info.region[i].block_count += io->read_bus(fd, a + 2) << 8;
+ info.region[i].block_size = io->read_bus(fd, a + 4) << 8;
+ info.region[i].block_size |= io->read_bus(fd, a + 6) << 16;
info.region[i].start = total;
info.region[i].size =
info.region[i].block_size * info.region[i].block_count;
total += info.region[i].size;
}
- write_word(fd, 0, 0xf0); // flash reset
+ io->write_bus(fd, 0, 0xf0); // flash reset
printf("Flash info:\n");
printf("Manufacturer ID: %04x\n", info.mid);
static uint32_t get_block_addr(uint32_t addr, uint32_t blk_offset)
{
- uint32_t i;
+ uint32_t i, base, faddr;
assert(info.region_cnt);
+ assert(info.size);
+
+ // get a flash address to allow mapper hardware
+ faddr = addr & (info.size - 1);
+ base = addr & ~(info.size - 1);
+
for (i = 0; i < info.region_cnt; i++) {
- if (info.region[i].start <= addr
- && addr < info.region[i].start + info.region[i].size)
+ if (info.region[i].start <= faddr
+ && faddr < info.region[i].start + info.region[i].size)
{
- uint32_t blk = (addr - info.region[i].start)
+ uint32_t blk = (faddr - info.region[i].start)
/ info.region[i].block_size
+ blk_offset;
- return info.region[i].start
+ return base + info.region[i].start
+ blk * info.region[i].block_size;
}
}
{
int i, step;
- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
- printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); /* 20 */
- printf("\b\b\b\b\b\b");
- printf("%06x/%06x |", done, total);
+ printf("\r%06x/%06x |", done, total);
step = (total + 19) / 20;
for (i = step; i <= total; i += step)
fputc('\n', stdout);
}
+static FILE *open_prep_read(const char *fname, long *size)
+{
+ FILE *f = fopen(fname, "rb");
+ if (!f) {
+ fprintf(stderr, "fopen %s: ", fname);
+ perror("");
+ exit(1);
+ }
+ if (*size <= 0) {
+ fseek(f, 0, SEEK_END);
+ *size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ }
+ if (*size <= 0) {
+ fprintf(stderr, "size of %s is %ld\n", fname, *size);
+ exit(1);
+ }
+ return f;
+}
+
+static const char *portname =
+#ifdef __APPLE__
+ "/dev/cu.usbserial-AL0254JM";
+#else
+ "/dev/ttyUSB0";
+#endif
+
static void usage(const char *argv0)
{
+ size_t i;
+
printf("usage:\n"
"%s [options]\n"
- " -d <ttydevice> (default /dev/ttyUSB0)\n"
+ " -d <ttydevice> (default %s)\n"
" -r <file> [size] dump the cart (default 4MB)\n"
- " -w <file> [size] flash the cart (file size)\n"
- " -e <size> erase (rounds to block size)\n"
- " -a <start_address> cart start address (default 0)\n"
- " -v verify written data\n"
- " -i get info about the flash chip\n"
- , argv0);
+ " -w <file> [size] program the flash (def. file size)\n"
+ " -s <file> [size] simple write (SRAM, etc, def. file size)\n"
+ " -e <size> erase (rounds to block size); can specify 'full'\n"
+ " -a <start_address> read/write start address (default 0)\n"
+ " -m <n> use an address mapper n, one of:\n"
+ , argv0, portname);
+ for (i = 1; i < sizeof(io_ops) / sizeof(io_ops[0]); i++)
+ printf(
+ " %zd: %s\n", i, io_ops[i].name);
+ printf( " -v verify written data\n"
+ " -i get info about the flash chip\n");
exit(1);
}
return argv[arg];
}
-static uint8_t g_block[0x10000];
-static uint8_t g_block2[0x10000];
+static long getarg_l(int argc, char *argv[], int arg)
+{
+ char *endp = NULL;
+ long r;
+
+ if (arg >= argc)
+ invarg(argc, argv, arg);
+ r = strtol(argv[arg], &endp, 0);
+ if (endp == NULL || *endp != 0)
+ invarg(argc, argv, arg);
+ return r;
+}
+
+// 32K to easily handle SNES LoROM
+static uint8_t g_block[0x8000];
+static uint8_t g_block2[sizeof(g_block)];
int main(int argc, char *argv[])
{
- const char *portname = "/dev/ttyUSB0";
const char *fname_w = NULL;
const char *fname_r = NULL;
+ const char *fname_ws = NULL;
long size_w = 0;
long size_r = 0;
+ long size_ws = 0;
long size_e = 0;
long size_v = 0;
long len, address_in = 0;
long a, a_blk, end;
int do_info = 0;
int do_verify = 0;
+ int write_step = 2;
FILE *f_w = NULL;
FILE *f_r = NULL;
+ FILE *f_ws = NULL;
uint8_t id[2] = { 0, 0 };
uint8_t cmd;
uint16_t rv;
if (!strcmp(argv[arg], "-r")) {
fname_r = getarg(argc, argv, ++arg);
if (arg + 1 < argc && argv[arg + 1][0] != '-') {
- size_r = strtol(argv[++arg], NULL, 0);
+ size_r = getarg_l(argc, argv, ++arg);
if (size_r <= 0)
invarg(argc, argv, arg);
}
if (!strcmp(argv[arg], "-w")) {
fname_w = getarg(argc, argv, ++arg);
if (arg + 1 < argc && argv[arg + 1][0] != '-') {
- size_w = strtol(argv[++arg], NULL, 0);
+ size_w = getarg_l(argc, argv, ++arg);
if (size_w <= 0)
invarg(argc, argv, arg);
}
continue;
}
+ if (!strcmp(argv[arg], "-s")) {
+ fname_ws = getarg(argc, argv, ++arg);
+ if (arg + 1 < argc && argv[arg + 1][0] != '-') {
+ size_ws = getarg_l(argc, argv, ++arg);
+ if (size_ws <= 0)
+ invarg(argc, argv, arg);
+ }
+ continue;
+ }
if (!strcmp(argv[arg], "-a")) {
- address_in = strtol(getarg(argc, argv, ++arg), NULL, 0);
- if (address_in < 0 || (address_in & 1))
+ address_in = getarg_l(argc, argv, ++arg);
+ if (address_in < 0)
invarg(argc, argv, arg);
continue;
}
if (!strcmp(argv[arg], "-e")) {
- size_e = strtol(getarg(argc, argv, ++arg), NULL, 0);
- if (size_e <= 0)
+ arg++;
+ if (!strcmp(getarg(argc, argv, arg), "full"))
+ size_e = -1;
+ else {
+ size_e = getarg_l(argc, argv, arg);
+ if (size_e <= 0)
+ invarg(argc, argv, arg);
+ }
+ continue;
+ }
+ if (!strcmp(argv[arg], "-m")) {
+ long v = getarg_l(argc, argv, ++arg);
+ if ((size_t)v >= sizeof(io_ops) / sizeof(io_ops[0]))
invarg(argc, argv, arg);
+ io = &io_ops[v];
+ if (v != 0)
+ write_step = 1;
continue;
}
if (!strcmp(argv[arg], "-v")) {
size_r = 0x400000;
if (fname_w) {
- f_w = fopen(fname_w, "rb");
- if (!f_w) {
- fprintf(stderr, "fopen %s: ", fname_w);
- perror("");
- return 1;
- }
- if (size_w <= 0) {
- fseek(f_w, 0, SEEK_END);
- size_w = ftell(f_w);
- fseek(f_w, 0, SEEK_SET);
- }
- if (size_w <= 0) {
- fprintf(stderr, "size of %s is %ld\n",
- fname_w, size_w);
- return 1;
- }
- if (size_e < size_w)
+ f_w = open_prep_read(fname_w, &size_w);
+ if (size_e == 0 && io->addrs_remapped)
+ size_e = -1;
+ if (size_e != -1 && size_e < size_w)
size_e = size_w;
if (do_verify)
size_v = size_w;
return 1;
}
+ if (fname_ws)
+ f_ws = open_prep_read(fname_ws, &size_ws);
+
setup(fd);
cmd = CMD_RD | PAR_SINGE | PAR_DEV_ID;
printf("flashkit id: %02x\n", id[0]);
set_delay(fd, 1);
- write_word(fd, 0, 0xf0); // flash reset
+
+ if (do_info || size_e || f_w)
+ io->write_bus(fd, 0, 0xf0); // flash reset
if (do_info || size_e)
read_info(fd);
- if (size_e) {
+ if (size_e == -1) {
+ printf("performing full erase..."); fflush(stdout);
+ flash_seq_erase_full(fd);
+ rv = ry_read(fd);
+ if (rv != 0xffff) {
+ fprintf(stderr, "\nerase error: %04x\n", rv);
+ return 1;
+ }
+ printf(" done.\n");
+ }
+ else if (size_e) {
// set_delay(fd, 0); // ?
a_blk = get_block_addr(address_in, 0);
end = address_in + size_e;
if (rv != 0xffff) {
fprintf(stderr, "\nerase error: %lx %04x\n",
a_blk, rv);
+ return 1;
}
a_blk = get_block_addr(a_blk, 1);
if (f_w != NULL) {
uint8_t b[2];
set_delay(fd, 0);
- printf("writing %ld bytes:\n", size_w);
- for (a = 0; a < size_w; a += 2) {
+ printf("flashing %ld bytes:\n", size_w);
+ for (a = 0; a < size_w; a += write_step) {
ssize_t r;
b[1] = 0xff;
- len = min(size_w - a, 2);
+ len = min(size_w - a, write_step);
r = fread(b, 1, len, f_w);
if (r != len) {
perror("\nfread");
return 1;
}
- flash_seq_write(fd, address_in + a, b);
+ io->flash_seq_write(fd, address_in + a, b);
- if (!(a & 0x3fe))
+ if (!(a & 0x3ff))
print_progress(a, size_w);
}
print_progress(a, size_w);
rv = ry_read(fd);
- if (rv != ((b[0] << 8) | b[1]))
+ if (write_step == 2 && rv != ((b[0] << 8) | b[1]))
fprintf(stderr, "warning: last bytes: %04x %02x%02x\n",
rv, b[0], b[1]);
rewind(f_w);
set_delay(fd, 1);
}
+ if (f_ws != NULL) {
+ printf("writing %ld bytes:\n", size_ws);
+ for (a = 0; a < size_ws; a += write_step) {
+ uint16_t b = 0xffff;
+ ssize_t r;
+
+ len = min(size_ws - a, write_step);
+ r = fread(&b, 1, len, f_ws);
+ if (r != len) {
+ perror("\nfread");
+ return 1;
+ }
+ if (write_step == 2)
+ b = htons(b);
+ io->write_bus(fd, address_in + a, b);
+
+ if (!(a & 0x3ff))
+ print_progress(a, size_ws);
+ }
+ print_progress(a, size_ws);
+ }
if (fname_r || size_v) {
long blks, blks_v, done, verify_diff = 0;
printf("reading %ld bytes:\n", max(size_r, size_v));
print_progress(0, blks * sizeof(g_block));
- set_addr(fd, address_in);
+ io->set_addr(fd, address_in);
for (done = 0; done < size_r || done < size_v; ) {
- read_block(fd, g_block, sizeof(g_block));
+ if (io->addrs_remapped)
+ io->set_addr(fd, address_in + done);
+ io->read_block(fd, g_block, sizeof(g_block));
if (f_r && done < size_r) {
len = min(size_r - done, sizeof(g_block));
if (fwrite(g_block, 1, len, f_r) != len) {