trs80: first cut at a floppy driver based upon the Dragon work
authorAlan Cox <alan@linux.intel.com>
Sat, 6 Dec 2014 22:00:25 +0000 (22:00 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 6 Dec 2014 22:00:25 +0000 (22:00 +0000)
Kernel/platform-trs80/Makefile
Kernel/platform-trs80/devfd.c
Kernel/platform-trs80/devfd.h
Kernel/platform-trs80/floppy.s [new file with mode: 0644]
Kernel/platform-trs80/trs80.s
Kernel/platform-trs80/trsfd.s [deleted file]
Kernel/platform-trs80/uzi.lnk

index b309f39..2803d02 100644 (file)
@@ -3,7 +3,7 @@ CSRCS = devlpr.c devtty.c devfd.c
 CSRCS += devices.c main.c
 
 ASRCS = trs80.s crt0.s
-ASRCS += tricks.s commonmem.s
+ASRCS += tricks.s commonmem.s floppy.s
 
 COBJS = $(CSRCS:.c=.rel)
 AOBJS = $(ASRCS:.s=.rel)
index caabc22..bc83883 100644 (file)
-/* 
- * TRS80 disk driver (TODO)
- *
- */
-
 #include <kernel.h>
 #include <kdata.h>
 #include <printf.h>
+#include <devfd.h>
 
-#define FD_TIMEOUT     100             /* FIXME */
-
-/* Floppy controller */
-__sfr __at 0xF0        fd_command;
-__sfr __at 0xF0        fd_status;
-#define FD_BUSY                1
-#define FD_DRQ         2
-
-#define CMD_RESET      0x0B
-#define CMD_SEEK       0x1B
-#define CMD_READ       0x8C
-#define CMD_WRITE      0xAC
-__sfr __at 0xF1 fd_track;
-__sfr __at 0xF2 fd_sector;
-__sfr __at 0xF3 fd_data;
-/* Drive select */
-__sfr __at 0xF4 fd_select;
-
-/* floppies. 26 128 byte sectors, not a nice way to use all of them in 512's */
-static int sectrack[16] = {
-    18
-};
-
-static uint8_t track[4];       /* only one controller register for all 4 drives */
-static uint8_t curdrive = 0xFF;
-static uint8_t fd_timer;
-
-static int fd_transfer(bool is_read, uint8_t minor, uint8_t rawflag);
-
-/* Replace with proper asm delay */
-static void nap(void)
-{
-    int i;
-    for(i=0;i<16;i++);
-}
-
-/* To write */
-static int fd_wait_idle(void)
-{
-    return 0xFF;
-}
-
-int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
-{
-    flag;
-    return fd_transfer(true, minor, rawflag);
-}
-
-int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
-{
-    flag;
-    return fd_transfer(false, minor, rawflag);
-}
-
-static uint8_t fd_seek(uint8_t track)
-{
-    uint8_t status;
-    fd_track = track;
-    nap();
-    fd_command = CMD_SEEK;
-    nap();
-    status = fd_wait_idle();
-    /* FIXME: bits of status */
-    return 0;
-}
-
-static uint8_t fd_writedata(uint8_t *dptr)
-{
-    uint8_t status;
-    irqflags_t irq;
-    uint8_t r;
-    uint16_t a;
-    
-    fd_command = CMD_WRITE;
-    nap();
-    do {
-        r = fd_status;
-        if (r & FD_DRQ) {
-            irq = di();
-            for (a = 0; a < 256; a++) {
-                fd_data = *dptr++;
-            }
-            irqrestore(irq);
-            status = fd_wait_idle();
-            /* bits of status */
-            return status & 0x5C;
-        }
-    }
-    while (r & FD_BUSY);
-    /* Went clear without asking for data */
-    return -1;
-}
-
-static uint8_t fd_readdata(uint8_t *dptr)
-{
-    uint8_t status;
-    irqflags_t irq;
-    uint8_t r;
-    unsigned int a;
-    
-    fd_command = CMD_READ;
-    nap();
-    do {
-        r = fd_status;
-        if (r & FD_DRQ) {
-            irq = di();
-            for (a = 0; a < 256; a++) {
-                *dptr++= fd_data;;
-            }
-            irqrestore(irq);
-            status = fd_wait_idle();
-            /* bits of status */
-            return status & 0x1C;
-        }
-    }
-    while (r & FD_BUSY);
-    /* Went clear without asking for data */
-    return -1;
-}
-
-static uint8_t fd_reset(void)
-{
-    uint8_t status;
-    
-    fd_command = CMD_RESET;
-    nap();
-    status = fd_wait_idle();
-    return 0;
-}
-
-static uint8_t fd_geom(int minor, blkno_t block)
-{
-    /* Turn block int track/sector 
-       and write to the controller.
-       Forced to do real / and % */
-    uint8_t trackw = block / sectrack[minor];
-    uint8_t sectorw = block % sectrack[minor];
-    uint8_t status = 0;
+#define MAX_FD 4
 
-    if (trackw != track[curdrive]) {
-        status = fd_seek(trackw);
-        track[curdrive] = trackw;
-    }
-    fd_sector = sectorw;
-    fd_timer = FD_TIMEOUT;
-    nap();
-    return status & 0x10;
-}
+#define OPDIR_NONE     0
+#define OPDIR_READ     1
+#define OPDIR_WRITE    2
 
-/* Deselect drive, motor off, may be called from an IRQ */
-static void fd_deselect(void)
-{
-    if (curdrive != 0xFF) {
-        track[curdrive] = fd_track;
-        curdrive = 0xFF;
-    }
-    fd_select = 0;
-}
+#define FD_READ                0x88    /* 2797 needs 0x88, 1797 needs 0x80 */
+#define FD_WRITE       0xA8    /* Likewise A8 v A0 */
 
-static void sdcc_bug(void)
-{
-}
+static uint8_t motorct;
+static uint8_t fd_selected = 0xFF;
+static uint8_t fd_tab[MAX_FD];
 
-static void fd_drivesel(uint8_t minor)
-{
-    irqflags_t irq = di();
-    uint8_t sdcc_tmp;
+/*
+ *     We only support normal block I/O for the moment. We do need to
+ *     add swapping!
+ */
 
-    if (minor != curdrive) {
-        if (curdrive != 0xFF)
-            fd_deselect();
-        track[curdrive] = fd_track;
-        /* nap needed anywhere ? */
-        fd_track = track[minor];
-        curdrive = minor;
-        /* FIXME: check and check for spin up times */
+static uint8_t selmap[4] = { 0x01, 0x02, 0x04, 0x08 };
 
-        /* Do this in two steps to stop SDCC 3.4 crashing and
-           we need the dummy call to stop it optimising it back into
-           the broken version */
-        sdcc_tmp = 1 << minor;
-        sdcc_bug();
-        fd_select = sdcc_tmp;
-    }
-    fd_timer = FD_TIMEOUT;
-    irqrestore(irq);
-}
-
-static int fd_transfer(bool is_read, uint8_t minor, uint8_t rawflag)
+static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
 {
     blkno_t block;
-    int block_xfer;     /* r/w return value (number of 512 byte blocks transferred) */
-    uint8_t *dptr;
-    int dlen;
+    uint16_t dptr;
     int ct = 0;
-    int st;
     int tries;
+    uint8_t err = 0;
+    uint8_t *driveptr = fd_tab + minor;
+    uint8_t cmd[6];
+
+    if(rawflag)
+        goto bad2;
 
-    if(rawflag) {
-        dlen = udata.u_count;
-        dptr = udata.u_base;
-        block = udata.u_offset >> 9;
-        block_xfer = dlen >> 8;                /* 256 byte blocks */
-    } else { /* rawflag == 0 */
-        dlen = 512;
-        dptr = udata.u_buf->bf_data;
-        block = udata.u_buf->bf_blk;
-        block_xfer = 2;
+    if (fd_selected != minor) {
+        uint8_t err = fd_motor_on(selmap[minor]);
+        if (err)
+            goto bad;
     }
 
-    fd_drivesel(minor);
-    while (ct < block_xfer) {
-        for (tries = 0; tries < 3; tries++) {
-            fd_geom(minor, block);
-            if (tries > 0)
-                fd_reset();
-            if (is_read)
-                st = fd_readdata(dptr);
-            else
-                st = fd_writedata(dptr);
-            if (st == 0)
+    dptr = (uint16_t)udata.u_buf->bf_data;
+    block = udata.u_buf->bf_blk;
+
+//    kprintf("Issue command: drive %d\n", minor);
+    cmd[0] = is_read ? FD_READ : FD_WRITE;
+    cmd[1] = block / 9;                /* 2 sectors per block */
+    cmd[2] = ((block % 9) << 1) + 1;   /*eww.. */
+    cmd[3] = is_read ? OPDIR_READ: OPDIR_WRITE;
+    cmd[4] = dptr & 0xFF;
+    cmd[5] = dptr >> 8;
+
+    while (ct < 2) {
+        for (tries = 0; tries < 4 ; tries++) {
+            err = fd_operation(cmd, driveptr);
+            if (err == 0)
                 break;
+            if (tries > 1)
+                fd_reset(driveptr);
         }
+        /* FIXME: should we try the other half and then bale out ? */
         if (tries == 3)
-            kprintf("fd%d: disk error %02X\n", st);
-        block++;
+            goto bad;
+        cmd[5]++;      /* Move on 256 bytes in the buffer */
+        cmd[2]++;      /* Next sector for 2nd block */
         ct++;
-        dptr += 256;
     }
-    return ct/2;
+    return 1;
+bad:
+    kprintf("fd%d: error %x\n", minor, err);
+bad2:
+    udata.u_error = EIO;
+    return -1;
 }
 
-int fd_open(uint8_t minor)
+int fd_open(uint8_t minor, uint16_t flag)
 {
-    if(minor >= 3 || !sectrack[minor]) {
+    flag;
+    if(minor > MAX_FD) {
         udata.u_error = ENODEV;
         return -1;
     }
     return 0;
 }
+
+int fd_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    flag;
+    return fd_transfer(minor, true, rawflag);
+}
+
+int fd_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+{
+    flag;
+    return fd_transfer(minor, false, rawflag);
+}
index da2a70c..0ecc83b 100644 (file)
@@ -6,4 +6,10 @@ 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);
 
+/* low level interface */
+uint16_t fd_reset(uint8_t *driveptr);
+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__ */
diff --git a/Kernel/platform-trs80/floppy.s b/Kernel/platform-trs80/floppy.s
new file mode 100644 (file)
index 0000000..324f610
--- /dev/null
@@ -0,0 +1,378 @@
+;
+;      Core floppy routines for the TRS80 1791 FDC
+;      Based on the 6809 code
+;
+;      FIXME: better drive spin up wait
+;      FIXME: double sided media
+;      FIXME: correct step rates (per drive ?)
+;      FIXME: precompensation
+;              - not on single density
+;              - track dependant for double density based on trsdos dir pos
+;
+;
+
+       .globl _fd_reset
+       .globl _fd_operation
+       .globl _fd_motor_on
+       .globl _fd_motor_off
+       .globl fd_nmi_handler
+
+FDCREG .equ    0xF0
+FDCTRK .equ    0xF1
+FDCSEC .equ    0xF2
+FDCDATA        .equ    0x43
+FDCCTRL        .equ    0xF4
+FDCINT .equ    0xE4
+;
+;      interrupt register reports 0x80 for interrut, 0x40 for drq
+;      (0x20 is the unrelated reset button)
+;
+
+;
+;      Structures we use
+;
+;
+;      Per disk structure to hold device state
+;
+TRKCOPY        .equ    0
+
+;
+;      Command issue
+;
+CMD    .equ    0
+TRACK  .equ    1
+SECTOR .equ    2
+DIRECT .equ    3               ; 0 = read 2 = write 1 = status
+DATA   .equ    4
+
+       .area   _COMMONMEM
+;
+;      Simple routine for pauses
+;
+nap:   dec     bc
+       ld      a, b
+       or      c
+       jr      nz, nap
+       ret
+;
+;      The motor off logic is driven from hardware
+;
+fd_nmi_handler:
+       xor     a
+       out     (FDCINT), a
+       ld      bc, #100
+       call    nap
+       pop     af              ; discard return address
+       jp      fdio_nmiout     ; and jump
+
+;
+;      Wait for the drive controller to become ready
+;      Preserve HL, DE
+;
+waitdisk:
+       ld      bc, #0
+waitdisk_l:
+       in      a, (FDCREG)
+       bit     0, a
+       ret     z
+       ;
+       ;       Keep poking fdcctrl to avoid a hardware motor timeout
+       ;
+       ld      a, (fdcctrl)
+       out     (FDCCTRL), a
+       djnz    waitdisk_l
+       dec     c
+       jr      nz, waitdisk_l
+       ld      a, #0xD0        ; reset
+       out     (FDCREG), a
+       ex      (sp), hl
+       ex      (sp),hl
+       ex      (sp),hl
+       ex      (sp),hl
+       in      a, (FDCREG)             ; read to reset int status
+       bit     0, a
+       ret
+;
+;      Set up and perform a disk operation
+;
+;      IX points to the command block
+;      HL points to the buffer
+;      DE points to the track reg copy
+;
+fdsetup:
+       ld      a, (de)
+       out     (FDCTRK), a
+       cp      TRACK(ix)
+       jr      z, fdiosetup
+
+       ;
+       ;       So we can verify
+       ;
+       ld      a, SECTOR(ix)
+       out     (FDCSEC), a
+       ;
+       ;       Need to seek the disk
+       ;
+       ld      a, #0x14        ; seek
+       out     (FDCREG), a
+       ex      (sp),hl
+       ex      (sp),hl
+       ex      (sp),hl
+       ex      (sp),hl
+       call    waitdisk
+       jr      nz, setuptimeout
+       and     #0x18           ; error bits
+       jr      z, fdiosetup
+       ; seek failed, not good
+setuptimeout:                  ; NE = bad
+       ld      a, #0xff        ; we have no idea where we are, force a seek
+       ld      (de), a         ; zap track info
+       ret
+;
+;      Head in the right place
+;
+fdiosetup:
+       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:
+       ld      a, (fdcctrl)
+;precomp1:
+       out     (FDCCTRL), a
+       ld      a, SECTOR(ix)
+       out     (FDCSEC), a
+       in      a, (FDCREG)     ; Clear any pending status
+
+       ld      a, CMD(ix)
+
+       ld      de, #0          ; timeout handling
+       
+       out     (FDCREG), a     ; issue the command
+       ex      (sp),hl ; give the FDC a moment to think
+       ex      (sp),hl
+       ex      (sp),hl
+       ex      (sp),hl
+       ld      a, DIRECT(ix)
+       dec     a
+       ld      a, (fdcctrl)
+       ld      d, a                    ; we need this in a register
+                                       ; to meet timing
+       set     6,d                     ; halt mode bit
+       jr      z, fdio_in
+       jr      nc, fdio_out
+;
+;      Status registers
+;
+fdxferdone:
+       ei
+fdxferdone2:
+       in      a, (FDCREG)
+       and     #0x19           ; Error bits + busy
+       bit     0, a            ; Wait for busy to drop, return in a
+       ret     z
+       ld      a, (fdcctrl)
+       out     (FDCCTRL), a
+       jr      fdxferdone2
+;
+;      Write to the disk - HL points to the target buffer
+;
+fdio_in:
+       ld      e, #0x16                ; bits to check
+       ld      bc, #FDCDATA            ; 256 bytes/sector, c is our port
+fdio_inl:
+       in      a, (FDCREG)
+       and     e
+       jr      z, fdio_in
+       ini
+       di
+       ld      a, d
+fdio_inbyte:
+       out     (FDCCTRL), a            ; stalls
+       ini
+       jr      nz, fdio_inbyte
+       jr      fdxferdone
+
+;
+;      Read from the disk - HL points to the target buffer
+;
+fdio_out:
+       ld      bc, #FDCDATA + 0xFF00   ; 256 bytes/sector, c is our port
+       ld      e, #0x76
+fdio_outl:
+       in      a, (FDCREG)             ; Wait for DRQ (or error)
+       and     e
+       jr      z, fdio_outl
+       outi                            ; Stuff byte into FDC while we think
+       di
+       in      a, (FDCREG)             ; No longer busy ??
+       rra
+       jr      nc, fdxferbad           ; Bugger... 
+       ld      a, #0xC0                ; Turn on magic floppy NMI interface
+       out     (FDCINT), a
+       ld      b, #50                  ; Spin for it
+spin1: djnz    spin1
+       ld      b, (hl)                 ; Next byte
+       inc     hl
+fdio_waitlock:
+       ld      a, d
+       out     (FDCCTRL), a            ; wait states on
+       in      a, (FDCREG)
+       and     e
+       jr      z, fdio_waitlock
+       out     (c), b
+       ld      a, d
+fdio_outbyte:
+       out     (FDCCTRL), a            ; stalls
+       outi
+       jr      fdio_outbyte
+fdio_nmiout:
+;
+;      Now tidy up
+;
+       jr      fdxferdone
+
+fdxferbad:
+       ld      a, #0xff
+       ret
+
+;
+;      C glue interface.
+;
+;      Because of the brain dead memory paging we dump the bits into
+;      kernel space always. The thought of taking an NMI while in the
+;      user memory and bank flipping to recover is just too odious !
+;
+
+;
+;      Reset to track 0, wait for the command then idle
+;
+;      fd_reset(uint8_t *drvptr)
+;
+_fd_reset:
+       pop     de
+       pop     hl
+       push    hl
+       push    de
+       ld      a, (fdcctrl)
+       out     (FDCCTRL), a
+       ld      a, #1
+       out     (FDCSEC), a
+       xor     a
+       out     (FDCTRK), a
+       out     (FDCREG), a     ; restore
+       dec     a
+       ld      (hl), a         ; Zap track pointer
+       ex      (sp),hl         ; give the FDC a moment to think
+       ex      (sp),hl
+       ex      (sp),hl
+       ex      (sp),hl
+       
+       call    waitdisk
+       cp      #0xff
+       ret     z
+       and     #0x10           ; Error bit from the reset
+       ret     nz
+       ld      (hl), a         ; Track 0 correctly hit
+       ret
+;
+;      fd_operation(uint16_t *cmd, uint16_t *drive)
+;
+;      The caller must ensure the drive has been selected and the motor is
+;      running.
+;
+_fd_operation:
+       pop     bc              ; return address
+       pop     hl              ; command
+       pop     de              ; drive track ptr
+       push    de
+       push    hl
+       push    bc
+       push    ix
+       push    hl
+       pop     ix
+       ld      l, DATA(ix)
+       ld      h, DATA+1(ix)
+       call    fdsetup         ; Set up for a command
+       ld      l, a
+       ld      h, #0
+       pop     ix
+       ret
+;
+;      C interface fd_motor_on(uint16_t drivesel)
+;
+;      Selects this drive and turns on the motors. Also pass in the
+;      choice of density
+;
+;      bits 0-3:       select that drive
+;      bit 4:          side (must rewrite each drive change)
+;      bit 5:          precompensation (not set here but in the I/O ops)
+;      bit 6:          synchronize I/O by stalling the CPU (don't set this)
+;      bit 7:          set for double density (MFM)
+;
+;
+_fd_motor_on:
+       pop     de
+       pop     hl
+       push    hl
+       push    de
+       ;
+       ;       Select drive B, turn on motor if needed
+       ;
+       ld      a,(motor_running)       ; nothing selected
+       or      a
+       jr      z, notsel
+
+       cp      l
+       jr      z,  motor_was_on
+;
+;      Select our drive
+;
+notsel:
+       ld      h, a            ; save state as it was
+       or      l
+       out     (FDCCTRL), a
+       out     (FDCCTRL), a    ; TRS80 erratum apparently needs this
+       ld      (fdcctrl), a
+       bit     4, h            ; FIXME - motor bit
+       jr      nz, motor_was_on
+       ld      bc, #0x7F00     ; Long delay (may need FE or FF for some disks)
+       call    nap
+       ; FIXME: longer motor spin up delay goes here (0.5 or 1 second)
+       
+       call    waitdisk
+;
+;      All is actually good
+;
+motor_was_on:
+       ld      hl, #0
+       ret
+
+;
+;      C interface fd_motor_off(void)
+;
+;      Turns off the drive motors, deselects all drives
+;
+_fd_motor_off:
+       ld      a, (motor_running)
+       or      a
+       ret     z
+       ; Should we seek to track 0 ?
+       in      a, (FDCCTRL)
+       and     #0xF0           ; clear drive bits
+       out     (FDCCTRL), a
+       xor     a
+       ld      (motor_running), a
+       ret
+
+       .area _COMMONDATA
+curdrive:
+       .db     0xff
+motor_running:
+       .db     0
+fdcctrl:
+       .db     0
+  
\ No newline at end of file
index 6247f35..8607135 100644 (file)
@@ -30,7 +30,7 @@
             .globl unix_syscall_entry
             .globl trap_illegal
             .globl outcharhex
-           .globl nmi_handler
+           .globl fd_nmi_handler
            .globl null_handler
 
             .include "kernel.def"
@@ -158,7 +158,7 @@ _program_vectors:
             ld (0x0001), hl
 
             ld (0x0066), a  ; Set vector for NMI
-            ld hl, #nmi_handler
+            ld hl, #fd_nmi_handler
             ld (0x0067), hl
 
 ;
diff --git a/Kernel/platform-trs80/trsfd.s b/Kernel/platform-trs80/trsfd.s
deleted file mode 100644 (file)
index 3d506a9..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-
-FDCSTAT                .equ    0xF0
-FDCA           .equ    0xF0
-FDCTRK         .equ    0xF1
-FDCSEC         .equ    0xF2
-FDCDAT         .equ    0xF3
-DRVSEL         .equ    0xF4
-
-;
-;      Write a command to the FDC then nap briefly while the
-;      FDC digests it
-;
-writecmd:
-               out (FDCA), a           ; off we go
-cmd_1:                                 ; wait for controller
-               ld b, 18
-               djnz cmd_1
-               ret
-
-
-;
-;      Set the desired track
-;
-;      B = the track we think we are on
-;      C = the sector we will want
-;      D = the track we will want
-;      E = the step rate (0-3) 
-;
-seekto:                call reselect
-               out (FDCTRK), b         ; current track
-               out (FDCSEC), c         ; sector we want
-               out (FDCDATA), d        ; track we want
-               ld a, b
-               cp d                    ; do we think we are there ?
-               ld b, 0x18              ; SEEK
-               jr z, seekto_1
-               ld b, 0x1C              ; SEEK with verify
-seekto_1:      ld a, b
-               or e                    ; step rate
-               call writecmd
-               ret
-
-;
-;      Perform a read transfer once we have been through the selection
-;      process
-;
-;      d = track
-;      
-;
-;
-read_xfer:     ld c, FDCTRK
-               out (c), d              ; track we want
-               
-               call writecmd
-
-               ld bc, FDCDAT           ; 256 bytes/sector, and load c with
-                                       ; our port
-               ld e, 0x16              ; mask of bits we are checking
-;               
-;      Wait for DRQ, and then block transfer the bytes
-;
-wait_drq:      in a, (FDCSTAT)
-               and e
-               jr z, wait_drq
-               ini
-               di
-               ld a, d
-wait_go:       out (DRVSEL), a         ; wait stating
-               ini                     ; byte in
-               jr nz, wait_go          ; repeat
-;
-;      Sector data has landed
-;
-               call fdcwait
-;      status in A
-               ret
-               
-
-fdcwait:
-               in a, (FDCSTAT)
-               bit 0, a                ; need a in return so don't use the rra
-                                       ; shortcut
-               ret z                   ; not busy ???
-               ld a, drvsel
-               out (DRVSEL), a
-               jr fdcwait
-
-
-select:                push bc
-               call reselect
-               ld b, a                 ; save the status
-               rlca                    
-               rla                     ; magic - move bits 6/4 into bits 7/4
-               sraa                    
-               and 0x90
-               ld c, a
-               bit 7, a                ; double density ?
-               jr z, nocomp
-               ld a, precomp_start
-               cp d                    ; track needs precomp ?
-               jr nc, nocomp
-               set 5, c
-               ld a, drivesel
-               and 0x0f
-               or c
-
-               out (DRVSEL), a         ; select drive
-               out (DRVSEL), a         ; in case the trash80 wasn't listening
-               
-               bit 1, b                ; delay time ?
-               call z, fdcspin         ; long
-               call fdcspin            ; short (1/2 long)
-               pop bc
-               ret
-
-fdcspin:       ld b, 0x7f
-               pause...
-               ret
-
-
-
-fdc_
-
index 78e488a..04d2a90 100644 (file)
@@ -17,6 +17,7 @@ platform-trs80/main.rel
 timer.rel
 kdata.rel
 platform-trs80/devfd.rel
+platform-trs80/floppy.rel
 platform-trs80/devices.rel
 devio.rel
 filesys.rel