<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From 80b822bb09161a6fcf1551101b6f8a0db1919c59 Mon Sep 17 00:00:00 2001
Message-Id: &lt;80b822bb09161a6fcf1551101b6f8a0db1919c59.1343915404.git.minovotn@redhat.com&gt;
In-Reply-To: &lt;5b3bcf18e866636f24ca1c23eb94d5caf23c6dd6.1343915404.git.minovotn@redhat.com&gt;
References: &lt;5b3bcf18e866636f24ca1c23eb94d5caf23c6dd6.1343915404.git.minovotn@redhat.com&gt;
From: Pavel Hrdina &lt;phrdina@redhat.com&gt;
Date: Mon, 16 Jul 2012 16:14:54 +0200
Subject: [PATCH 5/7] fdc: rewrite seek and DSKCHG bit handling

RH-Author: Pavel Hrdina &lt;phrdina@redhat.com&gt;
Message-id: &lt;7ae36bf2353a56b2fce894db51eee09629d6cd3f.1342446805.git.phrdina@redhat.com&gt;
Patchwork-id: 40341
O-Subject: [RHEL-6.4 qemu-kvm PATCH v6 5/6] fdc: rewrite seek and DSKCHG bit handling
Bugzilla: 729244
RH-Acked-by: Laszlo Ersek &lt;lersek@redhat.com&gt;
RH-Acked-by: Miroslav Rezanina &lt;mrezanin@redhat.com&gt;
RH-Acked-by: Michal Novotny &lt;minovotn@redhat.com&gt;

This bit is cleared on every successful seek to a different track (cylinder).
The seek is also called on revalidate or on read/write/format commands which
also clear the DSKCHG bit.

Signed-off-by: Pavel Hrdina &lt;phrdina@redhat.com&gt;
Signed-off-by: Kevin Wolf &lt;kwolf@redhat.com&gt;
(cherry picked from commit 6be01b1e0b14ad4809c9aec273c6109b91d2df1c)
---
 hw/fdc.c |   84 +++++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 34 deletions(-)

Signed-off-by: Michal Novotny &lt;minovotn@redhat.com&gt;
---
 hw/fdc.c |   84 +++++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 34 deletions(-)

diff --git a/hw/fdc.c b/hw/fdc.c
index 084fbe9..fe38649 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -159,8 +159,12 @@ static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
         }
 #endif
         drv-&gt;head = head;
-        if (drv-&gt;track != track)
+        if (drv-&gt;track != track) {
+            if (drv-&gt;bs != NULL &amp;&amp; bdrv_is_inserted(drv-&gt;bs)) {
+                drv-&gt;media_changed = 0;
+            }
             ret = 1;
+        }
         drv-&gt;track = track;
         drv-&gt;sect = sect;
     }
@@ -176,9 +180,7 @@ static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
 static void fd_recalibrate (fdrive_t *drv)
 {
     FLOPPY_DPRINTF("recalibrate\n");
-    drv-&gt;head = 0;
-    drv-&gt;track = 0;
-    drv-&gt;sect = 1;
+    fd_seek(drv, 0, 0, 1, 1);
 }
 
 /* Recognize floppy formats */
@@ -1059,7 +1061,10 @@ static void fdctrl_unimplemented (fdctrl_t *fdctrl, int direction)
     fdctrl_set_fifo(fdctrl, 1, 0);
 }
 
