[FLOPPY] Don't wait forever while trying to determine media type.
authorPierre Schweitzer <pierre@reactos.org>
Tue, 21 Nov 2017 09:22:50 +0000 (10:22 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Tue, 21 Nov 2017 09:22:50 +0000 (10:22 +0100)
This should fix some virtual machines and real hardware machine with empty floopy drive
not being able to boot ReactOS (stuck while initializing floppy.sys).
This fixes a regression introduced in r70746.
It could be generalized to other interrupts, floppy controllers not being reliable.

For more information: http://wiki.osdev.org/Floppy_Disk_Controller

CORE-7935
CORE-12908
CORE-13080

drivers/storage/floppy/floppy.c
drivers/storage/floppy/floppy.h
drivers/storage/floppy/readwrite.c

index d388cf7..4234b0f 100644 (file)
@@ -159,12 +159,13 @@ StopMotor(PCONTROLLER_INFO ControllerInfo)
 }
 
 
-VOID NTAPI
-WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo)
+NTSTATUS NTAPI
+WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo, PLARGE_INTEGER Timeout)
 /*
  * FUNCTION: Wait for the controller to interrupt, and then clear the event
  * ARGUMENTS:
  *     ControllerInfo: Controller to wait for
+ *     Timeout: How long to wait for
  * NOTES:
  *     - There is a small chance that an unexpected or spurious interrupt could
  *       be lost with this clear/wait/clear scheme used in this driver.  This is
@@ -173,11 +174,15 @@ WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo)
  *     - PAGED_CODE because it waits
  */
 {
+    NTSTATUS Status;
+
     PAGED_CODE();
     ASSERT(ControllerInfo);
 
-    KeWaitForSingleObject(&ControllerInfo->SynchEvent, Executive, KernelMode, FALSE, NULL);
+    Status = KeWaitForSingleObject(&ControllerInfo->SynchEvent, Executive, KernelMode, FALSE, Timeout);
     KeClearEvent(&ControllerInfo->SynchEvent);
+
+    return Status;
 }
 
 static DRIVER_DISPATCH CreateClose;
@@ -262,7 +267,7 @@ Recalibrate(PDRIVE_INFO DriveInfo)
             continue;
         }
 
-        WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+        WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
         /* Get the results */
         Status = HwRecalibrateResult(DriveInfo->ControllerInfo);
@@ -323,7 +328,7 @@ ResetChangeFlag(PDRIVE_INFO DriveInfo)
         return STATUS_IO_DEVICE_ERROR;
     }
 
-    WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+    WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
     if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS)
     {
@@ -340,7 +345,7 @@ ResetChangeFlag(PDRIVE_INFO DriveInfo)
         return STATUS_IO_DEVICE_ERROR;
     }
 
-    WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+    WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
     if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS)
     {
@@ -701,7 +706,7 @@ InitController(PCONTROLLER_INFO ControllerInfo)
     INFO_(FLOPPY, "InitController: waiting for initial interrupt\n");
 
     /* Wait for an interrupt */
-    WaitForControllerInterrupt(ControllerInfo);
+    WaitForControllerInterrupt(ControllerInfo, NULL);
 
     /* Reset means you have to clear each of the four interrupts (one per drive) */
     for(i = 0; i < MAX_DRIVES_PER_CONTROLLER; i++)
index e1d0efc..cd0301c 100644 (file)
@@ -92,8 +92,8 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
 VOID NTAPI
 SignalMediaChanged(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 
-VOID NTAPI
-WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo);
+NTSTATUS NTAPI
+WaitForControllerInterrupt(PCONTROLLER_INFO ControllerInfo, PLARGE_INTEGER Timeout);
 
 NTSTATUS NTAPI
 ResetChangeFlag(PDRIVE_INFO DriveInfo);
index 594d9c7..2ce3a6c 100644 (file)
@@ -170,6 +170,7 @@ RWDetermineMediaType(PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
     UCHAR HeadLoadTime;
     UCHAR HeadUnloadTime;
     UCHAR StepRateTime;
+    LARGE_INTEGER Timeout;
 
     PAGED_CODE();
 
@@ -181,9 +182,12 @@ RWDetermineMediaType(PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
      * Note that only 1.44 has been tested at all.
      */
 
+    Timeout.QuadPart = -10000000; /* 1 second. Is that enough? */
+
     do
     {
         int i;
+        NTSTATUS Status;
 
         /* Program data rate */
         if(HwSetDataRate(DriveInfo->ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS)
@@ -219,7 +223,7 @@ RWDetermineMediaType(PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
             }
 
             /* Wait for the recalibrate to finish */
-            WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+            WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
             RecalStatus = HwRecalibrateResult(DriveInfo->ControllerInfo);
 
@@ -244,9 +248,9 @@ RWDetermineMediaType(PDRIVE_INFO DriveInfo, BOOLEAN OneShot)
         }
 
         /* Wait for the ReadID to finish */
-        WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+        Status = WaitForControllerInterrupt(DriveInfo->ControllerInfo, &Timeout);
 
-        if(HwReadIdResult(DriveInfo->ControllerInfo, NULL, NULL) != STATUS_SUCCESS)
+        if(Status == STATUS_TIMEOUT || HwReadIdResult(DriveInfo->ControllerInfo, NULL, NULL) != STATUS_SUCCESS)
         {
             WARN_(FLOPPY, "RWDetermineMediaType(): ReadIdResult failed; continuing\n");
             if (OneShot)
@@ -303,7 +307,7 @@ RWSeekToCylinder(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
         return STATUS_UNSUCCESSFUL;
     }
 
-    WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+    WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
     if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS)
     {
@@ -318,7 +322,7 @@ RWSeekToCylinder(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
         return STATUS_UNSUCCESSFUL;
     }
 
-    WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+    WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
     if(HwReadIdResult(DriveInfo->ControllerInfo, &CurCylinder, NULL) != STATUS_SUCCESS)
     {
@@ -732,7 +736,7 @@ ReadWritePassive(PDRIVE_INFO DriveInfo, PIRP Irp)
          * At this point, we block and wait for an interrupt
          * FIXME: this seems to take too long
          */
-        WaitForControllerInterrupt(DriveInfo->ControllerInfo);
+        WaitForControllerInterrupt(DriveInfo->ControllerInfo, NULL);
 
         /* Read is complete; flush & free adapter channel */
         IoFlushAdapterBuffers(DriveInfo->ControllerInfo->AdapterObject, Irp->MdlAddress,