From 2e2876b75b982e96751378a57b6404f518d4c823 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 13 Oct 2018 14:42:07 +0100 Subject: [PATCH] trs80m1: more work on the FDC This gets us closer, unfortunately I've now broken the C compiler again. --- Kernel/platform-trs80m1/Makefile | 5 +- Kernel/platform-trs80m1/crt0.s | 2 +- Kernel/platform-trs80m1/devfd.c | 120 ++++++++++++++++++++++-------- Kernel/platform-trs80m1/devfd.h | 1 + Kernel/platform-trs80m1/devices.c | 2 +- Kernel/platform-trs80m1/floppy.s | 15 +++- Kernel/platform-trs80m1/floppy3.s | 23 +++--- 7 files changed, 118 insertions(+), 50 deletions(-) diff --git a/Kernel/platform-trs80m1/Makefile b/Kernel/platform-trs80m1/Makefile index e1d415d5..699b461e 100644 --- a/Kernel/platform-trs80m1/Makefile +++ b/Kernel/platform-trs80m1/Makefile @@ -1,5 +1,5 @@ -CSRCS = +CSRCS = devlpr.c devtty.c DISCARD_CSRCS = discard.c devhd_discard.c NSRCS = ../dev/net/net_native.c @@ -10,8 +10,7 @@ ASRCS += tricks.s commonmem.s floppy.s floppy3.s stringy.s ide.s # the asm helpers then can avoid another switch C2SRCS = buffers.c devfd.c devhd.c # And these so CODE1 is under 32K -C2SRCS += devices.c main.c devstringy.c devinput.c -C2SRCS += devlpr.c devtty.c devgfx.c +C2SRCS += devices.c main.c devstringy.c devinput.c devgfx.c DSRCS = ../dev/blkdev.c ../dev/devide.c ../dev/mbr.c DISCARD_DSRCS = ../dev/devide_discard.c diff --git a/Kernel/platform-trs80m1/crt0.s b/Kernel/platform-trs80m1/crt0.s index 924fc572..d9414c5b 100644 --- a/Kernel/platform-trs80m1/crt0.s +++ b/Kernel/platform-trs80m1/crt0.s @@ -76,4 +76,4 @@ stop: halt .area _STUBS stubs: - .ds 768 + .ds 768 \ No newline at end of file diff --git a/Kernel/platform-trs80m1/devfd.c b/Kernel/platform-trs80m1/devfd.c index f25eb4e6..c322a50d 100644 --- a/Kernel/platform-trs80m1/devfd.c +++ b/Kernel/platform-trs80m1/devfd.c @@ -3,10 +3,7 @@ * on both Model 1 and Model 3 * * Things To Do - * - Set sector size and shift values in the config calls - * - Use those in the I/O loop so we can do varying sector sizes * - Handle double sided media (need to consider heads in the loop) - * - Turn the step rate value into a step mask and use it in the asm code * - Teach the asm code about density * - Teach the asm code about double sided and maybe 128 byte sectors * - Rework density handling @@ -32,15 +29,15 @@ #define OPDIR_READ 1 #define OPDIR_WRITE 2 -#define FD_READ 0x80 /* 2797 needs 0x88, 1797 needs 0x80 */ -#define FD_WRITE 0xA0 /* Likewise A8 v A0 */ +#define FD_READ 0x80 +#define FD_WRITE 0xA0 static uint8_t motorct; /* Extern as they live in common */ extern uint8_t fd_map, fd_tab[MAX_FD]; extern uint8_t fd_selected; -extern uint8_t fd_cmd[7]; +extern uint8_t fd_cmd[9]; static struct fd_ops *fops; @@ -150,8 +147,39 @@ static struct fdcinfo fdc[MAX_FD] = { }, }; +/* Consider a struct of this plus the fdcinfo to make the referencing + nice ? */ +static uint8_t shift[MAX_FD] = { 2, 2, 2, 2 }; +static uint16_t size[MAX_FD] = { 512, 512, 512, 512 }; +static uint8_t step[MAX_FD] = { 3, 3, 3, 3 }; + /* Translate the drive into a selection. Assumes single sided on the M1 */ -static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x08 }; +static uint8_t selmap[MAX_FD] = { 0x01, 0x02, 0x04, 0x08 }; + +static uint8_t fd_select(uint8_t minor) +{ + uint8_t err = 0; + uint8_t tmp = 0; + /* Do we need to select the drive ? */ + if (trs80_model != TRS80_MODEL3 || fd_selected != minor) { + kputs("sel"); + /* Decide if we need double density */ + if (fdc[minor].features & FDF_DD) + tmp |= 0x80; + err = fops->fd_motor_on(selmap[minor]|tmp); + if (!err) + fd_selected = minor; + } + return err; +} + +static uint8_t do_fd_restore(uint8_t minor) +{ + if (fd_select(minor)) + return 0xFF; + kputs("res1"); + return fops->fd_restore(fd_tab + minor); +} static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) { @@ -166,46 +194,47 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) goto bad2; /* Do we need to select the drive ? */ - if (trs80_model != TRS80_MODEL3 || fd_selected != minor) { - uint8_t err; - uint8_t tmp = 0; - /* Decide if we need double density */ - if (f->features & FDF_DD) - tmp |= 0x80; - err = fops->fd_motor_on(selmap[minor]|tmp); - if (err) + if (fd_select(minor)) goto bad; - } /* If we don't know where the head on this drive is then force a seek */ - if (*driveptr == 0xFF) + if (*driveptr == 0xFF) { + kputs("res2"); if (err = fops->fd_restore(driveptr)) goto bad; + } - /* Adjust for the block size if raw I/O. For now hard code 512 byte - sectors but we need to sort this */ + /* Adjust for actual media sector size */ fd_map = rawflag; - if (rawflag && d_blkoff(BLKSHIFT)) + if (rawflag) { + if (d_blkoff(7 + shift[minor])) return -1; + } else { + udata.u_nblock <<= shift[minor]; + udata.u_block <<= shift[minor]; + } - /* We only deal with single sided 512 byte/sector media for the moment */ + /* We only deal with single sided media for the moment */ fd_cmd[0] = is_read ? FD_READ : FD_WRITE; fd_cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE; - fd_cmd[4] = ((uint16_t)udata.u_dptr) & 0xFF; - fd_cmd[5] = ((uint16_t)udata.u_dptr) >> 8; - fd_cmd[6] = 2; /* 0 128 1 256 2 512 : fixed for now */ + fd_cmd[6] = shift[minor]; + fd_cmd[7] = step[minor]; + fd_cmd[8] = f->precomp; while (ct < udata.u_nblock) { /* For each block we need to load we work out where to find it */ fd_cmd[1] = udata.u_block / f->sectors; fd_cmd[2] = udata.u_block % f->sectors; + fd_cmd[4] = ((uint16_t)udata.u_dptr) & 0xFF; + fd_cmd[5] = ((uint16_t)udata.u_dptr) >> 8; /* Some single density media has sectors numbered from zero */ if (!(f->config & FDC_SEC0)) fd_cmd[2]++; /* Reading 40 track media on an 80 track drive */ if (f->config & FDC_DSTEP) fd_cmd[1] <<= 1; + kputs("op"); /* Now try the I/O */ for (tries = 0; tries < 4 ; tries++) { err = fops->fd_op(driveptr); @@ -217,11 +246,10 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) } if (tries == 4) goto bad; - fd_cmd[5]++; /* Move on 256 bytes in the buffer */ - fd_cmd[5]++; /* Move on 256 bytes in the buffer */ + udata.u_dptr += size[minor]; ct++; } - return udata.u_nblock << 9; + return udata.u_nblock << (7 + shift[minor]); bad: kprintf("fd%d: error %x\n", minor, err); bad2: @@ -237,7 +265,7 @@ int fd_open(uint8_t minor, uint16_t flag) return -1; } /* No media ? */ - if (fops->fd_restore(fd_tab + minor) && !(flag & O_NDELAY)) { + if (do_fd_restore(minor) && !(flag & O_NDELAY)) { udata.u_error = EIO; return -1; } @@ -258,6 +286,8 @@ int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag) int fd_ioctl(uint8_t minor, uarg_t request, char *buffer) { + uint8_t s; + uint16_t w; switch(request) { case FDIO_GETCAP: return uput(fdcap + minor, buffer, sizeof(struct fdcinfo)); @@ -267,10 +297,35 @@ int fd_ioctl(uint8_t minor, uarg_t request, char *buffer) /* Ick.. but we are not portable code so we know how it packs */ if (uget(fdc + minor, buffer, 7)) return -1; - /*FIXME when we sort DS meida */ - fdc[minor].heads = 1; - /* TODO : steprate to masks */ fdc[minor].features &= fdcap[minor].features; + w = fdc[minor].features; + s = fdc[minor].steprate; + /* FIXME: WD1770 is different - consider undoubled model 1 */ + /* Check chip and clock details */ + /* WD1771 - 6 6 10 20 */ + if (s >= 20) + s = 3; + else if (s >= 10) + s = 2; + else + s = 0; + step[minor] = s; + if (!(fdc[minor].config & FDC_PRECOMP)) + fdc[minor].precomp = 255; /* Never precomp */ + switch(w &= FDF_SECSIZE) { + case 128: + s = 0; + break; + case 256: + s = 1; + break; + default: + case 512: + s = 2; + break; + } + shift[minor] = s; + size[minor] = w; /* Force reconfiguration */ fd_tab[minor] = 0xFF; fd_selected = 255; @@ -278,7 +333,8 @@ int fd_ioctl(uint8_t minor, uarg_t request, char *buffer) case FDIO_FMTTRK: return -1; case FDIO_RESTORE: - return fops->fd_restore(fd_tab + minor); + fd_selected = 255; /* Force a re-configure */ + return do_fd_restore(minor); } return -1; } diff --git a/Kernel/platform-trs80m1/devfd.h b/Kernel/platform-trs80m1/devfd.h index 0bc76af8..03ae5214 100644 --- a/Kernel/platform-trs80m1/devfd.h +++ b/Kernel/platform-trs80m1/devfd.h @@ -5,6 +5,7 @@ int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag); int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag); int fd_open(uint8_t minor, uint16_t flag); +int fd_ioctl(uint8_t minor, uarg_t request, char *buffer); /* low level interface */ uint8_t fd_restore(uint8_t *driveptr) __z88dk_fastcall; diff --git a/Kernel/platform-trs80m1/devices.c b/Kernel/platform-trs80m1/devices.c index 6bca6b4f..811f4547 100644 --- a/Kernel/platform-trs80m1/devices.c +++ b/Kernel/platform-trs80m1/devices.c @@ -19,7 +19,7 @@ struct devsw dev_tab[] = /* The device driver switch table */ /* 0: /dev/hd Hard disc block devices */ { hd_open, no_close, hd_read, hd_write, no_ioctl }, /* 1: /dev/fd Floppy disc block devices */ - { fd_open, no_close, fd_read, fd_write, no_ioctl }, + { fd_open, no_close, fd_read, fd_write, fd_ioctl }, /* 2: /dev/tty TTY devices */ { trstty_open, trstty_close, tty_read, tty_write, gfx_ioctl }, /* 3: /dev/lpr Printer devices */ diff --git a/Kernel/platform-trs80m1/floppy.s b/Kernel/platform-trs80m1/floppy.s index 3b5ea256..c2557e02 100644 --- a/Kernel/platform-trs80m1/floppy.s +++ b/Kernel/platform-trs80m1/floppy.s @@ -3,10 +3,12 @@ ; Based on the 6809 code ; ; FIXME: better drive spin up wait -; FIXME: tandy doubler +; FIXME: doublers ; FIXME: correct step rates (per drive ?) ; FIXME: precompensation ?? ; FIXME: 512 byte sector support +; FIXME: sector size setting +; FIXME: improve SD/DD handling ; .globl _fd_restore .globl _fd_operation @@ -81,6 +83,9 @@ TRACK .equ 1 SECTOR .equ 2 DIRECT .equ 3 ; 0 = read 2 = write 1 = status DATA .equ 4 +SIZE .equ 6 ; For now 1 = 256 2 = 512 +STEP .equ 7 ; Step rate +COMP .equ 8 ; Write compensation .area _COMMONMEM ; @@ -111,7 +116,8 @@ fdsetup: ; Need to seek the disk ; ld hl,#FDCREG - ld a, #0x18 ; seek FIXME: need to set step rate + ld a, #0x18 + or STEP(ix) ld (hl), a call waitcmd and #0x18 ; error bits @@ -288,7 +294,7 @@ _fd_restore: ld (FDCSEC), a xor a ld (FDCTRK), a - ld a, #0x0C + ld a, #0x0C ; FIXME: seek rate ?? ld (FDCREG), a ; restore ld a, #0xFF ld (hl), a ; Zap track pointer @@ -395,6 +401,7 @@ must_config: ld (LATCHD0), a ; Selects the actual disk we want ld d,a ; Save latch value rl c ; Bit 7 into C + ; FIXME: Tandy DD support ld a,#0xFE ; Figure out the density adc a,#0 ; FE or FF according to density di @@ -439,4 +446,4 @@ _fd_selected: _fd_tab: .db 0xFF, 0xFF, 0xFF, 0xFF _fd_cmd: - .ds 7 + .ds 9 diff --git a/Kernel/platform-trs80m1/floppy3.s b/Kernel/platform-trs80m1/floppy3.s index aa099c2e..7b6aecb3 100644 --- a/Kernel/platform-trs80m1/floppy3.s +++ b/Kernel/platform-trs80m1/floppy3.s @@ -57,6 +57,8 @@ SECTOR .equ 2 DIRECT .equ 3 ; 0 = read 2 = write 1 = status DATA .equ 4 SIZE .equ 6 ; For now 1 = 256 2 = 512 +STEP .equ 7 ; Step rate +COMP .equ 8 ; Write compensation .area _COMMONMEM ; @@ -122,6 +124,7 @@ waitdisk_l: ex (sp),hl in a, (FDCREG) ; read to reset int status bit 0, a + ld a,#0xff ret ; ; Set up and perform a disk operation @@ -172,14 +175,11 @@ patchfor256: ld a, TRACK(ix) ld (de), a ; save track -; cmp #22 ; FIXME -; jr nc, noprecomp -; ld a, (fdcctrl) -; or #0x10 ; Precomp on -; jr precomp1 -;noprecomp: + cp COMP(ix) ld a, (fdcctrl) -;precomp1: + jr nc, noprecomp + or #0x10 ; Precomp on +noprecomp: out (FDCCTRL), a ld a, SECTOR(ix) out (FDCSEC), a @@ -313,7 +313,7 @@ _fd3_restore: out (FDCSEC), a xor a out (FDCTRK), a - ld a, #0x0C + ld a, #0x0C ; FIXME: seek rate out (FDCREG), a ; restore ld a, #0xFF ld (hl), a ; Zap track pointer @@ -322,12 +322,14 @@ _fdr_wait: djnz _fdr_wait call waitdisk + ex de,hl ld l,a cp #0xff ret z and #0x99 ; Error bit from the reset ret nz - ld (hl), a ; Track 0 correctly hit (so 0) + ld (de), a ; Track 0 correctly hit (so 0) + ld l,a ret ; ; fd_operation3(uint8_t *driveptr) @@ -380,6 +382,7 @@ _fd3_motor_on: ; notsel: ld a, l + and #0x7F out (FDCCTRL), a out (FDCCTRL), a ; TRS80 erratum: model 4 gate array apparently needs this ld (fdcctrl), a @@ -391,6 +394,8 @@ notsel: ; ; All is actually good ; + ld a,#1 + ld (motor_running),a motor_was_on: ld hl, #0 ret -- 2.34.1