fdc765, zx+3: Now working on the +3
authorAlan Cox <alan@linux.intel.com>
Mon, 3 Dec 2018 14:57:19 +0000 (14:57 +0000)
committerAlan Cox <alan@linux.intel.com>
Mon, 3 Dec 2018 14:57:19 +0000 (14:57 +0000)
- Fix assorted bugs
- Add drive B support
- Hack for single sided media for now (need to address properly with disk
  ioctls)

Kernel/dev/devfdc765.c
Kernel/dev/devfdc765.h
Kernel/platform-zx+3/fdc765.s
Kernel/platform-zx+3/platform_fdc765.h [moved from Kernel/platform-zx+3/fdc765_platform.h with 60% similarity]

index 70264f0..2ef9e4b 100644 (file)
 #include <printf.h>
 #include <devfdc765.h>
 #include <timer.h>
-#include <fdc765_platform.h>
+#include <platform_fdc765.h>
 
 static timer_t spindown_timer, recal_timer;
 
+static uint8_t lastdrive;
+static uint8_t trackpos[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
+
 int devfd_open(uint8_t minor, uint16_t flag)
 {
     flag;
-    if(minor != 0) {
+    if(minor > FDC765_MAX_FLOPPY) {
         udata.u_error = ENODEV;
         return -1;
     }
+
     fd765_do_nudge_tc();
-    fd765_track = 0xff; /* not on a known track */
+
+    trackpos[minor] = 0xFF;
+    if (minor == lastdrive)
+        fd765_track = 0xff; /* not on a known track */
     return 0;
 }
 
@@ -67,40 +74,56 @@ static uint8_t fd_recalibrate(void)
     return 1;
 }
 
-/* Set up the controller for a given block, seek, and wait for spinup. */
-static void fd_seek(uint16_t lba)
+/* Set up the controller for a given block, seek, and wait for it.
+   By the time we are called the motor is assumed to be at speed */
+
+static uint8_t fd_seek(uint16_t lba)
 {
+    uint8_t i = 0;
+    /* Hack for the moment until we introduce the proper floppy ioctls
+       here and in the platform code */
+#ifdef CONFIG_FDC765_DS
     uint8_t track2 = lba / 9;
     uint8_t newtrack = track2 >> 1;
 
     fd765_sector = (lba % 9) + 1;
     fd765_head = track2 & 1;
+#else
+    uint8_t newtrack = lba / 9;
+    fd765_sector = (lba % 9) + 1;
+    fd765_head = 0;
+#endif
 
     if (newtrack != fd765_track)
     {
-        for (;;)
-        {
+        while (i++ < 5) {
             fd765_track = newtrack;
             nudge_timer();
             fd765_do_seek();
             if ((fd765_status[0] & 0xf8) == 0x20)
-                break;
-
-            fd_recalibrate();
+                return 0;
+            if (i != 5)
+                fd_recalibrate();
         }
+        return 1;
     }
+    return 0;
 }
 
 /* Select a drive and ensure the motor is on. */
 static void fd_select(int minor)
 {
-    (void)minor;
-
+    if (lastdrive != minor) {
+        trackpos[lastdrive] = fd765_track;
+        fd765_track = trackpos[minor];
+        lastdrive = minor;
+    }
+    fd765_drive = minor;
     fd765_motor_on();
     nudge_timer();
 }
 
-static int devfd_transfer(bool is_read, uint8_t is_raw)
+static int devfd_transfer(uint8_t minor, bool is_read, uint8_t is_raw)
 {
     int ct = 0;
     int tries;
@@ -118,7 +141,7 @@ static int devfd_transfer(bool is_read, uint8_t is_raw)
     // if (!is_read)
     //     return blocks << BLKSHIFT;
 
-    fd_select(0);
+    fd_select(minor);
     fd765_is_user = is_raw;
     fd765_buffer = udata.u_dptr;
 
@@ -133,7 +156,9 @@ static int devfd_transfer(bool is_read, uint8_t is_raw)
                 if (fd_recalibrate())
                     continue;
             }
-            fd_seek(lba);
+            /* Seek failed - no point trying the I/O again */
+            if (fd_seek(lba))
+                continue;
 
             /* Not all machines can make the timing for this, or have
                real controllers that can do it */
@@ -156,7 +181,8 @@ static int devfd_transfer(bool is_read, uint8_t is_raw)
         if (tries == 3)
         {
             /* FIXME: will be the drive num once we fix that */
-            kprintf("fd%d: I/O error %d:%d - %d\n", 0, is_read, lba, fd765_status[0]);
+            kprintf("fd%d: I/O error %d:%d - %d:%d\n", minor , is_read, lba,
+                            fd765_status[0], fd765_status[1]);
             udata.u_error = EIO;
             break;
         }
@@ -171,12 +197,12 @@ static int devfd_transfer(bool is_read, uint8_t is_raw)
 int devfd_read(uint8_t minor, uint8_t is_raw, uint8_t flag)
 {
     flag;minor;
-    return devfd_transfer(true, is_raw);
+    return devfd_transfer(minor, true, is_raw);
 }
 
 int devfd_write(uint8_t minor, uint8_t is_raw, uint8_t flag)
 {
     flag;minor;
-    return devfd_transfer(false, is_raw);
+    return devfd_transfer(minor, false, is_raw);
 }
 
index 7b4e710..cf5afcf 100644 (file)
@@ -23,6 +23,7 @@ extern uint8_t fd765_sector;
 extern uint8_t fd765_status[8];
 extern uint8_t* fd765_buffer;
 extern uint8_t fd765_sectors;
-extern bool fd765_is_user;
+extern uint8_t fd765_drive;
+extern uint8_t fd765_is_user;
 
 #endif /* __DEVFDC765_DOT_H__ */
index 5c28995..f110817 100644 (file)
@@ -52,9 +52,9 @@
        .globl _fd765_buffer
        .globl _fd765_is_user
        .globl _fd765_sectors
-       .globl _fd765_disc
+       .globl _fd765_drive
 
-       .globl _vborder
+       .globl _vtborder
 
        .globl diskmotor
 
@@ -117,13 +117,13 @@ _fd765_status:
        .ds 8                           ; 8 bytes of status data
 
 ; Sends the head/drive byte of a command.
-; (Drive #0 is always used.)
-; FIXME: add drive 1 support
 
 send_head:
-       ld a, (_fd765_head)
+       ld hl, (_fd765_head)            ; l = head h = drive)
+       ld a, l
        add a
        add a
+       add h
        jr fd765_tx
 
 ; Performs a RECALIBRATE command.
@@ -131,7 +131,7 @@ send_head:
 _fd765_do_recalibrate:
        ld a, #0x07                             ; RECALIBRATE
        call fd765_tx
-       ld a, #0x00                             ; drive #0 FIXME
+       ld a, (_fd765_drive)                    ; drive #
        call fd765_tx
        jr wait_for_seek_ending
 
@@ -146,11 +146,14 @@ _fd765_do_seek:
        jr wait_for_seek_ending
 _fd765_track:
        .db 0
-_fd765_head:
-       .db 0
 _fd765_sector:
        .db 0
-_fd765_disc:
+;
+;      These two must remain adjacent see send_head
+;
+_fd765_head:
+       .db 0
+_fd765_drive:
        .db 0
 
 ; Waits for a SEEK or RECALIBRATE command to finish by polling SENSE INTERRUPT STATUS.
@@ -184,7 +187,7 @@ wait_ms_loop2:
        dec a
        jr nz, wait_ms_loop
        pop bc
-       ld a,(_vborder)
+       ld a,(_vtborder)
        out (0xFE),a
        ret
 
@@ -302,7 +305,7 @@ read_finished:
        call fd765_read_status
        call tc_fix
 
-       ld a,(_vborder)
+       ld a,(_vtborder)
        out (0xFE),a
 
        pop af
@@ -394,7 +397,7 @@ write_finished:
        call fd765_read_status
        call tc_fix
 
-       ld a,(_vborder)
+       ld a,(_vtborder)
        out (0xFE),a
 
        pop af
similarity index 60%
rename from Kernel/platform-zx+3/fdc765_platform.h
rename to Kernel/platform-zx+3/platform_fdc765.h
index f431ac0..3d05e9f 100644 (file)
@@ -3,3 +3,6 @@
  */
 
 #define FDC_MOTOR_TIMEOUT      10              /* Seconds */
+
+#define FDC765_MAX_FLOPPY      2               /* Two drives */
+