Skip to content

Commit

Permalink
zx128: Add support for the sinclair Microdrive
Browse files Browse the repository at this point in the history
Read only for the moment, but tested with the boot loader path and seems to
be doing the right thing. Something is buggy in the checksum logic either
of the mdv maker or the reader, not sure which yet.

Headers and blocks are correctly fetched, data blocks are split from the header
as they arrive to avoid double buffering.

The interface 1 ROM is not used at all (so we can use this from a cartridge
to load the rest of the OS)
  • Loading branch information
Alan Cox committed Dec 10, 2014
1 parent 7e6e530 commit 1da9b23
Show file tree
Hide file tree
Showing 3 changed files with 568 additions and 0 deletions.
98 changes: 98 additions & 0 deletions Kernel/platform-zx128/devmdv.c
@@ -0,0 +1,98 @@
/*
* Sinclair Interface One + Microdrives, mapped as if they were a
* floppy disk.
*
* First draft: motor control not yet made smart
*/

#include <kernel.h>
#include <kdata.h>
#include <printf.h>
#include <devmdv.h>

#define MAX_MDV 2 /* for now */

/* Should probably have a max and a max open to keep the maps managable */
static unsigned char mdvmap[MAX_MDV][256];
static uint8_t mdv_valid;

/* Used by the asm helpers */
uint8_t mdv_sector;
uint8_t *mdv_buf;
uint8_t mdv_hdr_buf[15];
uint16_t mdv_len;

static int mdv_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
{
int err;
irqflags_t irq;

if (rawflag)
goto bad;

mdv_motor_on(minor);
/* FIXME: support swap ? */
mdv_sector = mdvmap[minor][udata.u_buf->bf_blk];
mdv_buf = udata.u_buf->bf_data;

irq = di();
if (is_read)
err = mdv_bread();
else
err = mdv_bwrite();
irqrestore(irq);
mdv_motor_off();
return 0;
bad:
udata.u_error = EIO;
return -1;
}

int mdv_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
{
flag;
return mdv_transfer(minor, true, rawflag);
}

int mdv_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
{
flag;
return mdv_transfer(minor, false, rawflag);
}

int mdv_open(uint8_t minor, uint16_t flag)
{
uint8_t *t;
int err;

flag;

if (minor >= MAX_MDV) {
udata.u_error = ENODEV;
return -1;
}
t = tmpbuf();
mdv_buf = t;
mdv_sector = 1;
err = mdv_bread();
if (err) {
mdv_sector = 128;
err = mdv_bread();
if (err) {
kprintf("mdv_open: maps bad: %d\n", err);
udata.u_error = ENXIO;
return -1;
}
kprintf("mdv_open: had to use secondary map\n");
}
brelse(t);
mdv_valid |= 1 << minor;
return 0;
}

int mdv_close(uint8_t minor)
{
/* Simple approach for now */
mdv_valid &= ~(1 << minor);
return 0;
}
17 changes: 17 additions & 0 deletions Kernel/platform-zx128/devmdv.h
@@ -0,0 +1,17 @@
#ifndef __DEVMDV_DOT_H__
#define __DEVMDV_DOT_H__

/* public interface */
int mdv_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
int mdv_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
int mdv_open(uint8_t minor, uint16_t flag);
int mdv_close(uint8_t minor);

/* low level interface */
int mdv_motor_on(uint8_t drive);
int mdv_motor_off(void);
int mdv_bread(void);
int mdv_bwrite(void);

#endif /* __DEVMDV_DOT_H__ */

0 comments on commit 1da9b23

Please sign in to comment.