summaryrefslogtreecommitdiff
path: root/avr
diff options
context:
space:
mode:
authorLeo C2015-05-14 19:32:16 +0200
committerLeo C2015-05-14 19:32:16 +0200
commit5f7f3586b0444116d5c1340465ecae8d6daa2461 (patch)
tree3fc09da55b7cf7262bb87a296ee8d16138cbf193 /avr
parent089ca8cc69b7a112e1525743b3ffadc3f13556c3 (diff)
downloadz180-stamp-5f7f3586b0444116d5c1340465ecae8d6daa2461.zip
Add CP/M 3 file i/o (initial version)
Diffstat (limited to 'avr')
-rw-r--r--avr/cmd_fat.c4
-rw-r--r--avr/cmd_loadcpm3.c1
-rw-r--r--avr/z180-serv.c236
3 files changed, 239 insertions, 2 deletions
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 <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
#include <util/atomic.h>
#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;
+
}
/*--------------------------------------------------------------------------*/