diff options
Diffstat (limited to 'avr/cmd_sd.c')
-rw-r--r-- | avr/cmd_sd.c | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/avr/cmd_sd.c b/avr/cmd_sd.c new file mode 100644 index 0000000..344a197 --- /dev/null +++ b/avr/cmd_sd.c @@ -0,0 +1,373 @@ +/* + * (C) Copyright 2014, 2018 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "cmd_sd.h" + +#include "diskio.h" +#include "ff.h" +#include "eval_arg.h" +#include "print-utils.h" +#include "z80-if.h" + + +/* + * status <pd#> - Show socket status + * + */ +static +command_ret_t do_status(cmd_tbl_t *cmdtp, uint_fast8_t 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 <pd#> - Initialize disk + * + */ +static +command_ret_t do_init(cmd_tbl_t *cmdtp, uint_fast8_t 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) + cmd_error(CMD_RET_FAILURE, 0, PSTR("No disk")); + + 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 <pd#> - Show disk info + * + */ +static +command_ret_t do_info(cmd_tbl_t *cmdtp, uint_fast8_t 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 <pd#> [<sector> [count]] - Dump sector + * + */ +static +command_ret_t do_dump(cmd_tbl_t *cmdtp, uint_fast8_t 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) + cmd_error(CMD_RET_FAILURE, 0, PSTR("rc=%.2x"), res); + + 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, uint_fast8_t 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) { + z80_bus_request_or_exit(); + 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 <pd#> <sector> <memaddr> [<n>] - Write memory to disk + * + */ +static +command_ret_t do_write(cmd_tbl_t *cmdtp, uint_fast8_t 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++; + z80_bus_request_or_exit(); + 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 <pd#> - CTRL_SYNC + * + */ +static +command_ret_t do_ioctl_sync(cmd_tbl_t *cmdtp, uint_fast8_t 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; +} + + +cmd_tbl_t cmd_tbl_sd[] = { +CMD_TBL_ITEM( + status, 2, CTBL_RPT, do_status, + "Socket status", + "drive" +), +CMD_TBL_ITEM( + init, 2, CTBL_RPT, do_init, + "Initialize disk", + "drive" +), +CMD_TBL_ITEM( + info, 2, CTBL_RPT, do_info, + "Disk info", + "drive" +), +CMD_TBL_ITEM( + dump, CONFIG_SYS_MAXARGS, CTBL_RPT, do_dump, + "Dump sector(s)", + "drive [sector [count ]]" +), +CMD_TBL_ITEM( + read, 2, CTBL_RPT, do_read, + "Read disk sector(s) into meomory", + "drive [sector [count [memaddr]]]" +), +CMD_TBL_ITEM( + write, 2, CTBL_RPT, do_write, + "Write sector(s) from meomory to disk", + "drive [sector [count [memaddr]]]" +), +CMD_TBL_ITEM( + sync, 2, CTBL_RPT, do_ioctl_sync, + "Device control: SYNC", + "drive" +), + +CMD_TBL_ITEM( + help, CONFIG_SYS_MAXARGS, CTBL_RPT, 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, + NULL, +#ifdef CONFIG_SYS_LONGHELP + FSTR(""), +#endif /* CONFIG_SYS_LONGHELP */ + NULL, +#ifdef CONFIG_AUTO_COMPLETE + NULL, +#endif +}, +/* Mark end of table */ +CMD_TBL_END(cmd_tbl_sd) +}; + + +command_ret_t do_sd(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc UNUSED, char * const argv[] UNUSED) +{ + puts_P(PSTR("Huch?")); + return CMD_RET_USAGE; +} |