summaryrefslogtreecommitdiff
path: root/avr/cmd_loadcpm3.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/cmd_loadcpm3.c')
-rw-r--r--avr/cmd_loadcpm3.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/avr/cmd_loadcpm3.c b/avr/cmd_loadcpm3.c
new file mode 100644
index 0000000..da1be37
--- /dev/null
+++ b/avr/cmd_loadcpm3.c
@@ -0,0 +1,172 @@
+/*
+ * (C) Copyright 2015 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "common.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "command.h"
+#include "env.h"
+#include "ff.h"
+#include "con-utils.h"
+#include "z80-if.h"
+#include "debug.h"
+
+
+#define RS 128 /* CP/M record size */
+
+/*
+ * Load Routine
+ *
+ * Input: addr = Page Address of load top
+ * len = Length in pages of module to read
+ *
+ */
+int load(FIL *File, uint32_t addr, uint8_t len)
+{
+ uint8_t buffer[RS];
+ unsigned int br; /* bytes read */
+ int res;
+
+ len *= 2; /* length in records of module */
+ //debug("## load: addr: 0x%.4X, records: 0x%.4X, (%u)\n", addr, len, len);
+
+ for (; len; len--) {
+ addr -= RS;
+ res = f_read(File, buffer, RS, &br);
+ if (res || br != RS) {
+ return 1;
+ }
+
+ if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
+ my_puts_P(PSTR("Bus timeout\n"));
+ return 2;
+ }
+ z80_write_block(buffer, addr, RS);
+ z80_bus_cmd(Release);
+ //debug("## written: 0x%.4X\n", addr);
+ }
+
+ return 0;
+}
+
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ uint16_t mem_top;
+ uint8_t res_len;
+ uint16_t bank_top;
+ uint8_t bank_len;
+ uint16_t osentry_addr = 0;
+ uint32_t common_base, banked_base;
+ char *fname;
+ FIL File;
+ /* TODO: put CONFIG_CPM3_SYSFILE in flash */
+ char default_fname[] = CONFIG_CPM3_SYSFILE;
+ unsigned int br; /* bytes read */
+ uint8_t buffer[RS];
+ int res;
+
+ (void) cmdtp; (void) flag;
+
+
+ common_base = getenv_ulong(PSTR(ENV_CPM3_COMMON_BASE), 16,
+ CONFIG_CPM3_COMMON_BASE);
+ banked_base = getenv_ulong(PSTR(ENV_CPM3_BANKED_BASE), 16,
+ CONFIG_CPM3_BANKED_BASE);
+
+ if (argc > 3)
+ banked_base = strtoul(argv[3], NULL, 16);
+ if (argc > 2)
+ banked_base = strtoul(argv[2], NULL, 16);
+
+ fname = getenv(PSTR(ENV_CPM3_SYSFILE));
+ if (argc > 2) {
+ fname = argv[2];
+ }
+ if (fname == NULL || *fname == '\0')
+ fname = default_fname;
+
+ res = f_open(&File, fname, FA_READ );
+ if (res) {
+ printf_P(PSTR("Error: failed to open '%s'\n"), fname);
+ return CMD_RET_FAILURE;
+ }
+
+ printf_P(PSTR("Loading: '%s'...\n"), fname);
+
+ /* read the load record */
+ res = f_read(&File, buffer, RS, &br);
+ if (res || br != RS)
+ goto out;
+
+ mem_top = buffer[0] << 8;
+ res_len = buffer[1];
+ bank_top = buffer[2] << 8;
+ bank_len = buffer[3];
+ osentry_addr = buffer[4] + (buffer[5] << 8);
+
+ /* read display info */
+ res = f_read(&File, buffer, RS, &br);
+ if (res || br != RS)
+ goto out;
+
+ /* print the info */
+ buffer[RS-1] = '$';
+ uint8_t *p = memchr(buffer, '$', RS);
+ *p = '\0';
+ my_puts((char *)buffer);
+
+ /* Main System Load */
+
+ /* Load Common Portion of System */
+ if ((res = load(&File, common_base + mem_top, res_len)) != 0)
+ goto out;
+
+ /* Load Banked Portion of System */
+ res = load(&File, banked_base + bank_top, bank_len);
+
+out:
+ f_close(&File);
+
+ if (res) {
+ printf_P(PSTR("Error: failed to read '%s'\n"), fname);
+ return CMD_RET_FAILURE;
+ } else {
+ if (res_len != 0) {
+ if (osentry_addr + common_base > 0xffff) {
+ z80_bus_cmd(Request);
+ if (z80_read(osentry_addr + common_base) == 0xc3) {
+ osentry_addr = z80_read(osentry_addr+common_base+1) +
+ (z80_read(osentry_addr + common_base+2) << 8);
+ }
+ z80_bus_cmd(Release);
+ if (banked_base + osentry_addr > 0xffff)
+ osentry_addr = 0;
+ }
+ setenv_hex(PSTR(ENV_STARTADDRESS), osentry_addr);
+ }
+ printf_P(PSTR("Loaded: Resident: "));
+ if (res_len != 0)
+ printf_P(PSTR("0x%.5lX-0x%.5lX, "),
+ (common_base + mem_top) - res_len*256,
+ (common_base + mem_top) - 1);
+ else
+ printf_P(PSTR(" - "));
+ printf_P(PSTR("Banked: "));
+ if (bank_len != 0)
+ printf_P(PSTR("0x%.5lX-0x%.5lX\n"),
+ (banked_base + bank_top) - bank_len*256,
+ (banked_base + bank_top) - 1);
+ else
+ printf_P(PSTR(" - \n"));
+
+ return CMD_RET_SUCCESS;
+ }
+}