]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
New command(s): attach (and detach) - not fully working.
authorLeo C <erbl259-lmu@yahoo.de>
Mon, 30 May 2016 15:33:27 +0000 (17:33 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Mon, 30 May 2016 15:33:27 +0000 (17:33 +0200)
avr/Tupfile
avr/cmd_attach.c [new file with mode: 0644]
avr/cmd_boot.c
avr/command_tbl.c
avr/z180-serv.c
include/getopt-min.h
include/z180-serv.h

index 9bb0d110fbf49ee2eed03f56f09af228d0577b02..be74c2db7e331763b28258ea99b8acd34b03f95a 100644 (file)
@@ -7,7 +7,7 @@ FATFS   = $(TOP)/fatfs/src/ff.c
 SRC            = main.c
 SRC            += cli.c cli_readline.c command.c command_tbl.c
 SRC            += cmd_help.c cmd_run.c cmd_boot.c cmd_misc.c
-SRC            += cmd_date.c cmd_mem.c cmd_gpio.c
+SRC            += cmd_date.c cmd_mem.c cmd_gpio.c cmd_attach.c
 SRC            += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c
 SRC            += env.c xmalloc.c con-utils.c print-utils.c getopt-min.c
 SRC            += timer.c serial.c i2c.c bcd.c pcf8583.c mmc.c
diff --git a/avr/cmd_attach.c b/avr/cmd_attach.c
new file mode 100644 (file)
index 0000000..e1a3b2c
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * (C) Copyright 2016 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+/*
+ * attach chanels to devices
+ */
+
+#include "common.h"
+#include <string.h>
+#include <stdbool.h>
+
+#include "command.h"
+#include "z180-serv.h"
+#include "getopt-min.h"
+//#include "print-utils.h"
+//#include "con-utils.h"
+//#include "timer.h"
+//#include "z80-if.h"
+//#include "debug.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 * 0
+               printf_P(PSTR("rc=%u FR_"), rc);
+               my_puts_P(rc_names[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;
+       drv_opt_t options = 0;
+       int res;
+
+       (void) cmdtp; (void) flag;
+
+
+       if (argv[0][0] == 'd')
+               /* we are called as 'detach' */
+               detach = true;
+
+       if (argc == 1) {
+               /* no arguments */
+               drv_list();
+               return CMD_RET_SUCCESS;
+       }
+
+       /* reset getopt() */
+       optind = 1;
+
+       int opt;
+       while ((opt = getopt(argc, argv, PSTR("drwo:"))) != -1) {
+               switch (opt) {
+               case 'd':
+                       detach = 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 ( !((detach && argc == 1) ||
+                       ((options & DRV_OPT_REATTATCH) && argc == 1) ||
+                       argc == 2) )
+               return CMD_RET_USAGE;
+
+       if ((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) {
+               res = 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;
+}
index 0d98296d21137238543aae5017c8584a47feaa11..73f2cf3e19c1999027e7fda1c6eb222e6952fb3c 100644 (file)
@@ -21,7 +21,7 @@
 #include "env.h"
 #include "con-utils.h"
 #include "z80-if.h"
-#include "z180-serv.h"
+#include "z180-serv.h" /* restart_z180_serv() */
 #include "debug.h"
 
 /* ugly hack to get Z180 loadfile into flash memory */
index 5dcbf1f1649dbfc72be643b512e62053349df3a1..944c1c4b0dcbbf5e5286168ed4ce645d91372471 100644 (file)
@@ -37,6 +37,7 @@ extern command_ret_t do_fat_ls(cmd_tbl_t *, int, int, char * const []);
 extern command_ret_t do_fat_rw(cmd_tbl_t *, int, int, char * const []);
 extern command_ret_t do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 extern command_ret_t do_source(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+extern command_ret_t do_attach(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
 #ifdef CONFIG_SYS_LONGHELP
 const FLASH char sd_help_text[] =
@@ -349,6 +350,22 @@ CMD_TBL_ITEM(
        "    - Write file to 'path/filename' on logical drive 'd' from RAM\n"
        "      starting at address 'addr'.\n"
 ),
+CMD_TBL_ITEM(
+       attach, CONFIG_SYS_MAXARGS,     1,      do_attach,
+       "attach filesystem image file to CP/M drive",
+       "[options] [dsk<n> <d:/path/filename>]\n"
+       "    - attach drive number <n> to diskfile <d:/path/filename>\n"
+       "attach -d dsk<n>\n"
+       "    - detach drive\n"
+       "attach\n"
+       "    - without arguments, list current assignments"
+),
+CMD_TBL_ITEM(
+       detach, 2,      1,      do_attach,
+       "detach file from CP/M drive",
+       "dsk<n>]\n"
+       "    - same as attach -d dsk<n>"
+),
 
 CMD_TBL_ITEM(
        help,   CONFIG_SYS_MAXARGS,     1,      do_help,
index e2a39d3fc4dee7f1999778ae4ee9a606fb73f6c7..1bf76b4d115df95d2b22e218501db99531ef7090 100644 (file)
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier:    GPL-2.0
  */
 
+#include "z180-serv.h"
 #include "common.h"
 #include <stdlib.h>
 #include <string.h>
 #include "z80-if.h"
 #include "debug.h"
 #include "print-utils.h"
-#include "z180-serv.h"
 #include "timer.h"
 #include "time.h"
 #include "bcd.h"
 #include "rtc.h"
 
-#define DEBUG_CPM_SDIO 0       /* set to 1 to debug */
+#define DEBUG_CPM_SDIO 1       /* set to 1 to debug */
 
 #define debug_cpmsd(fmt, args...)                                                          \
        debug_cond(DEBUG_CPM_SDIO, fmt, ##args)
@@ -207,22 +207,120 @@ void do_msg_get_set_time(uint8_t subf, int len, uint8_t * msg)
 
 /* ---------------------------------------------------------------------------*/
 
-/* TODO: Variable Disk Format */
-#define CONFIG_CPM_DISKSIZE            (8*1024*1024L)
-
-struct cpm_drive_s {
-       uint8_t drv;
-       uint8_t device;
-       char *img_name;
-       bool dirty;
-       FIL fd;
-};
-
 static uint8_t disk_buffer[CONFIG_CPM_BLOCK_SIZE];
 static struct cpm_drive_s drv_table[CONFIG_CPM_MAX_DRIVE];
 static int handle_cpm_drv_to;
 
 
+int drv_list(void)
+{
+       for (uint8_t i = 0; i < CONFIG_CPM_MAX_DRIVE; i++) {
+               struct cpm_drive_s * p = &drv_table[i];
+               if (p->img_name) {
+                       printf_P(PSTR("  dsk%d: %2s %3s attached to %s\n"), i,
+                                       p->opt&DRV_OPT_RO ? "RO":"RW", p->opt&DRV_OPT_DEBUG ? "DBG":"",
+                                       p->img_name);
+               }
+       }
+       return 0;
+}
+
+int drv_detach(uint8_t drv)
+{
+       if (drv < CONFIG_CPM_MAX_DRIVE) {
+               struct cpm_drive_s *p = &drv_table[drv];
+
+               debug_cpmsd("##  detach dsk%d: %s\n", drv,
+                               p->img_name ? p->img_name : "-");
+
+               if (p->img_name) {
+                       f_close(&p->fd);
+                       p->opt = 0;
+                       p->dirty = false;
+                       free(p->img_name);
+                       p->img_name = NULL;
+               }
+       }
+       return 0;
+}
+
+static int drv_find_file_attached(const char *fn)
+{
+       for (uint8_t i = 0; i < CONFIG_CPM_MAX_DRIVE; i++) {
+               struct cpm_drive_s *p = &drv_table[i];
+               if (p->img_name && !strcmp(fn, p->img_name)) {
+                       return i;
+               }
+       }
+       return -1;
+}
+
+int drv_attach(uint8_t drv, const char *filename, drv_opt_t options)
+{
+       int res;
+
+       if (drv >= CONFIG_CPM_MAX_DRIVE)
+               return AT_RANGE;
+
+       struct cpm_drive_s *p = &drv_table[drv];
+
+       if (options & DRV_OPT_REATTATCH) {
+               if (filename) {
+                       return AT_ERROR;
+               }
+
+               if (!p->img_name) {
+                       return AT_NOT;
+               }
+
+               p->opt = options & ~DRV_OPT_REATTATCH;
+
+               /* TODO: change options */
+
+       } else {
+
+               if (p->img_name)
+                       return AT_ALREADY;
+               if (drv_find_file_attached(filename) >= 0)
+                       return AT_OTHER;
+
+               p->opt = options & ~DRV_OPT_REATTATCH;
+
+               /* new attachment */
+
+               if ((p->img_name = strdup(filename)) == NULL)
+                       return AT_NOMEM;
+
+               res = f_open(&p->fd, p->img_name,
+                               FA_WRITE | FA_READ);
+
+               if (!res && f_size(&p->fd) < CONFIG_CPM_DISKSIZE) {
+                       unsigned int bw;
+
+                       debug_cpmsd("            expanding image file from %ld to %ld\n",
+                                       f_size(&p->fd), CONFIG_CPM_DISKSIZE);
+
+                       res = f_lseek(&p->fd, CONFIG_CPM_DISKSIZE-CONFIG_CPM_BLOCK_SIZE);
+                       if (!res) {
+                               memset(disk_buffer, 0xe5, CONFIG_CPM_BLOCK_SIZE);
+                               res = f_write(&p->fd, disk_buffer, CONFIG_CPM_BLOCK_SIZE, &bw);
+                               if (res || bw < CONFIG_CPM_BLOCK_SIZE) {
+                                       debug_cpmsd("               failed! res: %d, bytes written: %u\n",      res, bw);
+                               }
+                               p->dirty = true;
+                               bg_setstat(handle_cpm_drv_to, 1);
+                       }
+               }
+               if (res) {
+                       drv_detach(drv);
+                       return AT_OPEN;
+               }
+       }
+
+       return AT_OK;
+}
+
+
 int cpm_drv_to(int state)
 {
        static uint32_t ts;
@@ -294,13 +392,13 @@ void do_msg_cpm_login(uint8_t subf, int len, uint8_t * msg)
 
        /* Get relative drive number */
        drv = msg[1];
-       if ( drv>= CONFIG_CPM_MAX_DRIVE) {
+       if ( drv >= CONFIG_CPM_MAX_DRIVE) {
                return msg_cpm_result(subf, 0x02, res);
        }
 
-/*
-       uint32_t dph = ((uint32_t)msg[4] << 16) + ((uint16_t)msg[3] << 8) + msg[2];
-*/
+
+       drv_table[drv].dph = ((uint32_t)msg[4] << 16) + ((uint16_t)msg[3] << 8) + msg[2];
+
 
        if (drv_table[drv].img_name != NULL) {
                debug_cpmsd("## %7lu  close: '%s'\n", get_timer(0), drv_table[drv].img_name);
index 6495ebf21fa88dcdbc79841652352a4deac6d96b..e42aa7815f90dff89b694c045af2e54980c87656 100644 (file)
@@ -7,5 +7,6 @@ int getopt(                                             /* returns letter, '?', EOF */
        const FLASH char * optstring ); /* allowed args, e.g. "ab:c" */
 
 extern int optind;
+extern char *optarg;
 
 #endif /* GETOPT_MIN_H */
index 424318f540a8d2646427932934a15f36da825287..5385ecd9df21b43c1e79efc36fc9b3a440e4d73f 100644 (file)
@@ -7,7 +7,47 @@
 #ifndef Z180_SERV_H
 #define Z180_SERV_H
 
+#include <stdbool.h>
+#include "ff.h"
+
 void setup_z180_serv(void);
 void restart_z180_serv(void);
 
+
+/* CP/M drive interface */
+
+/* TODO: Variable Disk Format */
+#define CONFIG_CPM_DISKSIZE            (8*1024*1024L)
+
+typedef uint8_t drv_opt_t;
+
+#define DRV_OPT_RO                     (1<<0)  /* Drive is write protected */
+#define DRV_OPT_DEBUG          (1<<1)  /* Debug this drive */
+#define DRV_OPT_REATTATCH      (1<<7)  /* Change existing attachment */
+
+struct cpm_drive_s {
+       drv_opt_t       opt;
+       bool            dirty;
+       uint32_t        dph;
+       char            *img_name;
+       FIL                     fd;
+};
+
+/* Return codes */
+
+#define AT_OK          0
+#define AT_ERROR       1
+#define AT_RANGE       2
+#define AT_ALREADY     3
+#define AT_NOT         4
+#define AT_NOFILE      5
+#define AT_NOMEM       6
+#define AT_OPEN                7
+#define AT_OTHER       8
+
+
+int drv_list(void);
+int drv_detach(uint8_t drv);
+int drv_attach(uint8_t drv, const char *filename, drv_opt_t options);
+
 #endif /* Z180_SERV_H */