summaryrefslogtreecommitdiff
path: root/avr/z180-serv.c
diff options
context:
space:
mode:
Diffstat (limited to 'avr/z180-serv.c')
-rw-r--r--avr/z180-serv.c132
1 files changed, 115 insertions, 17 deletions
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);