summaryrefslogtreecommitdiff
path: root/avr/cmd_sd.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/cmd_sd.c')
-rw-r--r--avr/cmd_sd.c373
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;
+}