diff options
Diffstat (limited to 'avr/cmd_attach.c')
-rw-r--r-- | avr/cmd_attach.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/avr/cmd_attach.c b/avr/cmd_attach.c new file mode 100644 index 0000000..e9b5ccd --- /dev/null +++ b/avr/cmd_attach.c @@ -0,0 +1,160 @@ +/* + * (C) Copyright 2016 Leo C. <erbl259-lmu@yahoo.de> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +/* + * attach channels to devices + */ + +#include "common.h" +#include <string.h> +#include <stdbool.h> + +#include "command.h" +#include "z180-serv.h" +#include "getopt-min.h" + + +static const FLASH char * const FLASH rc_messages[] = { + FSTR("OK"), + FSTR("Unknown error"), + FSTR("Disk number out of range 0..7"), + FSTR("Disk allready attached"), + FSTR("Disk not attached"), + FSTR("File not found"), + FSTR("Not enough memory"), + FSTR("Error opening file"), + FSTR("File allready attached to other drive"), + }; + +static +void printerror(int rc, uint8_t unit, char *fn) +{ + if (rc < 0 || (unsigned) rc >= ARRAY_SIZE(rc_messages)) + rc = 1; + +#if GCC_BUG_61443 + printf_P(PSTR("Attachment of '%s' to dsk%d failed: "), fn, unit); + my_puts_P(rc_messages[rc]); + my_puts_P(PSTR("!\n")); +#else + printf_P(PSTR("Attachment of '%s' to dsk%d failed: %S!\n"), + fn, unit, rc_messages[rc]); +#endif +} + +/* + * attach [[options] [unit [diskfile]]] + * + * detach unit + * attach -d unit + * + * attach -o reattach unit + * attach -o reattach unit diskfile + * + * attach unit diskfile + * + */ + +command_ret_t do_attach(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + uint8_t unit; + char *filename = NULL; + bool detach = false; + bool detach_all = false; + drv_opt_t options = 0; + int res; + + (void) cmdtp; (void) flag; + + + if (argv[0][0] == 'd') { + /* we are called as 'detach' */ + detach = true; + } else if (argc == 1) { + /* no arguments */ + drv_list(); + return CMD_RET_SUCCESS; + } + + /* reset getopt() */ + optind = 0; + + int opt; + while ((opt = getopt(argc, argv, PSTR("darwo:"))) != -1) { + switch (opt) { + case 'd': + detach = true; + break; + case 'a': + detach_all = true; + break; + case 'r': + options |= DRV_OPT_RO; + break; + case 'w': + options &= ~DRV_OPT_RO; + break; + case 'o': + { + static const FLASH char delim[] = {", "}; + char *p = strtok_P(optarg, delim); + while (p != NULL) { + if (!strcmp_P(p, PSTR("ro"))) + options |= DRV_OPT_RO; + else if (!strcmp_P(p, PSTR("rw"))) + options &= ~DRV_OPT_RO; + else if (!strcmp_P(p, PSTR("debug"))) + options |= DRV_OPT_DEBUG; + else if (!strcmp_P(p, PSTR("nodebug"))) + options &= ~DRV_OPT_DEBUG; + else if (!strcmp_P(p, PSTR("reattach"))) + options |= DRV_OPT_REATTATCH; + else + return CMD_RET_USAGE; + + p = strtok_P(NULL, delim); + } + } + break; + default: /* '?' */ + return CMD_RET_USAGE; + } + } + + /* remaining arguments */ + argc -= optind; + if ( !( (argc == 0 && detach && detach_all) || + (argc == 1 && detach) || + (argc == 1 && (options & DRV_OPT_REATTATCH)) || + argc == 2) ) + return CMD_RET_USAGE; + + if (argc > 0 && ((strlen(argv[optind]) != 4) || + strncmp_P(argv[optind], PSTR("dsk"), 3) || + (unit = argv[optind][3] - '0') >= CONFIG_CPM_MAX_DRIVE)) { + + printf_P(PSTR("Unknown device: '%s'\n"), argv[optind]); + return CMD_RET_FAILURE; + } + + if (detach) { + if (detach_all) + for (uint8_t i = 0; i < CONFIG_CPM_MAX_DRIVE; i++) + drv_detach(i); + else + drv_detach(unit); + return CMD_RET_SUCCESS; + } + + if (argc == 2) + filename = argv[++optind]; + + res = drv_attach(unit, filename, options); + if (res) + printerror(res, unit, filename); + + return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS; +} |