+
+/*
+ * fatread/write - load binary file to/from a dos filesystem
+ * read <d:/path/filename> <addr> [bytes [pos]]
+ * write <d:/path/filename> <addr> <bytes>
+ */
+command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ FATFS FatFs;
+ FIL File;
+ uint32_t addr;
+ unsigned long bytes;
+ unsigned long pos;
+ unsigned long bytes_rw;
+
+ bool dowrite = (argv[0][3] == 'w');
+ FRESULT res;
+ bool buserr = 0;
+ uint32_t timer;
+ uint8_t buffer[512];
+
+ (void) cmdtp; (void) flag;
+
+ if (argc < (dowrite ? 4 : 3))
+ return CMD_RET_USAGE;
+
+ addr = strtoul(argv[2], 0, 16);
+ if (addr >= MAX_MEMORY) {
+ printf_P(PSTR("address too high: 0x%0lx\n"), addr);
+ return CMD_RET_FAILURE;
+ }
+ if (argc > 3)
+ bytes = strtoul(argv[3], 0, 16);
+ else
+ bytes = MAX_MEMORY;
+ if (argc > 4)
+ pos = strtoul(argv[4], 0, 16);
+ else
+ pos = 0;
+
+ if (addr + bytes > MAX_MEMORY)
+ bytes = MAX_MEMORY - addr;
+
+ res = f_mount(&FatFs, argv[1], 0);
+ if (!res) {
+ res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS
+ : FA_READ );
+
+ if (!res) {
+ res = f_lseek(&File, pos);
+ if (!res) {
+ bytes_rw = 0;
+ timer = get_timer(0);
+ while (bytes) {
+ unsigned int cnt, br;
+
+ if (bytes >= sizeof buffer) {
+ cnt = sizeof buffer;
+ bytes -= sizeof buffer;
+ } else {
+ cnt = bytes; bytes = 0;
+ }
+ if (dowrite) {
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ }
+ z80_read_block(buffer, addr, cnt);
+ z80_bus_cmd(Release);
+ res = f_write(&File, buffer, cnt, &br);
+ if (res != FR_OK)
+ break;
+ } else {
+ res = f_read(&File, buffer, cnt, &br);
+ if (res != FR_OK)
+ break;
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ buserr = 1;
+ break;
+ }
+ z80_write_block(buffer, addr, br);
+ z80_bus_cmd(Release);
+ }
+ addr += br;
+
+ bytes_rw += br;
+ if (cnt != br) {
+ if (dowrite)
+ printf_P(PSTR("Disk full?\n"));
+ break;
+ }
+ if (ctrlc()) {
+ printf_P(PSTR("Abort\n"));
+ break;
+ }
+ }
+
+ FRESULT fr = f_close(&File);
+ if (!res)
+ res = fr;
+ timer = get_timer(timer);
+ printf_P(PSTR("%lu (0x%lx) bytes read/written with %lu bytes/sec.\n"),
+ bytes_rw, bytes_rw, timer ? (bytes_rw * 1000 / timer) : 0);
+ }
+ }
+ f_mount(NULL, argv[1], 0);
+ }
+
+ if (buserr)
+ my_puts_P(PSTR("Bus timeout\n"));
+ if (res)
+ put_rc(res);
+ if (buserr || res)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}