Blob Blame History Raw
From 46ceee9e43c842627ac0f684e1d9d6244edb2a10 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Thu, 22 Aug 2013 02:15:58 +0200
Subject: [PATCH 2/5] floppy: Cleanup floppy irq wait handling.

RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <1377137759-16089-3-git-send-email-famz@redhat.com>
Patchwork-id: 53680
O-Subject: [RHEL-7 seabios PATCH 2/3] floppy: Cleanup floppy irq wait handling.
Bugzilla: 920140
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Markus Armbruster <armbru@redhat.com>

From: Kevin O'Connor <kevin@koconnor.net>

Rename FRS_TIMEOUT to FRS_IRQ - the flag indicates that an irq has
been received - it isn't directly related to timeouts.

On a timeout event, disable the floppy controller instead of doing a
full reset.  Also, perform the disable directly in floppy_wait_irq().

Always wait for the floppy irq after enabling the controller and after
a recalibrate command.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
(cherry picked from commit 6e529bdae4922f48c0d7eaa31613b7a9230e8f95)
Signed-off-by: Fam Zheng <famz@redhat.com>
---
 src/biosvar.h |  2 +-
 src/floppy.c  | 88 +++++++++++++++++++++++++++++------------------------------
 2 files changed, 45 insertions(+), 45 deletions(-)

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 src/biosvar.h |    2 +-
 src/floppy.c  |   88 ++++++++++++++++++++++++++++----------------------------
 2 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/src/biosvar.h b/src/biosvar.h
index f0a0fd2..252d4d1 100644
--- a/src/biosvar.h
+++ b/src/biosvar.h
@@ -120,7 +120,7 @@ struct bios_data_area_s {
 } PACKED;
 
 // BDA floppy_recalibration_status bitdefs
-#define FRS_TIMEOUT (1<<7)
+#define FRS_IRQ (1<<7)
 
 // BDA rtc_wait_flag bitdefs
 #define RWS_WAIT_PENDING (1<<0)
diff --git a/src/floppy.c b/src/floppy.c
index 458bb7a..429ccb5 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -164,63 +164,59 @@ find_floppy_type(u32 size)
  ****************************************************************/
 
 static void
-floppy_reset_controller(void)
+floppy_disable_controller(void)
 {
-    // Reset controller
-    u8 val8 = inb(PORT_FD_DOR);
-    outb(val8 & ~0x04, PORT_FD_DOR);
-    outb(val8 | 0x04, PORT_FD_DOR);
-
-    // Wait for controller to come out of reset
-    while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
-        ;
+    outb(inb(PORT_FD_DOR) & ~0x04, PORT_FD_DOR);
 }
 
 static int
-wait_floppy_irq(void)
+floppy_wait_irq(void)
 {
-    ASSERT16();
-    u8 frs;
+    u8 frs = GET_BDA(floppy_recalibration_status);
+    SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ);
     for (;;) {
-        if (!GET_BDA(floppy_motor_counter))
-            return -1;
+        if (!GET_BDA(floppy_motor_counter)) {
+            floppy_disable_controller();
+            return DISK_RET_ETIMEOUT;
+        }
         frs = GET_BDA(floppy_recalibration_status);
-        if (frs & FRS_TIMEOUT)
+        if (frs & FRS_IRQ)
             break;
         // Could use yield_toirq() here, but that causes issues on
         // bochs, so use yield() instead.
         yield();
     }
 
-    frs &= ~FRS_TIMEOUT;
-    SET_BDA(floppy_recalibration_status, frs);
-    return 0;
+    SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ);
+    return DISK_RET_SUCCESS;
 }
 
-static void
-floppy_prepare_controller(u8 floppyid)
+static int
+floppy_enable_controller(void)
 {
-    u8 frs = GET_BDA(floppy_recalibration_status);
-    SET_BDA(floppy_recalibration_status, frs & ~FRS_TIMEOUT);
-
-    // turn on motor of selected drive, DMA & int enabled, normal operation
-    u8 prev_reset = inb(PORT_FD_DOR) & 0x04;
-    u8 dor = 0x10;
-    if (floppyid)
-        dor = 0x20;
-    dor |= 0x0c;
-    dor |= floppyid;
-    outb(dor, PORT_FD_DOR);
+    outb(inb(PORT_FD_DOR) | 0x04, PORT_FD_DOR);
+    return floppy_wait_irq();
+}
 
+static int
+floppy_select_drive(u8 floppyid)
+{
     // reset the disk motor timeout value of INT 08
     SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
 
-    // wait for drive readiness
-    while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
-        ;
+    // Enable controller if it isn't running.
+    u8 dor = inb(PORT_FD_DOR);
+    if (!(dor & 0x04)) {
+        int ret = floppy_enable_controller();
+        if (ret)
+            return ret;
+    }
 
-    if (!prev_reset)
-        wait_floppy_irq();
+    // Turn on motor of selected drive, DMA & int enabled, normal operation
+    dor = (floppyid ? 0x20 : 0x10) | 0x0c | floppyid;
+    outb(dor, PORT_FD_DOR);
+
+    return DISK_RET_SUCCESS;
 }
 
 struct floppy_pio_s {
@@ -233,7 +229,13 @@ struct floppy_pio_s {
 static int
 floppy_pio(struct floppy_pio_s *pio)
 {
-    floppy_prepare_controller(pio->data[1] & 1);
+    int ret = floppy_select_drive(pio->data[1] & 1);
+    if (ret)
+        return ret;
+
+    // wait for drive readiness
+    while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
+        ;
 
     // send command to controller
     int i;
@@ -241,11 +243,9 @@ floppy_pio(struct floppy_pio_s *pio)
         outb(pio->data[i], PORT_FD_DATA);
 
     if (pio->waitirq) {
-        int ret = wait_floppy_irq();
-        if (ret) {
-            floppy_reset_controller();
-            return DISK_RET_ETIMEOUT;
-        }
+        int ret = floppy_wait_irq();
+        if (ret)
+            return ret;
     }
 
     if (!pio->resplen)
@@ -330,7 +330,7 @@ floppy_drive_recal(u8 floppyid)
     struct floppy_pio_s pio;
     pio.cmdlen = 2;
     pio.resplen = 0;
-    pio.waitirq = 0;
+    pio.waitirq = 1;
     pio.data[0] = 0x07;  // 07: Recalibrate
     pio.data[1] = floppyid; // 0=drive0, 1=drive1
     floppy_pio(&pio);
@@ -617,7 +617,7 @@ handle_0e(void)
     }
     // diskette interrupt has occurred
     u8 frs = GET_BDA(floppy_recalibration_status);
-    SET_BDA(floppy_recalibration_status, frs | FRS_TIMEOUT);
+    SET_BDA(floppy_recalibration_status, frs | FRS_IRQ);
 
     eoi_pic1();
 }
-- 
1.7.1