From 73aa7a33907457632ea8c00a27adbb3d9d18c49e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 3 Jul 2018 16:48:04 +0100 Subject: [PATCH] trs80m1: add initial exatron support We need something to develop tape code against and the stringy floppy is nice and easy on the Model I because it's a ROM full of nice helpers.. --- Kernel/platform-trs80m1/Makefile | 4 +- Kernel/platform-trs80m1/devgfx.c | 2 +- Kernel/platform-trs80m1/devices.c | 10 ++ Kernel/platform-trs80m1/devstringy.c | 185 +++++++++++++++++++++++++++ Kernel/platform-trs80m1/devstringy.h | 21 +++ Kernel/platform-trs80m1/fuzix.lnk | 2 + Kernel/platform-trs80m1/stringy.s | 95 ++++++++++++++ Kernel/platform-trs80m1/trs80.s | 2 + 8 files changed, 318 insertions(+), 3 deletions(-) create mode 100644 Kernel/platform-trs80m1/devstringy.c create mode 100644 Kernel/platform-trs80m1/devstringy.h create mode 100644 Kernel/platform-trs80m1/stringy.s diff --git a/Kernel/platform-trs80m1/Makefile b/Kernel/platform-trs80m1/Makefile index fb75cdb8..e878e477 100644 --- a/Kernel/platform-trs80m1/Makefile +++ b/Kernel/platform-trs80m1/Makefile @@ -1,10 +1,10 @@ CSRCS = devlpr.c devtty.c devfd.c devfd3.c devhd.c devgfx.c -CSRCS += devices.c main.c +CSRCS += devices.c main.c devstringy.c DISCARD_CSRCS = discard.c devhd_discard.c ASRCS = trs80.s trs80-bank.s crt0.s vtsupport.s -ASRCS += tricks.s commonmem.s floppy.s floppy3.s +ASRCS += tricks.s commonmem.s floppy.s floppy3.s stringy.s COBJS = $(CSRCS:.c=.rel) AOBJS = $(ASRCS:.s=.rel) diff --git a/Kernel/platform-trs80m1/devgfx.c b/Kernel/platform-trs80m1/devgfx.c index 24f459a4..d7feb4df 100644 --- a/Kernel/platform-trs80m1/devgfx.c +++ b/Kernel/platform-trs80m1/devgfx.c @@ -170,7 +170,7 @@ void gfx_init(void) max_mode = 1; displaymap[1] = 1; } else { - uint8_t *fb = 0x3C00; + uint8_t *fb = (uint8_t *)0x3C00; uint8_t c = *fb; *fb = 128; ioctrl = 0xB2; diff --git a/Kernel/platform-trs80m1/devices.c b/Kernel/platform-trs80m1/devices.c index 99ed5bc0..16d58296 100644 --- a/Kernel/platform-trs80m1/devices.c +++ b/Kernel/platform-trs80m1/devices.c @@ -11,6 +11,7 @@ #include #include #include +#include #include struct devsw dev_tab[] = /* The device driver switch table */ @@ -25,6 +26,14 @@ struct devsw dev_tab[] = /* The device driver switch table */ { lpr_open, lpr_close, no_rdwr, lpr_write, no_ioctl }, /* 4: /dev/mem etc System devices (one offs) */ { no_open, no_close, sys_read, sys_write, sys_ioctl }, + /* 5: reserved */ + { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 6: reserved */ + { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 7: reserved */ + { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 8: tape (for now - may move to 5 if lots of boxes have tape) */ + { tape_open, tape_close, tape_read, tape_write, tape_ioctl }, }; bool validdev(uint16_t dev) @@ -43,5 +52,6 @@ void floppy_setup(void) dev_tab[1].dev_open = fd3_open; dev_tab[1].dev_read = fd3_read; dev_tab[1].dev_write = fd3_write; + dev_tab[8].dev_open = nxio_open; } } diff --git a/Kernel/platform-trs80m1/devstringy.c b/Kernel/platform-trs80m1/devstringy.c new file mode 100644 index 00000000..a7c91db5 --- /dev/null +++ b/Kernel/platform-trs80m1/devstringy.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * Stringy tape wrapper. Note that the asm code uses the ROM which + * also uses some values in 0x40xx (40B1 and 401A in particular) + */ +static uint8_t fileid = 255; +static uint8_t mode; +static uint8_t inpos = 0; /* in position */ +static uint8_t inio = 0; +static int busy = 0; +uint8_t tape_err; + +static int tape_error(void) +{ + uint8_t a = tape_err; + tape_err = 0; + + /* EOF on read */ + if (a & 0x80) + return 0; + /* BREAK */ + if (a & 0x02) + udata.u_error = EINTR; + /* End of tape while writing */ + else if (a & 0x04) + udata.u_error = ENOSPC; + /* Buffer too small (read) */ + else if (a & 0x20) + udata.u_error = EINVAL; /* Not a good error for this really */ + else + udata.u_error = EIO; + kprintf("tape: error %x\n", a); + return -1; +} + +static int tape_rewind(void) +{ + if (!tape_op(0, TAPE_REWIND)) { + /* rewind */ + fileid = 1; + inpos = 0; + return 0; + } + return tape_error(); +} + +int tape_open(uint8_t minor, uint16_t flag) +{ + minor; flag; + + /* Check for the floppy tape ROM */ + if (*((uint16_t *)0x3034) != 0x3C3C) { + udata.u_error = ENODEV; + return -1; + } + if (busy) { + udata.u_error = EBUSY; + return -1; + } + + if (minor > 15 || tape_op(minor & 0x07, TAPE_SELECT)) { + udata.u_error = ENODEV; + return -1; + } + /* Can't open for mixed read/write at the same time */ + if (O_ACCMODE(flag) == O_RDWR) { + udata.u_error = EINVAL; + return -1; + } + mode = O_ACCMODE(flag); + + if ((minor & 0x08) || fileid == 255) + if (tape_rewind()) + return -1; + /* Only one drive can be used at a time */ + busy = 1; + inio = 0; + tape_err = 0; + return 0; +} + +int tape_close(uint8_t minor) +{ + minor; + if (mode == O_WRONLY) + if (tape_op(fileid, TAPE_CLOSEW)) + return tape_error(); + return 0; +} + +static int tape_rw(uint8_t op) +{ + if (!inpos) { + if (tape_op(fileid, TAPE_FIND) == 0) + inpos = 1; + else + return tape_error(); + + } + inio = 1; + udata.u_done = tape_op(fileid, op); + if (tape_err) + return tape_error(); + return udata.u_done; +} + +int tape_read(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + used(minor); + used(rawflag); + used(flag); + return tape_rw(TAPE_READ); +} + +int tape_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + used(minor); + used(rawflag); + used(flag); + return tape_rw(TAPE_WRITE); +} + +static struct mtstatus tapei = { + MT_TYPE_EXATRON, + 0, + ~0 +}; + +int tape_ioctl(uint8_t minor, uarg_t op, char *ptr) +{ + used(minor); + + switch(op) { + case MTSTATUS: + if (inpos) + tapei.mt_file = fileid; + else + tapei.mt_file = ~0; + return uput(&tapei, ptr, sizeof(tapei)); + } + /* Now calls we can only make when not mid stream */ + if (mode || inio) + goto bad; + + switch (op) { + case MTREWIND: + return tape_rewind(); + case MTSEEKF: + if (fileid > 99) + goto bad; + fileid++; + if (tape_op(fileid, TAPE_FIND)) + goto bad; + inpos = 1; + return 0; + case MTSEEKB: + if (fileid < 2) + goto bad; + fileid--; + if (tape_op(fileid, TAPE_FIND)) + goto bad; + inpos = 1; + return 0; + case MTERASE: + /* Erase from this point to the end of tape */ + if (fileid > 99) + goto bad; + if (tape_op(fileid, TAPE_ERASE)) + goto bad; + inpos = 0; + return 0; + default: + return -1; + } +bad: + udata.u_error = EINVAL; + return -1; +} diff --git a/Kernel/platform-trs80m1/devstringy.h b/Kernel/platform-trs80m1/devstringy.h new file mode 100644 index 00000000..d79cf45b --- /dev/null +++ b/Kernel/platform-trs80m1/devstringy.h @@ -0,0 +1,21 @@ + + +/* Must match the order in tape_op in the asm */ +#define TAPE_WRITE 0 +#define TAPE_READ 1 +#define TAPE_CLOSEW 2 +#define TAPE_REWIND 3 +#define TAPE_FIND 4 +#define TAPE_SELECT 5 +#define TAPE_ERASE 6 + +extern int tape_read(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int tape_write(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int tape_ioctl(uint8_t minor, uarg_t op, char *ptr); +extern int tape_open(uint8_t minor, uint16_t flag); +extern int tape_close(uint8_t minor); + +extern int tape_op(uint8_t id, uint8_t op); + + + diff --git a/Kernel/platform-trs80m1/fuzix.lnk b/Kernel/platform-trs80m1/fuzix.lnk index b07417cf..ccb011b8 100644 --- a/Kernel/platform-trs80m1/fuzix.lnk +++ b/Kernel/platform-trs80m1/fuzix.lnk @@ -27,6 +27,8 @@ platform-trs80m1/floppy3.rel platform-trs80m1/devhd.rel platform-trs80m1/devhd_discard.rel platform-trs80m1/devgfx.rel +platform-trs80m1/devstringy.rel +platform-trs80m1/stringy.rel platform-trs80m1/devices.rel devio.rel filesys.rel diff --git a/Kernel/platform-trs80m1/stringy.s b/Kernel/platform-trs80m1/stringy.s new file mode 100644 index 00000000..eb3a95f2 --- /dev/null +++ b/Kernel/platform-trs80m1/stringy.s @@ -0,0 +1,95 @@ + .module stringy + + .globl _tape_op + .globl _tape_err + + .include "kernel.def" + .include "../kernel.def" + + .area _COMMONMEM + + .globl _tape_op + + .globl go_slow + .globl go_fast + +_tape_op: + call go_slow + pop bc + pop de + push de ; file ID in D op in E + push bc + ld hl,(U_DATA__U_BASE) + ld bc,(U_DATA__U_COUNT) + xor a + ld (_tape_err),a + ld a,e + or a + jr z, write_op + dec a + jr z, read_op + dec a + jr z, closew_op + dec a + jr z, rewind_op + dec a + jr z, seekf_op + dec a + jr z, select_op + dec a + jr z, erase_op + ld hl,#0xFFFF + call go_fast + ret +find_op: + ld a,d + call 0x300F + jr tape_error +select_op: + ld a,d ; not a file ID but a drive ID this time + call 0x3012 + jr tape_error +seekf_op: + ld a,d + call 0x300F ; find file A +tape_error: + push af + call go_fast + pop af + ld hl,#0 ; return 0 if good or -1 if bad and save err + ret z + dec hl + ld (_tape_err),a + ret +closew_op: + ld a,d + ld bc,#0 + call 0x3027 ; Write an EOF and the marker for the next + jr tape_error ; file ID +rewind_op: + call 0x3000 ; Go back to start of tape (does not find + jr tape_error ; file 0 itself) +read_op: + call 0x3003 + push af + call go_fast + pop af + ld h,b + ld l,c ; actual bytes fetched + ret z +rwerr: + ld (_tape_err),a + ld hl,#0xffff + ret +write_op: + call 0x3006 + push af + call go_fast + pop af + ld hl,(U_DATA__U_COUNT) + ret z + jr rwerr +erase_op: + ld a,d + call 0x3024 + jr tape_error diff --git a/Kernel/platform-trs80m1/trs80.s b/Kernel/platform-trs80m1/trs80.s index 31c35ea4..da89ba7f 100644 --- a/Kernel/platform-trs80m1/trs80.s +++ b/Kernel/platform-trs80m1/trs80.s @@ -133,6 +133,8 @@ not_vg: ; The Model 3 sprinter type card uses port 95h the same way but ; also does automatic slow down when needed ; +; Only allowed to mess with AF +; go_slow: ld a,(_trs80_model) or a -- 2.34.1