trs80m1: more work on the FDC
authorAlan Cox <alan@linux.intel.com>
Sat, 13 Oct 2018 13:42:07 +0000 (14:42 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 13 Oct 2018 13:42:07 +0000 (14:42 +0100)
This gets us closer, unfortunately I've now broken the C compiler again.

Kernel/platform-trs80m1/Makefile
Kernel/platform-trs80m1/crt0.s
Kernel/platform-trs80m1/devfd.c
Kernel/platform-trs80m1/devfd.h
Kernel/platform-trs80m1/devices.c
Kernel/platform-trs80m1/floppy.s
Kernel/platform-trs80m1/floppy3.s

index e1d415d..699b461 100644 (file)
@@ -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
 
index 924fc57..d9414c5 100644 (file)
@@ -76,4 +76,4 @@ stop:         halt
 
                .area _STUBS
 stubs:
-               .ds 768
+               .ds 768
\ No newline at end of file
index f25eb4e..c322a50 100644 (file)
@@ -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
 #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;
 }
index 0bc76af..03ae521 100644 (file)
@@ -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;
index 6bca6b4..811f454 100644 (file)
@@ -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 */
index 3b5ea25..c2557e0 100644 (file)
@@ -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
index aa099c2..7b6aecb 100644 (file)
@@ -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