-/* Seek to next sector */
+/* Seek to next sector
+ * returns 0 when end of track reached (for DBL_SIDES on head 1)
+ * otherwise returns 1
+ */
 static int fdctrl_seek_to_next_sect (fdctrl_t *fdctrl, fdrive_t *cur_drv)
 {
     FLOPPY_DPRINTF("seek to next sector (%d %02x %02x =&gt; %d)\n",
@@ -1067,30 +1072,39 @@ static int fdctrl_seek_to_next_sect (fdctrl_t *fdctrl, fdrive_t *cur_drv)
                    fd_sector(cur_drv));
     /* XXX: cur_drv-&gt;sect &gt;= cur_drv-&gt;last_sect should be an
        error in fact */
-    if (cur_drv-&gt;sect &gt;= cur_drv-&gt;last_sect ||
-        cur_drv-&gt;sect == fdctrl-&gt;eot) {
-        cur_drv-&gt;sect = 1;
+    uint8_t new_head = cur_drv-&gt;head;
+    uint8_t new_track = cur_drv-&gt;track;
+    uint8_t new_sect = cur_drv-&gt;sect;
+
+    int ret = 1;
+
+    if (new_sect &gt;= cur_drv-&gt;last_sect ||
+        new_sect == fdctrl-&gt;eot) {
+        new_sect = 1;
         if (FD_MULTI_TRACK(fdctrl-&gt;data_state)) {
-            if (cur_drv-&gt;head == 0 &amp;&amp;
+            if (new_head == 0 &amp;&amp;
                 (cur_drv-&gt;flags &amp; FDISK_DBL_SIDES) != 0) {
-                cur_drv-&gt;head = 1;
+                new_head = 1;
             } else {
-                cur_drv-&gt;head = 0;
-                cur_drv-&gt;track++;
-                if ((cur_drv-&gt;flags &amp; FDISK_DBL_SIDES) == 0)
-                    return 0;
+                new_head = 0;
+                new_track++;
+                if ((cur_drv-&gt;flags &amp; FDISK_DBL_SIDES) == 0) {
+                    ret = 0;
+                }
             }
         } else {
-            cur_drv-&gt;track++;
-            return 0;
+            new_track++;
+            ret = 0;
+        }
+        if (ret == 1) {
+            FLOPPY_DPRINTF("seek to next track (%d %02x %02x =&gt; %d)\n",
+                    new_head, new_track, new_sect, fd_sector(cur_drv));
         }
-        FLOPPY_DPRINTF("seek to next track (%d %02x %02x =&gt; %d)\n",
-                       cur_drv-&gt;head, cur_drv-&gt;track,
-                       cur_drv-&gt;sect, fd_sector(cur_drv));
     } else {
-        cur_drv-&gt;sect++;
+        new_sect++;
     }
-    return 1;
+    fd_seek(cur_drv, new_head, new_track, new_sect, 1);
+    return ret;
 }
 
 /* Callback for transfer end (stop or abort) */
@@ -1659,13 +1673,12 @@ static void fdctrl_handle_seek (fdctrl_t *fdctrl, int direction)
     SET_CUR_DRV(fdctrl, fdctrl-&gt;fifo[1] &amp; FD_DOR_SELMASK);
     cur_drv = get_cur_drv(fdctrl);
     fdctrl_reset_fifo(fdctrl);
-    if (fdctrl-&gt;fifo[2] &gt; cur_drv-&gt;max_track) {
-        fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK);
-    } else {
-        cur_drv-&gt;track = fdctrl-&gt;fifo[2];
-        /* Raise Interrupt */
-        fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
-    }
+    /* The seek command just sends step pulses to the drive and doesn't care if
+     * there is a medium inserted of if it's banging the head against the drive.
+     */
+    fd_seek(cur_drv, cur_drv-&gt;head, fdctrl-&gt;fifo[2], cur_drv-&gt;sect, 1);
+    /* Raise Interrupt */
+    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 }
 
 static void fdctrl_handle_perpendicular_mode (fdctrl_t *fdctrl, int direction)
@@ -1721,32 +1734,35 @@ static void fdctrl_handle_drive_specification_command (fdctrl_t *fdctrl, int dir
     }
 }
 
-static void fdctrl_handle_relative_seek_out (fdctrl_t *fdctrl, int direction)
+static void fdctrl_handle_relative_seek_in(fdctrl_t *fdctrl, int direction)
 {
     fdrive_t *cur_drv;
 
     SET_CUR_DRV(fdctrl, fdctrl-&gt;fifo[1] &amp; FD_DOR_SELMASK);
     cur_drv = get_cur_drv(fdctrl);
     if (fdctrl-&gt;fifo[2] + cur_drv-&gt;track &gt;= cur_drv-&gt;max_track) {
-        cur_drv-&gt;track = cur_drv-&gt;max_track - 1;
+        fd_seek(cur_drv, cur_drv-&gt;head, cur_drv-&gt;max_track - 1,
+                cur_drv-&gt;sect, 1);
     } else {
-        cur_drv-&gt;track += fdctrl-&gt;fifo[2];
+        fd_seek(cur_drv, cur_drv-&gt;head,
+                cur_drv-&gt;track + fdctrl-&gt;fifo[2], cur_drv-&gt;sect, 1);
     }
     fdctrl_reset_fifo(fdctrl);
     /* Raise Interrupt */
     fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
 }
 
-static void fdctrl_handle_relative_seek_in (fdctrl_t *fdctrl, int direction)
+static void fdctrl_handle_relative_seek_out(fdctrl_t *fdctrl, int direction)
 {
     fdrive_t *cur_drv;
 
     SET_CUR_DRV(fdctrl, fdctrl-&gt;fifo[1] &amp; FD_DOR_SELMASK);
     cur_drv = get_cur_drv(fdctrl);
     if (fdctrl-&gt;fifo[2] &gt; cur_drv-&gt;track) {
-        cur_drv-&gt;track = 0;
+        fd_seek(cur_drv, cur_drv-&gt;head, 0, cur_drv-&gt;sect, 1);
     } else {
-        cur_drv-&gt;track -= fdctrl-&gt;fifo[2];
+        fd_seek(cur_drv, cur_drv-&gt;head,
+                cur_drv-&gt;track - fdctrl-&gt;fifo[2], cur_drv-&gt;sect, 1);
     }
     fdctrl_reset_fifo(fdctrl);
     /* Raise Interrupt */
-- 
1.7.10.4

</pre></body></html>