From 1bd8d58792dee33c4979707e5fb557685985eb88 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 6 Dec 2014 23:53:16 +0000 Subject: [PATCH] trs80: first cut at a WD1010 hard disk driver --- Kernel/platform-trs80/Makefile | 2 +- Kernel/platform-trs80/devfd.h | 2 +- Kernel/platform-trs80/devhd.c | 159 ++++++++++++++++++++++++++++++++ Kernel/platform-trs80/devhd.h | 9 ++ Kernel/platform-trs80/devices.c | 5 +- Kernel/platform-trs80/uzi.lnk | 1 + 6 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 Kernel/platform-trs80/devhd.c create mode 100644 Kernel/platform-trs80/devhd.h diff --git a/Kernel/platform-trs80/Makefile b/Kernel/platform-trs80/Makefile index 2803d028..e199e028 100644 --- a/Kernel/platform-trs80/Makefile +++ b/Kernel/platform-trs80/Makefile @@ -1,5 +1,5 @@ -CSRCS = devlpr.c devtty.c devfd.c +CSRCS = devlpr.c devtty.c devfd.c devhd.c CSRCS += devices.c main.c ASRCS = trs80.s crt0.s diff --git a/Kernel/platform-trs80/devfd.h b/Kernel/platform-trs80/devfd.h index 0ecc83b5..5f945073 100644 --- a/Kernel/platform-trs80/devfd.h +++ b/Kernel/platform-trs80/devfd.h @@ -12,4 +12,4 @@ uint16_t fd_operation(uint8_t *cmd, uint8_t *driveptr); uint16_t fd_motor_on(uint16_t drivesel); uint16_t fd_motor_off(uint16_t driveptr); -#endif /* __DEVRD_DOT_H__ */ +#endif /* __DEVFD_DOT_H__ */ diff --git a/Kernel/platform-trs80/devhd.c b/Kernel/platform-trs80/devhd.c new file mode 100644 index 00000000..cba79c55 --- /dev/null +++ b/Kernel/platform-trs80/devhd.c @@ -0,0 +1,159 @@ +/* + * WD1010 hard disk driver + */ + +#include +#include +#include +#include + +__sfr __at 0xC0 hd_wpbits; +__sfr __at 0xC1 hd_ctrl; +__sfr __at 0xC8 hd_data; +__sfr __at 0xC9 hd_precomp; /* W/O */ +__sfr __at 0xC9 hd_err; /* R/O */ +__sfr __at 0xCA hd_seccnt; +__sfr __at 0xCB hd_secnum; +__sfr __at 0xCC hd_cyllo; +__sfr __at 0xCD hd_cylhi; +__sfr __at 0xCE hd_sdh; +__sfr __at 0xCF hd_status; /* R/O */ +__sfr __at 0xCF hd_cmd; + +#define HDCMD_RESTORE 0x10 +#define HDCMD_READ 0x20 +#define HDCMD_WRITE 0x30 +#define HDCMD_VERIFY 0x40 +#define HDCMD_FORMAT 0x50 +#define HDCMD_INIT 0x60 +#define HDCMD_SEEK 0x70 + +/* Seek and restore low 4 bits are the step rate, read/write support + multi-sector mode but not all emulators do .. */ + +#define MAX_HD 4 + + +static uint8_t hd_waitready(void) +{ + uint8_t st; + do { + st = hd_status; + } while (st & 0x80); + return st; +} + +/* FIXME: move this to asm in _COMMONMEM and support banks and swap */ +static uint8_t hd_xfer(bool is_read, uint16_t addr) +{ + int ct = 256; + uint8_t *ptr = (uint8_t *)addr; + + if (!(hd_status & 0x08)) + return hd_status; + if (is_read) { + /* Ought to check DRQ per byte ? */ + while (ct--) { + *ptr++ = hd_data; + } + return 0; + } else { + while (ct--) { + hd_data = *ptr++; + } + return 0; + } +} + +/* + * We only support normal block I/O for the moment. We do need to + * add swapping! + */ + +static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag) +{ + blkno_t block; + uint16_t dptr; + int ct = 0; + int tries; + uint8_t err = 0; + uint8_t cmd = HDCMD_READ; + uint8_t head; + uint8_t sector; + + if (rawflag) + goto bad2; + + if (!is_read) + cmd = HDCMD_WRITE; + + dptr = (uint16_t) udata.u_buf->bf_data; + block = udata.u_buf->bf_blk; + + /* We assume 32 sectors per track for now. From our 512 byte + PoV that's 16 */ + + /* For our test purposes we use a disk with 32 sectors, 8 heads so + our blocks map out as ccccccccCCCCCCCCHHHSSSS */ + hd_seccnt = 1; + sector = ((block & 15) << 1) + 1; + hd_secnum = sector; + hd_cyllo = (block >> 7) & 0xFF; + hd_cylhi = (block >> 15) & 0xFF; + head = (block >> 4) & 7; + + hd_precomp = 0; /* FIXME */ + hd_sdh = 0x80 | head | (minor << 3); + + while (ct < 2) { + for (tries = 0; tries < 4; tries++) { + hd_cmd = cmd; + err = hd_waitready(); + if (err == 0) { + err = hd_xfer(is_read, dptr); + break; + } + if (tries > 1) { + hd_cmd = HDCMD_RESTORE; + hd_waitready(); + } + } + /* FIXME: should we try the other half and then bale out ? */ + if (tries == 3) + goto bad; + ct++; + dptr += 256; + hd_secnum = sector + 1; + } + return 1; +bad: + if (err & 1) + kprintf("hd%d: error %x\n", minor, hd_err); + else + kprintf("hd%d: status %x\n", minor, err); +bad2: + udata.u_error = EIO; + return -1; +} + +int hd_open(uint8_t minor, uint16_t flag) +{ + flag; + if (minor > MAX_HD) { + udata.u_error = ENODEV; + return -1; + } + return 0; +} + +int hd_read(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + flag; + return hd_transfer(minor, true, rawflag); +} + +int hd_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + flag; + return hd_transfer(minor, false, rawflag); +} diff --git a/Kernel/platform-trs80/devhd.h b/Kernel/platform-trs80/devhd.h new file mode 100644 index 00000000..5b99f00f --- /dev/null +++ b/Kernel/platform-trs80/devhd.h @@ -0,0 +1,9 @@ +#ifndef __DEVHD_DOT_H__ +#define __DEVHD_DOT_H__ + +/* public interface */ +int hd_read(uint8_t minor, uint8_t rawflag, uint8_t flag); +int hd_write(uint8_t minor, uint8_t rawflag, uint8_t flag); +int hd_open(uint8_t minor, uint16_t flag); + +#endif /* __DEVHD_DOT_H__ */ diff --git a/Kernel/platform-trs80/devices.c b/Kernel/platform-trs80/devices.c index c74fdd14..131482b9 100644 --- a/Kernel/platform-trs80/devices.c +++ b/Kernel/platform-trs80/devices.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -10,8 +11,8 @@ struct devsw dev_tab[] = /* The device driver switch table */ { /* 0: /dev/fd Floppy disc block devices */ { fd_open, no_close, fd_read, fd_write, no_ioctl }, - /* 1: /dev/hd Hard disc block devices (not yet) */ - { nxio_open, no_close, no_rdwr, no_rdwr, no_ioctl }, + /* 1: /dev/hd Hard disc block devices */ + { hd_open, no_close, hd_read, hd_write, no_ioctl }, /* 2: /dev/tty TTY devices */ { tty_open, tty_close, tty_read, tty_write, tty_ioctl }, /* 3: /dev/lpr Printer devices */ diff --git a/Kernel/platform-trs80/uzi.lnk b/Kernel/platform-trs80/uzi.lnk index 04d2a902..09c02712 100644 --- a/Kernel/platform-trs80/uzi.lnk +++ b/Kernel/platform-trs80/uzi.lnk @@ -18,6 +18,7 @@ timer.rel kdata.rel platform-trs80/devfd.rel platform-trs80/floppy.rel +platform-trs80/devhd.rel platform-trs80/devices.rel devio.rel filesys.rel -- 2.34.1