Floppy driver updates, managed to boot system from floppy

svn path=/trunk/; revision=1824
This commit is contained in:
Phillip Susi 2001-04-26 01:24:31 +00:00
parent 197fe0acf4
commit dc3c360885
4 changed files with 127 additions and 39 deletions

View file

@ -5,6 +5,7 @@
***************************************************************************/
#include <ddk/ntddk.h>
#define NDEBUG
#include <debug.h>
#include "floppy.h"
@ -16,7 +17,6 @@ VOID FloppyDpc( PKDPC Dpc,
{
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
CHECKPOINT1;
ControllerExtension->DpcState( Dpc,
DeviceObject,
Irp,
@ -31,7 +31,6 @@ VOID FloppyDpcDetect( PKDPC Dpc,
{
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
CHECKPOINT1;
KeSetEvent( &ControllerExtension->Event, 0, FALSE );
}
@ -40,8 +39,8 @@ VOID FloppyDpcFailIrp( PKDPC Dpc,
PIRP Irp,
PVOID Context )
{
CHECKPOINT1;
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
CHECKPOINT;
IoCompleteRequest( Irp, 0 );
}
@ -54,7 +53,6 @@ VOID FloppyMotorSpindownDpc( PKDPC Dpc,
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension;
CHECKPOINT1;
// queue call to turn off motor
IoAllocateController( Controller,
ControllerExtension->Device,
@ -72,7 +70,6 @@ VOID FloppyMotorSpinupDpc( PKDPC Dpc,
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension;
LARGE_INTEGER Timeout;
CHECKPOINT1;
Timeout.QuadPart = FLOPPY_MOTOR_SPINDOWN_TIME;
// Motor has had time to spin up, mark motor as spun up and restart IRP
// don't forget to set the spindown timer
@ -88,6 +85,38 @@ VOID FloppyMotorSpinupDpc( PKDPC Dpc,
ControllerExtension->Irp );
}
VOID FloppySeekDpc( PKDPC Dpc,
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context )
{
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension;
// if the seek failed, fail the IRP
if( ControllerExtension->St0 & FLOPPY_ST0_GDMASK )
{
ControllerExtension->Irp->IoStatus.Status = STATUS_DISK_CORRUPT_ERROR;
ControllerExtension->Irp->IoStatus.Information = 0;
DPRINT( "Failing IRP: St0 = %2x, St1 = %2x, St2 = %2x\n",
ControllerExtension->St0,
ControllerExtension->St1,
ControllerExtension->St2 );
for(;;);
IoCompleteRequest( ControllerExtension->Irp, 0 );
IoFreeController( DeviceExtension->Controller );
return;
}
KeStallExecutionProcessor( 10000000 );
DPRINT( "Seek completed, now on cyl %2x\n", DeviceExtension->Cyl );
// now that we are on the right cyl, restart the read
if( FloppyExecuteReadWrite( DeviceObject,
ControllerExtension->Irp,
ControllerExtension->MapRegisterBase,
ControllerExtension->Irp ) == DeallocateObject )
IoFreeController( DeviceExtension->Controller );
}
VOID FloppyDpcReadWrite( PKDPC Dpc,
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
@ -95,26 +124,48 @@ VOID FloppyDpcReadWrite( PKDPC Dpc,
{
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension;
DWORD SectorSize = 128 << ControllerExtension->SectorSizeCode;
PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( ControllerExtension->Irp );
BOOLEAN WriteToDevice = Stk->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE;
CHECKPOINT1;
Irp = ControllerExtension->Irp;
// if the IO failed, fail the IRP
if( ControllerExtension->St0 & FLOPPY_ST0_GDMASK )
{
Irp->IoStatus.Status = STATUS_DISK_CORRUPT_ERROR;
Irp->IoStatus.Information = 0;
DPRINT( "Failing IRP: St0 = %2x, St1 = %2x, St2 = %2x\n",
ControllerExtension->St0,
ControllerExtension->St1,
ControllerExtension->St2 );
for(;;);
IoCompleteRequest( Irp, 0 );
CHECKPOINT1;
IoFreeController( Controller );
return;
}
ControllerExtension->CurrentOffset += SectorSize;
ControllerExtension->CurrentLength -= SectorSize;
(char *)ControllerExtension->CurrentVa += SectorSize;
// don't forget to flush the buffers
IoFlushAdapterBuffers( ControllerExtension->AdapterObject,
ControllerExtension->Irp->MdlAddress,
ControllerExtension->MapRegisterBase,
ControllerExtension->Irp->Tail.Overlay.DriverContext[0],
MediaTypes[DeviceExtension->MediaType].BytesPerSector,
WriteToDevice );
DPRINT( "St0 = %2x, St1 %2x, St2 = %2x\n",
ControllerExtension->St0,
ControllerExtension->St1,
ControllerExtension->St2 );
// update buffer info
Stk->Parameters.Read.ByteOffset.u.LowPart += SectorSize;
Stk->Parameters.Read.Length -= SectorSize;
// drivercontext used for current va
(DWORD)ControllerExtension->Irp->Tail.Overlay.DriverContext[0] += SectorSize;
DPRINT( "First dword: %x\n", *((DWORD *)ControllerExtension->MapRegisterBase) )
// if there is more IO to be done, restart execute routine to issue next read
if( ControllerExtension->CurrentLength )
if( Stk->Parameters.Read.Length )
{
CHECKPOINT1;
if( FloppyExecuteReadWrite( DeviceObject,
Irp,
ControllerExtension->MapRegisterBase,
@ -122,7 +173,7 @@ VOID FloppyDpcReadWrite( PKDPC Dpc,
IoFreeController( Controller );
}
else {
CHECKPOINT1;
IoFreeController( Controller );
// oetherwise, complete the Irp
IoCompleteRequest( Irp, 0 );
}
@ -134,7 +185,6 @@ VOID FloppyDpcDetectMedia( PKDPC Dpc,
{
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
CHECKPOINT1;
// If the read ID failed, fail the irp
if( ControllerExtension->St1 != 0 )
{

View file

@ -17,7 +17,7 @@
#include <ddk/ntddk.h>
#include "floppy.h"
#define NDEBUG
#include <debug.h>
@ -28,7 +28,7 @@ FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] =
};
const FLOPPY_MEDIA_TYPE MediaTypes[] = {
{ 0x02, 9, 80, 18, 512 },
{ 0x02, 80, 2, 18, 512 },
{ 0, 0, 0, 0, 0 } };
@ -41,6 +41,7 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
PFLOPPY_DEVICE_EXTENSION DeviceExtension;
UNICODE_STRING DeviceName;
UNICODE_STRING arcname;
UNICODE_STRING SymlinkName;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
@ -182,6 +183,7 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) );
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL );
DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) );
KeStallExecutionProcessor( 10000 );
FloppyWriteDATA( ControllerExtension->PortBase, 0 ); // drive select
Timeout.QuadPart = FLOPPY_RECAL_TIMEOUT;
Status = KeWaitForSingleObject( &ControllerExtension->Event,
@ -199,6 +201,7 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
DbgPrint( "Floppy: error recalibrating drive, ST0: %2x\n", (DWORD)ControllerExtension->St0 );
goto interruptcleanup;
}
DeviceExtension->Cyl = 0;
// drive is good, and it is now on track 0, turn off the motor
FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA );
/* Initialize the device */
@ -234,6 +237,9 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
}
// Ok, we own the adapter object, from now on we can just IoMapTransfer, and not
// bother releasing the adapter ever.
RtlInitUnicodeString( &arcname, L"\\ArcName\\multi(0)disk(0)fdisk(0)" );
Status = IoAssignArcName( &arcname, &DeviceName );
DbgPrint( "Floppy drive initialized\n" );
return TRUE;
@ -273,13 +279,15 @@ IO_ALLOCATION_ACTION FloppyExecuteReadWrite( PDEVICE_OBJECT DeviceObject,
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension;
LARGE_INTEGER Timeout;
BOOLEAN WriteToDevice;
UCHAR Cyl, Sector, Head;
DWORD Cyl, Sector, Head;
PIO_STACK_LOCATION Stk;
ControllerExtension->Irp = Irp = (PIRP)Context;
Stk = IoGetCurrentIrpStackLocation( Irp );
ControllerExtension->Device = DeviceObject;
Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME;
CHECKPOINT;
WriteToDevice = IoGetCurrentIrpStackLocation( Irp )->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE;
WriteToDevice = Stk->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE;
// verify drive is spun up and selected
if( ControllerExtension->MotorOn != DeviceExtension->DriveSelect )
{
@ -296,7 +304,14 @@ IO_ALLOCATION_ACTION FloppyExecuteReadWrite( PDEVICE_OBJECT DeviceObject,
&ControllerExtension->MotorSpinupDpc );
return KeepObject;
}
else {
Timeout.QuadPart = FLOPPY_MOTOR_SPINDOWN_TIME;
// motor is already spinning, so reset the spindown timer
KeCancelTimer( &ControllerExtension->SpinupTimer );
KeSetTimer( &ControllerExtension->SpinupTimer,
Timeout,
&ControllerExtension->MotorSpindownDpc );
}
// verify media content
if( FloppyReadDIR( ControllerExtension->PortBase ) & FLOPPY_DI_DSKCHNG )
{
@ -322,21 +337,37 @@ IO_ALLOCATION_ACTION FloppyExecuteReadWrite( PDEVICE_OBJECT DeviceObject,
}
// looks like we have media in the drive.... do the read
// first, calculate geometry for read
Sector = ControllerExtension->CurrentOffset / MediaTypes[DeviceExtension->MediaType].BytesPerSector;
Sector = Stk->Parameters.Read.ByteOffset.u.LowPart / MediaTypes[DeviceExtension->MediaType].BytesPerSector;
// absolute sector right now
Cyl = Sector / MediaTypes[DeviceExtension->MediaType].SectorsPerTrack;
DPRINT( "Sector = %x, Offset = %x, Cyl = %x, Heads = %x MediaType = %x\n", Sector, Irp->Parameters.Read.ByteOffset.u.LowPart, (DWORD)Cyl, (DWORD)MediaTypes[DeviceExtension->MediaType].Heads, (DWORD)DeviceExtension->MediaType );
Head = Cyl % MediaTypes[DeviceExtension->MediaType].Heads;
DPRINT( "Head = %2x\n", Head );
// convert absolute cyl to relative
Cyl /= MediaTypes[DeviceExtension->MediaType].Heads;
// convert absolute sector to relative
Sector %= MediaTypes[DeviceExtension->MediaType].SectorsPerTrack;
Sector++; // track relative sector numbers are 1 based, not 0 based
DPRINT( "Cyl = %2x, Head = %2x, Sector = %2x\n", Cyl, Head, Sector );
// seek if we need to seek
if( DeviceExtension->Cyl != Cyl )
{
DPRINT( "Seeking...\n" );
ControllerExtension->IsrState = FloppyIsrDetect;
ControllerExtension->DpcState = FloppySeekDpc;
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SEEK );
KeStallExecutionProcessor( 1000 );
FloppyWriteDATA( ControllerExtension->PortBase, DeviceExtension->DriveSelect );
KeStallExecutionProcessor( 1000 );
FloppyWriteDATA( ControllerExtension->PortBase, Cyl );
return KeepObject;
}
//set up DMA and issue read command
IoMapTransfer( ControllerExtension->AdapterObject,
Irp->MdlAddress,
ControllerExtension->MapRegisterBase,
ControllerExtension->CurrentVa,
Irp->Tail.Overlay.DriverContext[0], // current va
&MediaTypes[DeviceExtension->MediaType].BytesPerSector,
WriteToDevice );
ControllerExtension->IsrState = FloppyIsrReadWrite;
@ -386,17 +417,15 @@ NTSTATUS STDCALL FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject,
IoCompleteRequest( Irp, 1 );
return STATUS_INVALID_PARAMETER;
}
ControllerExtension->CurrentOffset = Stk->Parameters.Read.ByteOffset.u.LowPart;
ControllerExtension->CurrentLength = Stk->Parameters.Read.Length;
ControllerExtension->CurrentVa = MmGetMdlVirtualAddress( Irp->MdlAddress );
// store currentva in drivercontext
Irp->Tail.Overlay.DriverContext[0] = MmGetMdlVirtualAddress( Irp->MdlAddress );
DPRINT( "FloppyDispatchReadWrite: offset = %x, length = %x, va = %x\n",
ControllerExtension->CurrentOffset,
ControllerExtension->CurrentLength,
ControllerExtension->CurrentVa );
// Queue IRP
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = ControllerExtension->CurrentLength;
Irp->IoStatus.Information = Stk->Parameters.Read.Length;
IoMarkIrpPending( Irp );
KeRaiseIrql( DISPATCH_LEVEL, &oldlvl );
IoAllocateController( ((PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Controller,
@ -404,6 +433,7 @@ NTSTATUS STDCALL FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject,
FloppyExecuteReadWrite,
Irp );
KeLowerIrql( oldlvl );
DPRINT( "oldlvl = %x\n", oldlvl );
return STATUS_PENDING;
}
@ -473,3 +503,4 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
}
/* EOF */

View file

@ -116,6 +116,8 @@ typedef struct _FLOPPY_MEDIA_TYPE
ULONG BytesPerSector;
} FLOPPY_MEDIA_TYPE;
extern const FLOPPY_MEDIA_TYPE MediaTypes[];
#define FDP_DEBUG 0x02
#define FDP_SILENT_DCL_CLEAR 0x04
#define FDP_MSG 0x10
@ -123,19 +125,20 @@ typedef struct _FLOPPY_MEDIA_TYPE
#define FDP_INVERTED_DCL 0x80
// time to hold reset line low
#define FLOPPY_RESET_TIME 1000
#define FLOPPY_MOTOR_SPINUP_TIME -10000000
#define FLOPPY_MOTOR_SPINDOWN_TIME -30000000
#define FLOPPY_RECAL_TIMEOUT -5000000
#define FLOPPY_RESET_TIME 50000
#define FLOPPY_MOTOR_SPINUP_TIME -15000000
#define FLOPPY_MOTOR_SPINDOWN_TIME -50000000
#define FLOPPY_RECAL_TIMEOUT -30000000
typedef BOOLEAN (*FloppyIsrStateRoutine)( PCONTROLLER_OBJECT Controller );
typedef PIO_DPC_ROUTINE FloppyDpcStateRoutine;
typedef struct _FLOPPY_DEVICE_EXTENSION
{
PCONTROLLER_OBJECT Controller;
CHAR DriveSelect;
ULONG MediaType; // Media type index
PCONTROLLER_OBJECT Controller;
CHAR DriveSelect;
CHAR Cyl; // current cylinder
ULONG MediaType; // Media type index
} FLOPPY_DEVICE_EXTENSION, *PFLOPPY_DEVICE_EXTENSION;
typedef struct _FLOPPY_CONTROLLER_EXTENSION
@ -160,9 +163,6 @@ typedef struct _FLOPPY_CONTROLLER_EXTENSION
KDPC MotorSpindownDpc; // DPC for motor spin down
PADAPTER_OBJECT AdapterObject; // Adapter object for dma
PVOID MapRegisterBase;
DWORD CurrentOffset;
DWORD CurrentLength; // offset and length of next operation
PVOID CurrentVa; // current VA offset for IoMapTransfer
} FLOPPY_CONTROLLER_EXTENSION, *PFLOPPY_CONTROLLER_EXTENSION;
typedef struct _FLOPPY_CONTROLLER_PARAMETERS
@ -202,6 +202,11 @@ VOID FloppyMotorSpinupDpc( PKDPC Dpc,
PVOID Arg1,
PVOID Arg2 );
VOID FloppySeekDpc( PKDPC Dpc,
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context );
VOID FloppyMotorSpindownDpc( PKDPC Dpc,
PVOID Context,
PVOID Arg1,

View file

@ -5,6 +5,7 @@
***********************************************************************/
#include <ddk/ntddk.h>
#define NDEBUG
#include <debug.h>
#include "floppy.h"
@ -15,12 +16,13 @@
BOOLEAN FloppyIsrDetect( PCONTROLLER_OBJECT Controller )
{
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension;
// Issue read interrupt status, and store the results
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SNS_INTR );
KeStallExecutionProcessor( 1000 );
ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase );
KeStallExecutionProcessor( 1000 );
FloppyReadDATA( ControllerExtension->PortBase ); // ignore cyl
DeviceExtension->Cyl = FloppyReadDATA( ControllerExtension->PortBase );
// now queue DPC to set the event
IoRequestDpc( ControllerExtension->Device,
0,
@ -106,7 +108,6 @@ BOOLEAN FloppyIsrReadWrite( PCONTROLLER_OBJECT Controller )
// read result registers from read or write command, and queue dpc to start next operation
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
CHECKPOINT1;
ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase );
KeStallExecutionProcessor( 1000 );
ControllerExtension->St1 = FloppyReadDATA( ControllerExtension->PortBase );
@ -120,7 +121,6 @@ BOOLEAN FloppyIsrReadWrite( PCONTROLLER_OBJECT Controller )
FloppyReadDATA( ControllerExtension->PortBase ); // sector
KeStallExecutionProcessor( 1000 );
ControllerExtension->SectorSizeCode = FloppyReadDATA( ControllerExtension->PortBase );
CHECKPOINT1;
IoRequestDpc( ControllerExtension->Device,
ControllerExtension->Irp,
Controller );
@ -138,7 +138,9 @@ BOOLEAN FloppyIsr(PKINTERRUPT Interrupt, PVOID ServiceContext)
// need to make sure interrupt is for us, and add some delay for the damn FDC
// without the delay, even though the thing has interrupted, it's still not ready
// for us to read the data register.
KeStallExecutionProcessor( 1000 );
Byte = FloppyReadMSTAT( ControllerExtension->PortBase );
KeStallExecutionProcessor( 1000 );
if( Byte == 0 )
{
DPRINT( "Ignoring interrupt, MSTAT = 0\n" );