From: Alan Cox Date: Mon, 1 Jun 2015 19:46:42 +0000 (+0100) Subject: devdw: move common bits to the dev/ directory X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=008dc3218d7c365ad0586c21824b67c0ba8c6b55;p=FUZIX.git devdw: move common bits to the dev/ directory --- diff --git a/Kernel/dev/devdw.c b/Kernel/dev/devdw.c new file mode 100644 index 00000000..b4168be9 --- /dev/null +++ b/Kernel/dev/devdw.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include + +#define MAX_DW 4 /* can be 255 */ + +#define DW_READ 0 +#define DW_WRITE 1 + +static uint8_t dw_tab[MAX_DW]; + +/* + * Block device glue for DriveWire + * + * DriveWire uses 256 byte sector transfers + */ + +static int dw_transfer(uint8_t minor, bool is_read, uint8_t rawflag) +{ + blkno_t block; + uint16_t dptr; + int nblock; + int tries; + uint8_t err; + uint8_t *driveptr = dw_tab + minor; + uint8_t cmd[6]; + uint8_t page; + irqflags_t irq; + + if (rawflag == 0) { + page = 0; + dptr = (uint16_t)udata.u_buf->bf_data; + block = udata.u_buf->bf_blk; + nblock = 2; + } else if (rawflag == 1) { + if (((uint16_t)udata.u_offset|udata.u_count) & BLKMASK) + goto bad2; + page = (uint8_t)udata.u_page; + dptr = (uint16_t)udata.u_base; + block = udata.u_offset >> 9; + nblock = udata.u_count >> 8; + } else if (rawflag == 2) { + page = (uint8_t)swappage; + dptr = (uint16_t)swapbase; + nblock = swapcnt >> 8; + block = swapblk; + } else + goto bad2; + +// kprintf("Issue command: drive %d\n", minor); + /* maybe mimicking floppy driver more than needed? */ + cmd[0] = is_read ? DW_READ : DW_WRITE; + cmd[1] = block >> 7; /* 2 sectors per block */ + cmd[2] = (block << 1) & 0xFF; + cmd[3] = dptr >> 8; + cmd[4] = dptr & 0xFF; + cmd[5] = page; + *driveptr = minor; /* pass minor (drive number) through here for now */ + + while (nblock--) { + for (tries = 0; tries < 4 ; tries++) { + // kprintf("dw_operation block %d left %d\n", block, nblock); + irq = di(); /* for now block interrupts for whole operation */ + err = dw_operation(cmd, driveptr); + irqrestore(irq); + if (err == 0) + break; + if (tries > 1) + dw_reset(driveptr); + } + /* FIXME: should we try the other half and then bail out ? */ + if (tries == 3) + goto bad; + cmd[3]++; /* Move on 256 bytes in the buffer */ + cmd[2]++; /* Next sector for 2nd block */ + if (cmd[2] == 0) + cmd[1]++; + } + return 1; +bad: + kprintf("dw%d: error %x\n", minor, err); +bad2: + udata.u_error = EIO; + return -1; +} + +/* FIXME: for bit-banger transport (not Becker) we should set up + the PIA at some point too */ + +int dw_open(uint8_t minor, uint16_t flag) +{ + used(flag); + if(minor >= MAX_DW) { + udata.u_error = ENODEV; + return -1; + } + return 0; +} + +int dw_read(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + used(flag); + return dw_transfer(minor, true, rawflag); +} + +int dw_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + used(flag); + return dw_transfer(minor, false, rawflag); +} + diff --git a/Kernel/dev/devdw.h b/Kernel/dev/devdw.h new file mode 100644 index 00000000..d7b93583 --- /dev/null +++ b/Kernel/dev/devdw.h @@ -0,0 +1,14 @@ +#ifndef __DEVDW_DOT_H__ +#define __DEVDW_DOT_H__ + +/* public interface */ +int dw_read(uint8_t minor, uint8_t rawflag, uint8_t flag); +int dw_write(uint8_t minor, uint8_t rawflag, uint8_t flag); +int dw_open(uint8_t minor, uint16_t flag); + +/* low level interface */ +uint8_t dw_reset(uint8_t *drive); +uint8_t dw_operation(uint8_t *cmd, uint8_t *drive); + +#endif /* __DEVDW_DOT_H__ */ +