/* * (C) Copyright 2014 Leo C. * * SPDX-License-Identifier: GPL-2.0+ */ #include "common.h" //#include #include "command.h" #include "diskio.h" #include "ff.h" #include "eval_arg.h" #include "print-utils.h" #include "z80-if.h" /* * status - Show socket status * */ static command_ret_t do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { DSTATUS res; BYTE dev; (void) cmdtp; (void) flag; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); res = disk_status(dev); printf_P(PSTR("Socket status: %02x\n"), res); return CMD_RET_SUCCESS; } /* * init - Initialize disk * */ static command_ret_t do_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { DSTATUS res; BYTE dev; (void) cmdtp; (void) flag; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); if (disk_status(dev) & STA_NODISK) { printf_P(PSTR("No Disk\n")); return CMD_RET_FAILURE; } res = disk_initialize(dev); printf_P(PSTR("rc=%.2x\n"), res); if (res & (STA_NODISK | STA_NOINIT)) return CMD_RET_FAILURE; return CMD_RET_SUCCESS; } /* * info - Show disk info * */ static command_ret_t do_info(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { DSTATUS res; BYTE dev; union { unsigned char uca[64]; unsigned long ul; unsigned char uc; } dat; (void) cmdtp; (void) flag; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); res = disk_status(dev); if (res & (STA_NODISK | STA_NOINIT)) { printf_P(res & STA_NODISK ? PSTR("No disk\n") : PSTR("Not initialized\n")); return CMD_RET_FAILURE; } if (disk_ioctl(dev, GET_SECTOR_COUNT, &dat.ul) == RES_OK) printf_P(PSTR("Drive size: %lu sectors\n"), dat.ul); if (disk_ioctl(dev, GET_BLOCK_SIZE, &dat.ul) == RES_OK) printf_P(PSTR("Erase block: %lu sectors\n"), dat.ul); if (disk_ioctl(dev, MMC_GET_TYPE, &dat.uc) == RES_OK) printf_P(PSTR("Card type: %u\n"), dat.uc); if (disk_ioctl(dev, MMC_GET_CSD, dat.uca) == RES_OK) dump_ram(dat.uca, 0, 16, "CSD:"); if (disk_ioctl(dev, MMC_GET_CID, dat.uca) == RES_OK) dump_ram(dat.uca, 0, 16, "CID:"); if (disk_ioctl(dev, MMC_GET_OCR, dat.uca) == RES_OK) dump_ram(dat.uca, 0, 4, "OCR:"); if (disk_ioctl(dev, MMC_GET_SDSTAT, dat.uca) == RES_OK) dump_ram(dat.uca, 0, 64, "SD Status:"); return CMD_RET_SUCCESS; } /* * dump [ [count]] - Dump sector * */ static command_ret_t do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { static BYTE dev_last; static DWORD sec_last; BYTE buffer[FF_MAX_SS]; char header[20]; DRESULT res; BYTE dev; DWORD sec; UINT count; (void) cmdtp; (void) flag; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); if (dev != dev_last) sec_last = 0; sec = sec_last; count = 1; if ((flag & CMD_FLAG_REPEAT) == 0) { /* If another parameter, it is the sector to dump. */ if (argc > 2) sec = eval_arg(argv[2], NULL); if (argc > 3) count = (UINT) eval_arg(argv[3], NULL); } for ( ; count; count--, sec++) { res = disk_read(dev, buffer, sec, 1); if (res) { printf_P(PSTR("rc=%.2x\n"), res); return CMD_RET_FAILURE; } sprintf_P(header, PSTR("Sector: %lu"), sec); dump_ram(buffer, 0, FF_MAX_SS, header); } dev_last = dev; sec_last = sec; return CMD_RET_SUCCESS; } /* * read drive sector count memaddr - Read disk into memory * */ static command_ret_t do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { DRESULT res; BYTE dev; DWORD sec; uint32_t addr; int count, nr; BYTE buffer[FF_MAX_SS]; static DWORD sec_last; static uint32_t addr_last; (void) cmdtp; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); sec = sec_last; count = 1; addr = addr_last; if ((flag & CMD_FLAG_REPEAT) == 0) { /* If another parameter, it is the sector to dump. */ if (argc > 2) sec = eval_arg(argv[2], NULL); if (argc > 3) count = eval_arg(argv[3], NULL); if (argc > 4) addr = eval_arg(argv[4], NULL); } for (nr = 0; nr < count;) { nr++; if ((res = disk_read(dev, buffer, sec, 1)) == RES_OK) { if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } z80_write_block(buffer, addr /*+ base*/, FF_MAX_SS); z80_bus_cmd(Release); sec++; addr += FF_MAX_SS; } else break; } printf_P(PSTR("Read %d sector(s), rc=%.2x.\n"), nr, res); if (res) printf_P(PSTR("Last sector not written!\n")); sec_last = sec; addr_last = addr; return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS; } /* * write [] - Write memory to disk * */ static command_ret_t do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { DRESULT res; BYTE dev; DWORD sec; uint32_t addr; int count, nr; BYTE buffer[FF_MAX_SS]; static DWORD sec_last; static uint32_t addr_last; (void) cmdtp; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); sec = sec_last; addr = addr_last; count = 1; if ((flag & CMD_FLAG_REPEAT) == 0) { /* If another parameter, it is the sector to dump. */ if (argc > 2) sec = eval_arg(argv[2], NULL); if (argc > 3) count = eval_arg(argv[3], NULL); if (argc > 4) addr = eval_arg(argv[4], NULL); } for (nr = 0; nr < count;) { nr++; if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { my_puts_P(PSTR("Bus timeout\n")); return CMD_RET_FAILURE; } z80_read_block(buffer, addr /*+ base*/, FF_MAX_SS); z80_bus_cmd(Release); res = disk_write(dev, buffer, sec, 1); if (res != RES_OK) break; sec++; addr += FF_MAX_SS; } printf_P(PSTR("%d sector(s) written, rc=%.2x.\n"), nr, res); sec_last = sec; addr_last = addr; return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS; } /* * Disk ioctl * sync - CTRL_SYNC * */ static command_ret_t do_ioctl_sync(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { BYTE dev; (void) cmdtp; (void) flag; if (argc < 2) return CMD_RET_USAGE; dev = (BYTE) eval_arg(argv[1], NULL); printf_P(PSTR("rc=%.2x\n"), disk_ioctl(dev, CTRL_SYNC, 0)); return CMD_RET_SUCCESS; } static command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); cmd_tbl_t cmd_sd_sub[] = { CMD_TBL_ITEM( status, 2, 1, do_status, "Socket staus", "drive" ), CMD_TBL_ITEM( init, 2, 1, do_init, "Initialize disk", "drive" ), CMD_TBL_ITEM( info, 2, 1, do_info, "Disk info", "drive" ), CMD_TBL_ITEM( dump, CONFIG_SYS_MAXARGS, 1, do_dump, "Dump sector(s)", "drive [sector [count ]]" ), CMD_TBL_ITEM( read, 2, 1, do_read, "Read disk sector(s) into meomory", "drive [sector [count [memaddr]]]" ), CMD_TBL_ITEM( write, 2, 1, do_write, "Write sector(s) from meomory to disk", "drive [sector [count [memaddr]]]" ), CMD_TBL_ITEM( sync, 2, 1, do_ioctl_sync, "Device control: SYNC", "drive" ), CMD_TBL_ITEM( help, CONFIG_SYS_MAXARGS, 1, do_help, "Print sub command description/usage", "\n" " - print brief description of all sub commands\n" "sd help command ...\n" " - print detailed usage of sub cmd 'command'" ), /* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */ {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help, FSTR("Alias for 'help'"), #ifdef CONFIG_SYS_LONGHELP FSTR(""), #endif /* CONFIG_SYS_LONGHELP */ #ifdef CONFIG_AUTO_COMPLETE 0, #endif }, }; static command_ret_t do_help(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { return _do_help(cmd_sd_sub, ARRAY_SIZE(cmd_sd_sub), cmdtp, flag, argc, argv); } command_ret_t do_sd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { cmd_tbl_t *cp; if (argc < 2) return CMD_RET_USAGE; /* drop initial "sd" arg */ argc--; argv++; cp = find_cmd_tbl(argv[0], cmd_sd_sub, ARRAY_SIZE(cmd_sd_sub)); if (cp) return cp->cmd(cmdtp, flag, argc, argv); return CMD_RET_USAGE; }