From 5f7f3586b0444116d5c1340465ecae8d6daa2461 Mon Sep 17 00:00:00 2001 From: Leo C Date: Thu, 14 May 2015 19:32:16 +0200 Subject: [PATCH] Add CP/M 3 file i/o (initial version) --- TODO.md | 2 +- avr/cmd_fat.c | 4 +- avr/cmd_loadcpm3.c | 1 + avr/z180-serv.c | 236 +++++++++++++++++++++++++++++++++++++++++++++ z180/init.180 | 7 +- 5 files changed, 244 insertions(+), 6 deletions(-) diff --git a/TODO.md b/TODO.md index 3ccd0d7..75c9679 100644 --- a/TODO.md +++ b/TODO.md @@ -4,7 +4,7 @@ TODO List - TODO: eliminate xmalloc - TODO: build time directory as lib - TODO: file search path. 'cd' command? - +- TODO: increase __malloc_margin to ? (now 0x20) ---------------------------------------------------- - Done: - command 'help ' should return success diff --git a/avr/cmd_fat.c b/avr/cmd_fat.c index 8ed7ae3..c5791e5 100644 --- a/avr/cmd_fat.c +++ b/avr/cmd_fat.c @@ -22,8 +22,8 @@ #include "timer.h" #include "debug.h" - -#define MAX_MEMORY (1ul << 20) +/* TODO: use memory size test function (cmd_mem.c) */ +#define MAX_MEMORY (1ul << 19) #define BUFFER_SIZE 512 diff --git a/avr/cmd_loadcpm3.c b/avr/cmd_loadcpm3.c index 267cad8..f2a30f1 100644 --- a/avr/cmd_loadcpm3.c +++ b/avr/cmd_loadcpm3.c @@ -67,6 +67,7 @@ command_ret_t do_loadcpm3(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg char *fname; FATFS FatFs; FIL File; + /* TODO: put CONFIG_PATH_CPM3SYS in flash */ char default_fname[] = CONFIG_PATH_CPM3SYS; unsigned int br; /* bytes read */ uint8_t buffer[RS]; diff --git a/avr/z180-serv.c b/avr/z180-serv.c index 9860175..c80daeb 100644 --- a/avr/z180-serv.c +++ b/avr/z180-serv.c @@ -5,12 +5,18 @@ */ #include "common.h" +#include +#include +#include #include #include "background.h" +#include "env.h" +#include "ff.h" #include "serial.h" #include "z80-if.h" #include "debug.h" +#include "print-utils.h" #include "z180-serv.h" /*--------------------------------------------------------------------------*/ @@ -96,6 +102,224 @@ void do_msg_echo(uint8_t subf, int len, uint8_t * msg) msg_xmit(1, 3, len, msg); } +/* ---------------------------------------------------------------------------*/ + +#define MAX_DEVICE 2 +#define MAX_DRIVE 2 +#define BLOCK_SIZE 512 + +struct fat_device_s { + FATFS dd; + bool active; +}; + + +struct cpm_drive_s { + uint8_t drv; + uint8_t device; + char *img_name; + FIL fd; +}; + +static uint8_t disk_buffer[BLOCK_SIZE]; +static struct fat_device_s device_table[MAX_DEVICE]; +static struct cpm_drive_s drv_table[MAX_DRIVE]; + +/* + db 2 ; disk command + ds 1 ; subcommand (login/read/write) + ds 1 ; @adrv (8 bits) +0 + ds 1 ; @rdrv (8 bits) +1 + ds 3 ; @xdph (24 bits) +2 +*/ + +void do_msg_cpm_login(uint8_t subf, int len, uint8_t * msg) +{ + + FRESULT res = 0; + uint8_t rc = 0; + uint8_t drv; + char *np; + uint8_t result_msg[3]; + + (void)subf; + + if (len != 5) { /* TODO: check adrv, rdrv */ + rc = 0x01; + goto out; + } + + debug("\n## login: %c:\n", msg[0]+'A'); + + + drv = msg[0]; + if ( drv>= MAX_DRIVE) { + rc = 0x02; + goto out; + } + + /* TODO: this has to be done somewhere globaly */ + + if (!device_table[0].active) { + f_mount(&device_table[0].dd, "0:", 0); + device_table[0].active = true; + } + if (!device_table[1].active) { + f_mount(&device_table[1].dd, "1:", 0); + device_table[1].active = true; + } + +/* + uint32_t dph = ((uint32_t)msg[4] << 16) + ((uint16_t)msg[3] << 8) + msg[2]; +*/ + + if (drv_table[drv].img_name != NULL) { + debug("## close: '%s'\n", drv_table[drv].img_name); + f_close(&drv_table[drv].fd); + free(drv_table[drv].img_name); + drv_table[drv].img_name = NULL; + } + + strcpy_P((char *)disk_buffer, PSTR("dsk0")); + disk_buffer[3] = msg[0] + '0'; + if (((np = getenv((char*)disk_buffer)) == NULL) || + ((drv_table[drv].img_name = strdup(np)) == NULL)) { + rc = 0x03; + goto out; + } + + + res = f_open(&drv_table[drv].fd, drv_table[drv].img_name, + FA_WRITE | FA_READ); + + debug("## open: '%s', (env: '%s'), res: %d\n", + drv_table[drv].img_name, disk_buffer, res); + +out: + + if (res) + rc |= 0x80; + + result_msg[0] = rc; + result_msg[1] = res; + result_msg[2] = res >> 8; + + if (rc) { + debug("## error rc: %.02x, res: %d\n", rc, res); + }; + + /* send result*/ + msg_xmit(2, subf, sizeof(result_msg), result_msg); +} + + +/* + db 2 ; disk command + ds 1 ; subcommand (login/read/write) + ds 1 ; @adrv (8 bits) +0 + ds 1 ; @rdrv (8 bits) +1 + ds 1 ; @cnt (8 bits) +2 + ds 2 ; @trk (16 bits) +3 + ds 2 ; @sect(16 bits) +5 + ds 3 ; phys. transfer addr +7 +*/ + +void do_msg_cpm_rw(uint8_t subf, int len, uint8_t * msg) +{ + uint8_t drv; + uint32_t addr; + uint32_t pos; + + bool dowrite = (subf == 2); + FRESULT res = 0; + uint8_t rc = 0; + bool buserr = 0; + uint8_t result_msg[3]; + + if (len != 10) { /* TODO: check adrv, rdrv */ + rc = 0x01; + goto out; + } + + drv = msg[0]; + if ( drv>= MAX_DRIVE) { + rc = 0x02; + goto out; + } + + addr = ((uint32_t)msg[9] << 16) + ((uint16_t)msg[8] << 8) + msg[7]; + + /* bytes = BLOCK_SIZE; */ /* TODO: multi sector count */ + pos = (((uint16_t)(msg[4] << 8) + msg[3]) * 8 + + ((uint32_t)(msg[6] << 8) + msg[5])) * BLOCK_SIZE; + + + debug("## cpm_rw: %s %c: trk: %4d, sec: %d, pos: 0x%.5lx, addr: 0x%.5lx\n", + dowrite ? "write" : " read", msg[0]+'A', + ((uint16_t)(msg[4] << 8) + msg[3]), msg[5], pos, addr); + + + + /* TODO: check bank boundary crossing */ + /* + if (addr + BLOCK_SIZE > MAX_MEMORY) + ... = MAX_MEMORY - addr; + */ + + + res = f_lseek(&drv_table[drv].fd, pos); + if (!res) { + unsigned int br; + + if (dowrite) { + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + buserr = 1; + } else { + z80_read_block(disk_buffer, addr, BLOCK_SIZE); + z80_bus_cmd(Release); + res = f_write(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &br); + if (!res) + res = f_sync(&drv_table[drv].fd); + } + } else { + res = f_read(&drv_table[drv].fd, disk_buffer, BLOCK_SIZE, &br); + if (res == FR_OK) { + if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) { + buserr = 1; + } else { + z80_write_block(disk_buffer, addr, br); + z80_bus_cmd(Release); + } + } + } + + if (br != BLOCK_SIZE) { + debug("## f_read res: %d, bytes rd/wr: %u\n", res, br); + dump_ram(disk_buffer, 0, 64, "Read Data"); + res = -1; + } + } + +out: + if (buserr) { + debug("Bus timeout\n"); + rc = 0x03; + } + if (res) + rc |= 0x80; + + result_msg[0] = rc; + result_msg[1] = res; + result_msg[2] = res >> 8; + + if (rc) { + debug("#### error rc: %.02x, res: %d\n", rc, res); + } + + /* send result*/ + msg_xmit(2, subf, sizeof(result_msg), result_msg); +} + const FLASH struct msg_item z80_messages[] = { @@ -108,6 +332,12 @@ const FLASH struct msg_item z80_messages[] = { 1, 2, 2, do_msg_echo}, + { 2, + 0, 0, + do_msg_cpm_login}, + { 2, + 1, 2, + do_msg_cpm_rw}, { 0xff, /* end mark */ 0, 0, 0}, @@ -258,6 +488,12 @@ void restart_z180_serv(void) for (int i = 0; i < NUM_FIFOS; i++) z80_memfifo_init(i, 0); bg_setstat(handle_msg_handling, 0); + + f_mount(NULL, "0:", 0); + device_table[0].active = false; + f_mount(NULL, "1:", 0); + device_table[1].active = false; + } /*--------------------------------------------------------------------------*/ diff --git a/z180/init.180 b/z180/init.180 index b1f835b..11f45ec 100644 --- a/z180/init.180 +++ b/z180/init.180 @@ -79,6 +79,7 @@ hwini0: db 3 ;count db rcr,CREFSH ;configure DRAM refresh db dcntl,INIWAITS ;wait states + db cbr,SYS$CBR db cbar,SYS$CBAR endif db 0 @@ -151,10 +152,10 @@ hw_reset: kstart: if CPU_Z180 - ld a,SYS$CBAR - out0 (cbar),a ld a,SYS$CBR out0 (cbr),a + ld a,SYS$CBAR + out0 (cbar),a endif ld sp,$stack ;01e1 @@ -220,7 +221,7 @@ wstart: if CPU_Z180 ; TODO: SYS$CBR -syscbr: db 1 +syscbr: db 0 endif ; -- 2.39.2