- Fix floppy controller detection

- Simplify waiting in Get_Byte and Send_Byte
 - See issue #4391 for details

svn path=/trunk/; revision=45568
This commit is contained in:
Cameron Gutman 2010-02-11 02:22:34 +00:00
parent c7f7e3bac7
commit aa9a3648eb
2 changed files with 40 additions and 95 deletions

View file

@ -686,19 +686,20 @@ static NTSTATUS NTAPI InitController(PCONTROLLER_INFO ControllerInfo)
return STATUS_IO_DEVICE_ERROR; return STATUS_IO_DEVICE_ERROR;
} }
/* Check if floppy drive exists */ /* All controllers should support this so
if(HwSenseInterruptStatus(ControllerInfo) != STATUS_SUCCESS) * if we get something strange back then we
* know that this isn't a floppy controller
*/
if (HwGetVersion(ControllerInfo) <= 0)
{ {
WARN_(FLOPPY, "Floppy drive not detected!\n"); WARN_(FLOPPY, "InitController: unable to contact controller\n");
return STATUS_NO_SUCH_DEVICE; return STATUS_NO_SUCH_DEVICE;
} }
INFO_(FLOPPY, "InitController: resetting the controller after floppy detection\n"); /* Reset the controller to avoid interrupt garbage on certain controllers */
/* Reset the controller again after drive detection */
if(HwReset(ControllerInfo) != STATUS_SUCCESS) if(HwReset(ControllerInfo) != STATUS_SUCCESS)
{ {
WARN_(FLOPPY, "InitController: unable to reset controller\n"); WARN_(FLOPPY, "InitController: unable to reset controller #2\n");
return STATUS_IO_DEVICE_ERROR; return STATUS_IO_DEVICE_ERROR;
} }

View file

@ -45,7 +45,6 @@
* with the bit position in the register, or they *might not*. This should * with the bit position in the register, or they *might not*. This should
* all be converted to standardize on absolute values or shifts. * all be converted to standardize on absolute values or shifts.
* I prefer bit fields, but they break endianness. * I prefer bit fields, but they break endianness.
* TODO: Figure out the right delays in Send_Byte and Get_Byte
*/ */
#include <ntddk.h> #include <ntddk.h>
@ -54,13 +53,6 @@
#include "floppy.h" #include "floppy.h"
#include "hardware.h" #include "hardware.h"
/*
* Global variable that tracks the amount of time we've
* been waiting on the controller
*/
static ULONG TimeIncrement = 0;
/* /*
* Hardware Support Routines * Hardware Support Routines
*/ */
@ -131,60 +123,35 @@ static NTSTATUS NTAPI Send_Byte(PCONTROLLER_INFO ControllerInfo,
* - Function designed after flowchart in intel datasheet * - Function designed after flowchart in intel datasheet
* - 250us max delay. Note that this is exactly 5 times longer * - 250us max delay. Note that this is exactly 5 times longer
* than Microsoft recommends stalling the processor * than Microsoft recommends stalling the processor
* - Remember that we can be interrupted here, so this might
* take much more wall clock time than 250us
* - PAGED_CODE, because we spin for more than the Microsoft-recommended * - PAGED_CODE, because we spin for more than the Microsoft-recommended
* maximum. * maximum.
* - This function is necessary because sometimes the FIFO reacts slowly * - This function is necessary because sometimes the FIFO reacts slowly
* and isn't yet ready to read or write the next byte * and isn't yet ready to read or write the next byte
* FIXME: time interval here and in Get_Byte
*/ */
{ {
LARGE_INTEGER StartingTickCount; int i;
LARGE_INTEGER CurrentTickCount;
PUCHAR Address;
PAGED_CODE(); PAGED_CODE();
Address = ControllerInfo->BaseAddress + FIFO; for(i = 0; i < 5; i++)
if(!TimeIncrement)
TimeIncrement = KeQueryTimeIncrement();
StartingTickCount.QuadPart = 0;
for(;;)
{ {
if(!ReadyForWrite(ControllerInfo)) if(ReadyForWrite(ControllerInfo))
{ break;
ULONG64 ElapsedTicks;
ULONG64 TimeUnits;
/* If this is the first time through... */ KeStallExecutionProcessor(50);
if(!StartingTickCount.QuadPart)
{
KeQueryTickCount(&StartingTickCount);
continue;
}
/* Otherwise, only do this for 250 us == 2500 100ns units */
KeQueryTickCount(&CurrentTickCount);
ElapsedTicks = CurrentTickCount.QuadPart - StartingTickCount.QuadPart;
TimeUnits = ElapsedTicks * TimeIncrement;
if(TimeUnits > 25000000)
break;
continue;
}
WRITE_PORT_UCHAR(Address, Byte);
return STATUS_SUCCESS;
} }
INFO_(FLOPPY, "Send_Byte: timed out trying to write\n"); if (i < 5)
HwDumpRegisters(ControllerInfo); {
return STATUS_UNSUCCESSFUL; WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + FIFO, Byte);
return STATUS_SUCCESS;
}
else
{
INFO_(FLOPPY, "Send_Byte: timed out trying to write\n");
HwDumpRegisters(ControllerInfo);
return STATUS_UNSUCCESSFUL;
}
} }
@ -208,52 +175,29 @@ static NTSTATUS NTAPI Get_Byte(PCONTROLLER_INFO ControllerInfo,
* - PAGED_CODE because we spin for longer than Microsoft recommends * - PAGED_CODE because we spin for longer than Microsoft recommends
*/ */
{ {
LARGE_INTEGER StartingTickCount; int i;
LARGE_INTEGER CurrentTickCount;
PUCHAR Address;
PAGED_CODE(); PAGED_CODE();
Address = ControllerInfo->BaseAddress + FIFO; for(i = 0; i < 5; i++)
if(!TimeIncrement)
TimeIncrement = KeQueryTimeIncrement();
StartingTickCount.QuadPart = 0;
for(;;)
{ {
if(!ReadyForRead(ControllerInfo)) if(ReadyForRead(ControllerInfo))
{ break;
ULONG64 ElapsedTicks;
ULONG64 TimeUnits;
/* if this is the first time through, start the timer */ KeStallExecutionProcessor(50);
if(!StartingTickCount.QuadPart)
{
KeQueryTickCount(&StartingTickCount);
continue;
}
/* Otherwise, only do this for 250 us == 2500 100ns units */
KeQueryTickCount(&CurrentTickCount);
ElapsedTicks = CurrentTickCount.QuadPart - StartingTickCount.QuadPart;
TimeUnits = ElapsedTicks * TimeIncrement;
if(TimeUnits > 25000000)
break;
continue;
}
*Byte = READ_PORT_UCHAR(Address);
return STATUS_SUCCESS;
} }
WARN_(FLOPPY, "Get_Byte: timed out trying to read\n"); if (i < 5)
HwDumpRegisters(ControllerInfo); {
return STATUS_UNSUCCESSFUL; *Byte = READ_PORT_UCHAR(ControllerInfo->BaseAddress + FIFO);
return STATUS_SUCCESS;
}
else
{
INFO_(FLOPPY, "Get_Byte: timed out trying to write\n");
HwDumpRegisters(ControllerInfo);
return STATUS_UNSUCCESSFUL;
}
} }