summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
authorLeo C2016-05-30 17:33:27 +0200
committerLeo C2016-05-30 17:33:27 +0200
commitcb4fb1ed02b59f798368a76f2596d7c24125e68a (patch)
tree77431b3fdfb4399782986f6263081d61314285d5 /avr
parentafc7c4b41af6cc2008bdc525f944e61f14cad93f (diff)
downloadz180-stamp-cb4fb1ed02b59f798368a76f2596d7c24125e68a.zip
New command(s): attach (and detach) - not fully working.
Diffstat (limited to 'avr')
-rw-r--r--avr/Tupfile2
-rw-r--r--avr/cmd_attach.c157
-rw-r--r--avr/cmd_boot.c2
-rw-r--r--avr/command_tbl.c17
-rw-r--r--avr/z180-serv.c132
5 files changed, 291 insertions, 19 deletions
diff --git a/avr/Tupfile b/avr/Tupfile
index 9bb0d11..be74c2d 100644
--- a/avr/Tupfile
+++ b/avr/Tupfile
@@ -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
index 0000000..e1a3b2c
--- /dev/null
+++ b/avr/cmd_attach.c
@@ -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;
+}
diff --git a/avr/cmd_boot.c b/avr/cmd_boot.c
index 0d98296..73f2cf3 100644
--- a/avr/cmd_boot.c
+++ b/avr/cmd_boot.c
@@ -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 */
diff --git a/avr/command_tbl.c b/avr/command_tbl.c
index 5dcbf1f..944c1c4 100644
--- a/avr/command_tbl.c
+++ b/avr/command_tbl.c
@@ -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,
diff --git a/avr/z180-serv.c b/avr/z180-serv.c
index e2a39d3..1bf76b4 100644
--- a/avr/z180-serv.c
+++ b/avr/z180-serv.c
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: GPL-2.0
*/
+#include "z180-serv.h"
#include "common.h"
#include <stdlib.h>
#include <string.h>
@@ -18,13 +19,12 @@
#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);