mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 17:44:45 +00:00
Massive floppy work
svn path=/trunk/; revision=1757
This commit is contained in:
parent
6b46ea08e7
commit
d8538e9795
5 changed files with 761 additions and 449 deletions
|
@ -1,20 +1,28 @@
|
||||||
# $Id: Makefile,v 1.5 2000/12/08 00:43:45 ekohl Exp $
|
# $Id: Makefile,v 1.6 2001/03/31 15:53:56 phreak Exp $
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
PATH_TO_TOP = ../../..
|
PATH_TO_TOP = ../../..
|
||||||
|
|
||||||
TARGET=floppy
|
TARGET=floppy
|
||||||
|
|
||||||
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
|
OBJECTS = floppy.o isr.o dpc.o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
|
||||||
|
|
||||||
CFLAGS = -I.
|
CFLAGS = -I.
|
||||||
|
|
||||||
all: $(TARGET).sys
|
all: $(TARGET).sys
|
||||||
|
|
||||||
|
floppy.o: floppy.h
|
||||||
|
|
||||||
|
isr.o: floppy.h
|
||||||
|
|
||||||
|
dpc.o: floppy.h
|
||||||
|
|
||||||
.phony: all
|
.phony: all
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
- $(RM) $(TARGET).o
|
- $(RM) floppy.o
|
||||||
|
- $(RM) isr.o
|
||||||
|
- $(RM) dpc.o
|
||||||
- $(RM) $(TARGET).coff
|
- $(RM) $(TARGET).coff
|
||||||
- $(RM) junk.tmp
|
- $(RM) junk.tmp
|
||||||
- $(RM) base.tmp
|
- $(RM) base.tmp
|
||||||
|
|
156
reactos/drivers/dd/floppy/dpc.c
Normal file
156
reactos/drivers/dd/floppy/dpc.c
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* Defered procedure calls for floppy disk driver, reactos project, created *
|
||||||
|
* by Phillip Susi on 2/25/2001. This software is published under the GNU *
|
||||||
|
* general public license, see the README file for more details *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include "floppy.h"
|
||||||
|
|
||||||
|
|
||||||
|
VOID FloppyDpc( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
CHECKPOINT1;
|
||||||
|
ControllerExtension->DpcState( Dpc,
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
Context );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID FloppyDpcDetect( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
CHECKPOINT1;
|
||||||
|
KeSetEvent( &ControllerExtension->Event, 0, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FloppyDpcFailIrp( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
CHECKPOINT1;
|
||||||
|
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
|
||||||
|
IoCompleteRequest( Irp, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FloppyMotorSpindownDpc( PKDPC Dpc,
|
||||||
|
PVOID Context,
|
||||||
|
PVOID Arg1,
|
||||||
|
PVOID Arg2 )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
CHECKPOINT1;
|
||||||
|
// queue call to turn off motor
|
||||||
|
IoAllocateController( Controller,
|
||||||
|
ControllerExtension->Device,
|
||||||
|
FloppyExecuteSpindown,
|
||||||
|
ControllerExtension );
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FloppyMotorSpinupDpc( PKDPC Dpc,
|
||||||
|
PVOID Context,
|
||||||
|
PVOID Arg1,
|
||||||
|
PVOID Arg2 )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
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
|
||||||
|
KeSetTimer( &ControllerExtension->SpinupTimer,
|
||||||
|
Timeout,
|
||||||
|
&ControllerExtension->MotorSpindownDpc );
|
||||||
|
DPRINT( "Motor spun up, retrying operation\n" );
|
||||||
|
ControllerExtension->MotorOn = DeviceExtension->DriveSelect;
|
||||||
|
IoFreeController( Controller );
|
||||||
|
IoAllocateController( Controller,
|
||||||
|
ControllerExtension->Device,
|
||||||
|
FloppyExecuteReadWrite,
|
||||||
|
ControllerExtension->Irp );
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FloppyDpcReadWrite( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)Context;
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
DWORD SectorSize = 128 << ControllerExtension->SectorSizeCode;
|
||||||
|
|
||||||
|
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;
|
||||||
|
IoCompleteRequest( Irp, 0 );
|
||||||
|
CHECKPOINT1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ControllerExtension->CurrentOffset += SectorSize;
|
||||||
|
ControllerExtension->CurrentLength -= SectorSize;
|
||||||
|
(char *)ControllerExtension->CurrentVa += SectorSize;
|
||||||
|
// if there is more IO to be done, restart execute routine to issue next read
|
||||||
|
if( ControllerExtension->CurrentLength )
|
||||||
|
{
|
||||||
|
CHECKPOINT1;
|
||||||
|
if( FloppyExecuteReadWrite( DeviceObject,
|
||||||
|
Irp,
|
||||||
|
ControllerExtension->MapRegisterBase,
|
||||||
|
Irp ) == DeallocateObject )
|
||||||
|
IoFreeController( Controller );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CHECKPOINT1;
|
||||||
|
// oetherwise, complete the Irp
|
||||||
|
IoCompleteRequest( Irp, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VOID FloppyDpcDetectMedia( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
DPRINT( "Read ID failed: ST1 = %2x\n", ControllerExtension->St1 );
|
||||||
|
Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
|
||||||
|
IoCompleteRequest( Irp, 0 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// set media type, and restart the IRP from the beginning
|
||||||
|
((PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension)->MediaType = 0;
|
||||||
|
DPRINT( "Media detected, restarting IRP\n" );
|
||||||
|
// don't forget to free the controller so that the now queued routine may execute
|
||||||
|
IoFreeController( Controller );
|
||||||
|
|
||||||
|
IoAllocateController( Controller,
|
||||||
|
DeviceObject,
|
||||||
|
FloppyExecuteReadWrite,
|
||||||
|
Irp );
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
*
|
*
|
||||||
* Modification History:
|
* Modification History:
|
||||||
* 08/19/98 RJJ Created.
|
* 08/19/98 RJJ Created.
|
||||||
|
* 01/31/01 PJS Heavy rewrite, most of code thrown out
|
||||||
*
|
*
|
||||||
* To do:
|
* To do:
|
||||||
* FIXME: get it working
|
* FIXME: get it working
|
||||||
|
@ -19,390 +20,37 @@
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#define VERSION "V0.0.1"
|
|
||||||
|
|
||||||
/* --------------------------------------------------- File Statics */
|
|
||||||
|
|
||||||
/* from linux drivers/block/floppy.c */
|
|
||||||
#define FLOPPY_MAX_REPLIES (16)
|
|
||||||
|
|
||||||
typedef struct _FLOPPY_DEVICE_EXTENSION
|
|
||||||
{
|
|
||||||
} FLOPPY_DEVICE_EXTENSION, *PFLOPPY_DEVICE_EXTENSION;
|
|
||||||
|
|
||||||
typedef struct _FLOPPY_CONTROLLER_EXTENSION
|
|
||||||
{
|
|
||||||
PKINTERRUPT Interrupt;
|
|
||||||
KSPIN_LOCK SpinLock;
|
|
||||||
FLOPPY_CONTROLLER_TYPE FDCType;
|
|
||||||
ULONG Number;
|
|
||||||
ULONG PortBase;
|
|
||||||
ULONG Vector;
|
|
||||||
} FLOPPY_CONTROLLER_EXTENSION, *PFLOPPY_CONTROLLER_EXTENSION;
|
|
||||||
|
|
||||||
typedef struct _FLOPPY_CONTROLLER_PARAMETERS
|
|
||||||
{
|
|
||||||
ULONG PortBase;
|
|
||||||
ULONG Vector;
|
|
||||||
ULONG IrqL;
|
|
||||||
ULONG SynchronizeIrqL;
|
|
||||||
KINTERRUPT_MODE InterruptMode;
|
|
||||||
KAFFINITY Affinity;
|
|
||||||
} FLOPPY_CONTROLLER_PARAMETERS, *PFLOPPY_CONTROLLER_PARAMETERS;
|
|
||||||
|
|
||||||
#define FLOPPY_MAX_CONTROLLERS 2
|
|
||||||
FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] =
|
FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] =
|
||||||
{
|
{
|
||||||
{0x03f0, 6, 6, 6, LevelSensitive, 0xffff},
|
{0x03f0, 6, 6, 2, 6, LevelSensitive, 0xffff}
|
||||||
{0x0370, 6, 6, 6, LevelSensitive, 0xffff},
|
// {0x0370, 6, 6, 6, LevelSensitive, 0xffff},
|
||||||
};
|
};
|
||||||
|
|
||||||
FLOPPY_DEVICE_PARAMETERS DeviceTypes[] =
|
const FLOPPY_MEDIA_TYPE MediaTypes[] = {
|
||||||
{
|
{ 0x02, 9, 80, 18, 512 },
|
||||||
/* Unknown */
|
{ 0, 0, 0, 0, 0 } };
|
||||||
{0, 500, 16, 16, 8000, 1000, 3000, 0, 20, 5, 80, 3000, 20, {3,1,2,0,2}, 0, 0, { 7, 4, 8, 2, 1, 5, 3,10}, 1500, 0, "unknown"},
|
|
||||||
/* 5 1/4 360 KB PC*/
|
|
||||||
{1, 300, 16, 16, 8000, 1000, 3000, 0, 20, 5, 40, 3000, 17, {3,1,2,0,2}, 0, 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 1500, 1, "360K PC"},
|
|
||||||
/* 5 1/4 HD AT*/
|
|
||||||
{2, 500, 16, 16, 6000, 400, 3000, 14, 20, 6, 83, 3000, 17, {3,1,2,0,2}, 0, 0, { 2, 5, 6,23,10,20,11, 0}, 1500, 2, "1.2M"},
|
|
||||||
/* 3 1/2 DD*/
|
|
||||||
{3, 250, 16, 16, 3000, 1000, 3000, 0, 20, 5, 83, 3000, 20, {3,1,2,0,2}, 0, 0, { 4,22,21,30, 3, 0, 0, 0}, 1500, 4, "720k"},
|
|
||||||
/* 3 1/2 HD*/
|
|
||||||
{4, 500, 16, 16, 4000, 400, 3000, 10, 20, 5, 83, 3000, 20, {3,1,2,0,2}, 0, 0, { 7, 4,25,22,31,21,29,11}, 1500, 7, "1.44M"},
|
|
||||||
/* 3 1/2 ED*/
|
|
||||||
{5, 1000, 15, 8, 3000, 400, 3000, 10, 20, 5, 83, 3000, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 1500, 8, "2.88M AMI BIOS"},
|
|
||||||
/* 3 1/2 ED*/
|
|
||||||
{6, 1000, 15, 8, 3000, 400, 3000, 10, 20, 5, 83, 3000, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 1500, 8, "2.88M"}
|
|
||||||
};
|
|
||||||
|
|
||||||
static BOOLEAN FloppyInitialized = FALSE;
|
|
||||||
|
|
||||||
/* Bits of main status register */
|
|
||||||
#define STATUS_BUSYMASK (0x0f)
|
|
||||||
#define STATUS_BUSY (0x10)
|
|
||||||
#define STATUS_DMA (0x20)
|
|
||||||
#define STATUS_DIR (0x40)
|
|
||||||
#define STATUS_READY (0x80)
|
|
||||||
|
|
||||||
#define FLOPPY_STATUS (4)
|
|
||||||
#define FLOPPY_DATA (5)
|
|
||||||
|
|
||||||
#define FLOPPY_CMD_UNLK_FIFO 0x14
|
|
||||||
#define FLOPPY_CMD_LOCK_FIFO 0x94
|
|
||||||
|
|
||||||
/* ------------------------------------------------------ Functions */
|
|
||||||
|
|
||||||
static int
|
|
||||||
FloppyReadSTAT(ULONG PortBase)
|
|
||||||
{
|
|
||||||
return(READ_PORT_UCHAR((PUCHAR)(PortBase + FLOPPY_STATUS)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* waits until the fdc becomes ready */
|
|
||||||
static int
|
|
||||||
FloppyWaitUntilReady(ULONG PortBase)
|
|
||||||
{
|
|
||||||
int Retries;
|
|
||||||
int Status;
|
|
||||||
|
|
||||||
for (Retries = 0; Retries < FLOPPY_MAX_STAT_RETRIES; Retries++)
|
|
||||||
{
|
|
||||||
Status = FloppyReadSTAT(PortBase);
|
|
||||||
if (Status & STATUS_READY)
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FloppyInitialized)
|
|
||||||
{
|
|
||||||
DPRINT("Getstatus times out (%x) on fdc %d\n",
|
|
||||||
Status,
|
|
||||||
PortBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
FloppyWriteData(ULONG PortBase, BYTE Byte)
|
|
||||||
{
|
|
||||||
WRITE_PORT_UCHAR((PUCHAR)(PortBase + FLOPPY_DATA), Byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sends a command byte to the fdc */
|
|
||||||
static BOOLEAN
|
|
||||||
FloppyWriteCommandByte(ULONG PortBase, BYTE Byte)
|
|
||||||
{
|
|
||||||
int Status;
|
|
||||||
|
|
||||||
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY)
|
|
||||||
{
|
|
||||||
FloppyWriteData(PortBase, Byte);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FloppyInitialized)
|
|
||||||
{
|
|
||||||
DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
|
|
||||||
Byte,
|
|
||||||
PortBase,
|
|
||||||
Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* gets the response from the fdc */
|
|
||||||
static int
|
|
||||||
FloppyReadResultCode(ULONG PortBase, PUCHAR Result)
|
|
||||||
{
|
|
||||||
int Replies;
|
|
||||||
int Status;
|
|
||||||
|
|
||||||
for (Replies = 0; Replies < FLOPPY_MAX_REPLIES; Replies++)
|
|
||||||
{
|
|
||||||
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
|
|
||||||
if ((Status & ~STATUS_BUSY) == STATUS_READY)
|
|
||||||
{
|
|
||||||
return Replies;
|
|
||||||
}
|
|
||||||
if (Status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
|
|
||||||
{
|
|
||||||
Result[Replies] = READ_PORT_UCHAR((PUCHAR)(PortBase + FLOPPY_DATA));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("FloppyReadResultCode: break\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FloppyInitialized)
|
|
||||||
{
|
|
||||||
DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
|
|
||||||
PortBase,
|
|
||||||
Status,
|
|
||||||
Replies);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MORE_OUTPUT -2
|
|
||||||
/* does the fdc need more output? */
|
|
||||||
static int
|
|
||||||
FloppyNeedsMoreOutput(ULONG PortBase, PUCHAR Result)
|
|
||||||
{
|
|
||||||
int Status;
|
|
||||||
|
|
||||||
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
|
|
||||||
return -1;
|
|
||||||
if ((Status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
|
|
||||||
{
|
|
||||||
return FLOPPY_NEEDS_OUTPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FloppyReadResultCode(PortBase, Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOLEAN
|
|
||||||
FloppyConfigure(ULONG PortBase, BOOLEAN DisableFIFO, BYTE FIFODepth)
|
|
||||||
{
|
|
||||||
BYTE Result[FLOPPY_MAX_REPLIES];
|
|
||||||
|
|
||||||
/* Turn on FIFO */
|
|
||||||
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_CFG_FIFO);
|
|
||||||
if (FloppyNeedsMoreOutput(PortBase, Result) != FLOPPY_NEEDS_OUTPUT)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
FloppyWriteCommandByte(PortBase, 0);
|
|
||||||
FloppyWriteCommandByte(PortBase,
|
|
||||||
0x10 |
|
|
||||||
(DisableFIFO ? 0x20 : 0x00) |
|
|
||||||
(FIFODepth & 0x0f));
|
|
||||||
/* pre-compensation from track 0 upwards */
|
|
||||||
FloppyWriteCommandByte(PortBase, 0);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FloppyGetControllerVersion
|
|
||||||
*
|
|
||||||
* DESCRIPTION
|
|
||||||
* Get the type/version of the floppy controller
|
|
||||||
*
|
|
||||||
* RUN LEVEL:
|
|
||||||
* PASSIVE_LEVEL
|
|
||||||
*
|
|
||||||
* ARGUMENTS:
|
|
||||||
* IN OUT PFLOPPY_DEVICE_EXTENSION DeviceExtension
|
|
||||||
*
|
|
||||||
* RETURNS:
|
|
||||||
* BOOL success or failure
|
|
||||||
*
|
|
||||||
* COMMENTS:
|
|
||||||
* This routine (get_fdc_version) was originally written by David C. Niemi
|
|
||||||
*/
|
|
||||||
static BOOLEAN
|
|
||||||
FloppyGetControllerVersion(IN PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
|
|
||||||
OUT PFLOPPY_CONTROLLER_TYPE ControllerType)
|
|
||||||
{
|
|
||||||
UCHAR Result[FLOPPY_MAX_REPLIES];
|
|
||||||
int ResultLength;
|
|
||||||
|
|
||||||
/* 82072 and better know DUMPREGS */
|
|
||||||
if (!FloppyWriteCommandByte(ControllerParameters->PortBase,
|
|
||||||
FLOPPY_CMD_DUMP_FDC))
|
|
||||||
{
|
|
||||||
DPRINT("Failed to write command byte\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
ResultLength = FloppyReadResultCode(ControllerParameters->PortBase,
|
|
||||||
Result);
|
|
||||||
if (ResultLength < 0)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 8272a/765 don't know DUMPREGS */
|
|
||||||
if ((ResultLength == 1) && (Result[0] == 0x80))
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d is an 8272A\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_8272A;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (ResultLength != 10)
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d init: DUMP_FDC: unexpected return of %d bytes.\n",
|
|
||||||
ControllerParameters->PortBase,
|
|
||||||
ResultLength);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FloppyConfigure(ControllerParameters->PortBase, FALSE, 0x0a))
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d is an 82072\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_82072;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
FloppyWriteCommandByte(ControllerParameters->PortBase, FLOPPY_CMD_PPND_RW);
|
|
||||||
if (FloppyNeedsMoreOutput(ControllerParameters->PortBase, Result) ==
|
|
||||||
FLOPPY_NEEDS_OUTPUT)
|
|
||||||
{
|
|
||||||
FloppyWriteCommandByte(ControllerParameters->PortBase, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d is an 82072A\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_82072A;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pre-1991 82077, doesn't know LOCK/UNLOCK */
|
|
||||||
FloppyWriteCommandByte(ControllerParameters->PortBase, FLOPPY_CMD_UNLK_FIFO);
|
|
||||||
ResultLength = FloppyReadResultCode(ControllerParameters->PortBase,
|
|
||||||
Result);
|
|
||||||
if ((ResultLength == 1) && (Result[0] == 0x80))
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d is a pre-1991 82077\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_82077_ORIG;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if ((ResultLength != 1) || (Result[0] != 0x00))
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
|
|
||||||
ControllerParameters->PortBase,
|
|
||||||
ResultLength);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Revised 82077AA passes all the tests */
|
|
||||||
FloppyWriteCommandByte(ControllerParameters->PortBase, FLOPPY_CMD_PARTID);
|
|
||||||
ResultLength = FloppyReadResultCode(ControllerParameters->PortBase,
|
|
||||||
Result);
|
|
||||||
if (ResultLength != 1)
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d init: PARTID: unexpected return of %d bytes.\n",
|
|
||||||
ControllerParameters->PortBase,
|
|
||||||
ResultLength);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (Result[0] == 0x80)
|
|
||||||
{
|
|
||||||
DPRINT("FDC %d is a post-1991 82077\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_82077;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
switch (Result[0] >> 5)
|
|
||||||
{
|
|
||||||
case 0x0:
|
|
||||||
/* Either a 82078-1 or a 82078SL running at 5Volt */
|
|
||||||
DPRINT("FDC %d is an 82078.\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_82078;
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case 0x1:
|
|
||||||
DPRINT("FDC %d is a 44pin 82078\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_82078;
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case 0x2:
|
|
||||||
DPRINT("FDC %d is a S82078B\n", ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_S82078B;
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case 0x3:
|
|
||||||
DPRINT("FDC %d is a National Semiconductor PC87306\n",
|
|
||||||
ControllerParameters->PortBase);
|
|
||||||
*ControllerType = FDC_87306;
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINT("FDC %d init: 82078 variant with unknown PARTID=%d.\n",
|
|
||||||
ControllerParameters->PortBase,
|
|
||||||
Result[0] >> 5);
|
|
||||||
*ControllerType = FDC_82078_UNKN;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOLEAN
|
|
||||||
FloppyIsr(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
|
||||||
{
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
||||||
PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
|
PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
|
||||||
int Index)
|
int Index)
|
||||||
{
|
{
|
||||||
FLOPPY_CONTROLLER_TYPE ControllerType;
|
|
||||||
PCONTROLLER_OBJECT ControllerObject;
|
PCONTROLLER_OBJECT ControllerObject;
|
||||||
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
|
||||||
|
PFLOPPY_DEVICE_EXTENSION DeviceExtension;
|
||||||
UNICODE_STRING DeviceName;
|
UNICODE_STRING DeviceName;
|
||||||
UNICODE_STRING SymlinkName;
|
UNICODE_STRING SymlinkName;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PCONFIGURATION_INFORMATION ConfigInfo;
|
PCONFIGURATION_INFORMATION ConfigInfo;
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
/* Detect controller and determine type */
|
BYTE Byte;
|
||||||
if (!FloppyGetControllerVersion(ControllerParameters, &ControllerType))
|
int c;
|
||||||
{
|
PCONFIGURATION_INFORMATION Config;
|
||||||
DPRINT("Failed to get controller version\n");
|
DEVICE_DESCRIPTION DeviceDescription;
|
||||||
return FALSE;
|
ULONG MaxMapRegs;
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Register port ranges and interrupts with HAL */
|
/* FIXME: Register port ranges and interrupts with HAL */
|
||||||
|
|
||||||
|
@ -421,15 +69,18 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
||||||
ControllerExtension->Number = Index;
|
ControllerExtension->Number = Index;
|
||||||
ControllerExtension->PortBase = ControllerParameters->PortBase;
|
ControllerExtension->PortBase = ControllerParameters->PortBase;
|
||||||
ControllerExtension->Vector = ControllerParameters->Vector;
|
ControllerExtension->Vector = ControllerParameters->Vector;
|
||||||
ControllerExtension->FDCType = ControllerType;
|
KeInitializeEvent( &ControllerExtension->Event, SynchronizationEvent, FALSE );
|
||||||
|
ControllerExtension->Device = 0; // no active device
|
||||||
|
ControllerExtension->Irp = 0; // no active IRP
|
||||||
/* Initialize the spin lock in the controller extension */
|
/* Initialize the spin lock in the controller extension */
|
||||||
KeInitializeSpinLock(&ControllerExtension->SpinLock);
|
KeInitializeSpinLock(&ControllerExtension->SpinLock);
|
||||||
|
ControllerExtension->IsrState = FloppyIsrDetect;
|
||||||
|
ControllerExtension->DpcState = FloppyDpcDetect;
|
||||||
|
|
||||||
/* Register an interrupt handler for this controller */
|
/* Register an interrupt handler for this controller */
|
||||||
Status = IoConnectInterrupt(&ControllerExtension->Interrupt,
|
Status = IoConnectInterrupt(&ControllerExtension->Interrupt,
|
||||||
FloppyIsr,
|
FloppyIsr,
|
||||||
ControllerExtension,
|
ControllerObject,
|
||||||
&ControllerExtension->SpinLock,
|
&ControllerExtension->SpinLock,
|
||||||
ControllerExtension->Vector,
|
ControllerExtension->Vector,
|
||||||
ControllerParameters->IrqL,
|
ControllerParameters->IrqL,
|
||||||
|
@ -442,12 +93,26 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
||||||
{
|
{
|
||||||
DPRINT("Could not Connect Interrupt %d\n",
|
DPRINT("Could not Connect Interrupt %d\n",
|
||||||
ControllerExtension->Vector);
|
ControllerExtension->Vector);
|
||||||
IoDeleteController(ControllerObject);
|
goto controllercleanup;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: setup DMA stuff for controller */
|
/* setup DMA stuff for controller */
|
||||||
|
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
|
||||||
|
DeviceDescription.Master = FALSE;
|
||||||
|
DeviceDescription.ScatterGather = FALSE;
|
||||||
|
DeviceDescription.AutoInitialize = FALSE;
|
||||||
|
DeviceDescription.Dma32BitAddress = FALSE;
|
||||||
|
DeviceDescription.DmaChannel = ControllerParameters->DmaChannel;
|
||||||
|
DeviceDescription.InterfaceType = Isa;
|
||||||
|
// DeviceDescription.DmaWidth = Width8Bits;
|
||||||
|
ControllerExtension->AdapterObject = HalGetAdapter( &DeviceDescription, &MaxMapRegs );
|
||||||
|
if( ControllerExtension->AdapterObject == NULL )
|
||||||
|
{
|
||||||
|
DPRINT1( "Could not get adapter object\n" );
|
||||||
|
goto interruptcleanup;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Check for each possible drive and create devices for them */
|
/* Check for each possible drive and create devices for them */
|
||||||
for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++)
|
for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++)
|
||||||
|
@ -468,40 +133,292 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
||||||
&DeviceObject);
|
&DeviceObject);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
IoDisconnectInterrupt(ControllerExtension->Interrupt);
|
goto interruptcleanup;
|
||||||
IoDeleteController(ControllerObject);
|
|
||||||
}
|
}
|
||||||
|
DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
DeviceExtension->DriveSelect = 0;
|
||||||
|
DeviceExtension->Controller = ControllerObject;
|
||||||
|
DeviceExtension->MediaType = ~0;
|
||||||
|
ControllerExtension->MotorOn = ~0;
|
||||||
|
// set up DPC
|
||||||
|
ControllerExtension->Device = DeviceObject;
|
||||||
|
KeInitializeDpc( &ControllerExtension->MotorSpinupDpc,
|
||||||
|
FloppyMotorSpinupDpc,
|
||||||
|
ControllerObject );
|
||||||
|
KeInitializeDpc( &ControllerExtension->MotorSpindownDpc,
|
||||||
|
FloppyMotorSpindownDpc,
|
||||||
|
ControllerObject );
|
||||||
|
KeInitializeTimer( &ControllerExtension->SpinupTimer );
|
||||||
|
IoInitializeDpcRequest( DeviceObject, FloppyDpc );
|
||||||
|
// reset controller and wait for interrupt
|
||||||
|
DPRINT( "Controller Off\n" );
|
||||||
|
FloppyWriteDOR( ControllerExtension->PortBase, 0 );
|
||||||
|
// let controller reset for at least FLOPPY_RESET_TIME
|
||||||
|
KeStallExecutionProcessor( FLOPPY_RESET_TIME );
|
||||||
|
DPRINT( "Controller On\n" );
|
||||||
|
FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA );
|
||||||
|
// wait for interrupt now
|
||||||
|
Timeout.QuadPart = -10000000;
|
||||||
|
Status = KeWaitForSingleObject( &ControllerExtension->Event,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
&Timeout );
|
||||||
|
if( Status != STATUS_WAIT_0 )
|
||||||
|
{
|
||||||
|
DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status );
|
||||||
|
goto devicecleanup;
|
||||||
|
}
|
||||||
|
// ok, so we have an FDC, now check for drives
|
||||||
|
// aparently the sense drive status command does not work on any FDC I can find
|
||||||
|
// so instead we will just have to assume a 1.44 meg 3.5 inch floppy. At some
|
||||||
|
// point we should get the bios disk parameters passed in to the kernel at boot
|
||||||
|
// and stored in the HARDWARE registry key for us to pick up here.
|
||||||
|
|
||||||
|
// turn on motor, wait for spinup time, and recalibrate the drive
|
||||||
|
FloppyWriteDOR( ControllerExtension->PortBase, FLOPPY_DRIVE0_ON );
|
||||||
|
Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME;
|
||||||
|
KeDelayExecutionThread( KernelMode, FALSE, &Timeout );
|
||||||
|
DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL );
|
||||||
|
DPRINT( "MSTAT: %2x\n", FloppyReadMSTAT( ControllerExtension->PortBase ) );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, 0 ); // drive select
|
||||||
|
Timeout.QuadPart = FLOPPY_RECAL_TIMEOUT;
|
||||||
|
Status = KeWaitForSingleObject( &ControllerExtension->Event,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
&Timeout );
|
||||||
|
if( Status != STATUS_WAIT_0 )
|
||||||
|
{
|
||||||
|
DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status );
|
||||||
|
goto devicecleanup;
|
||||||
|
}
|
||||||
|
if( ControllerExtension->St0 != FLOPPY_ST0_SEEKGD )
|
||||||
|
{
|
||||||
|
DbgPrint( "Floppy: error recalibrating drive, ST0: %2x\n", (DWORD)ControllerExtension->St0 );
|
||||||
|
goto interruptcleanup;
|
||||||
|
}
|
||||||
|
// 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 */
|
/* Initialize the device */
|
||||||
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
||||||
DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
DeviceObject->AlignmentRequirement = FILE_512_BYTE_ALIGNMENT;
|
||||||
|
// change state machine, no interrupt expected
|
||||||
/* count new floppy drive */
|
ControllerExtension->IsrState = FloppyIsrUnexpected;
|
||||||
/* NOTE: HalIoAssignDriveLetters assigns the drive letters! */
|
Config = IoGetConfigurationInformation();
|
||||||
ConfigInfo = IoGetConfigurationInformation ();
|
Config->FloppyCount++;
|
||||||
ConfigInfo->FloppyCount++;
|
// call IoAllocateAdapterChannel, and wait for execution routine to be given the channel
|
||||||
|
CHECKPOINT;
|
||||||
|
Status = IoAllocateAdapterChannel( ControllerExtension->AdapterObject,
|
||||||
|
DeviceObject,
|
||||||
|
0x3000/PAGESIZE, // max track size is 12k
|
||||||
|
FloppyAdapterControl,
|
||||||
|
ControllerExtension );
|
||||||
|
if( !NT_SUCCESS( Status ) )
|
||||||
|
{
|
||||||
|
DPRINT1( "Error: IoAllocateAdapterChannel returned %x\n", Status );
|
||||||
|
goto interruptcleanup;
|
||||||
|
}
|
||||||
|
CHECKPOINT;
|
||||||
|
Status = KeWaitForSingleObject( &ControllerExtension->Event,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
&Timeout );
|
||||||
|
CHECKPOINT;
|
||||||
|
if( Status != STATUS_WAIT_0 )
|
||||||
|
{
|
||||||
|
DPRINT1( "Error: KeWaitForSingleObject returned: %x\n", Status );
|
||||||
|
goto interruptcleanup;
|
||||||
|
}
|
||||||
|
// Ok, we own the adapter object, from now on we can just IoMapTransfer, and not
|
||||||
|
// bother releasing the adapter ever.
|
||||||
|
DbgPrint( "Floppy drive initialized\n" );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
devicecleanup:
|
||||||
|
IoDeleteDevice( DeviceObject );
|
||||||
|
interruptcleanup:
|
||||||
|
IoDisconnectInterrupt(ControllerExtension->Interrupt);
|
||||||
|
controllercleanup:
|
||||||
|
// turn off controller
|
||||||
|
FloppyWriteDOR( ControllerExtension->PortBase, 0 );
|
||||||
|
IoDeleteController(ControllerObject);
|
||||||
|
for(;;);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL FloppyStartIo(PDEVICE_OBJECT DeviceObject,
|
IO_ALLOCATION_ACTION FloppyExecuteSpindown( PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp,
|
||||||
|
PVOID MapRegisterbase,
|
||||||
|
PVOID Context )
|
||||||
{
|
{
|
||||||
DPRINT("FloppyStartIo\n");
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension= (PFLOPPY_CONTROLLER_EXTENSION)Context;
|
||||||
|
|
||||||
|
// turn off motor, and return
|
||||||
|
DPRINT( "Spinning down motor\n" );
|
||||||
|
ControllerExtension->MotorOn = ~0;
|
||||||
|
FloppyWriteDOR( ControllerExtension->PortBase,
|
||||||
|
FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA );
|
||||||
|
return DeallocateObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IO_ALLOCATION_ACTION FloppyExecuteReadWrite( PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID MapRegisterbase,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension;
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
BOOLEAN WriteToDevice;
|
||||||
|
UCHAR Cyl, Sector, Head;
|
||||||
|
|
||||||
|
ControllerExtension->Irp = Irp = (PIRP)Context;
|
||||||
|
ControllerExtension->Device = DeviceObject;
|
||||||
|
Timeout.QuadPart = FLOPPY_MOTOR_SPINUP_TIME;
|
||||||
|
CHECKPOINT;
|
||||||
|
WriteToDevice = IoGetCurrentIrpStackLocation( Irp )->MajorFunction == IRP_MJ_WRITE ? TRUE : FALSE;
|
||||||
|
// verify drive is spun up and selected
|
||||||
|
if( ControllerExtension->MotorOn != DeviceExtension->DriveSelect )
|
||||||
|
{
|
||||||
|
// turn on and select drive, and allow it to spin up
|
||||||
|
// FloppyMotorSpinupDpc will restart this operation once motor is spun up
|
||||||
|
DPRINT( "Motor not on, turning it on now\n" );
|
||||||
|
FloppyWriteDOR( ControllerExtension->PortBase,
|
||||||
|
DeviceExtension->DriveSelect ? FLOPPY_DRIVE1_ON : FLOPPY_DRIVE0_ON );
|
||||||
|
// cancel possible spindown timer first
|
||||||
|
KeCancelTimer( &ControllerExtension->SpinupTimer );
|
||||||
|
KeSetTimerEx( &ControllerExtension->SpinupTimer,
|
||||||
|
Timeout,
|
||||||
|
0,
|
||||||
|
&ControllerExtension->MotorSpinupDpc );
|
||||||
|
return KeepObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify media content
|
||||||
|
if( FloppyReadDIR( ControllerExtension->PortBase ) & FLOPPY_DI_DSKCHNG )
|
||||||
|
{
|
||||||
|
// No disk is in the drive
|
||||||
|
DPRINT( "No disk is in the drive\n" );
|
||||||
|
Irp->IoStatus.Status = STATUS_NO_MEDIA;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest( Irp, 0 );
|
||||||
|
return DeallocateObject;
|
||||||
|
}
|
||||||
|
if( DeviceExtension->MediaType == ~0 )
|
||||||
|
{
|
||||||
|
// media is in disk, but we have not yet detected what kind it is,
|
||||||
|
// so detect it now
|
||||||
|
// First, we need to recalibrate the drive though
|
||||||
|
ControllerExtension->IsrState = FloppyIsrRecal;
|
||||||
|
DPRINT( "Recalibrating drive\n" );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RECAL );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, DeviceExtension->DriveSelect );
|
||||||
|
return KeepObject;
|
||||||
|
}
|
||||||
|
// looks like we have media in the drive.... do the read
|
||||||
|
// first, calculate geometry for read
|
||||||
|
Sector = ControllerExtension->CurrentOffset / MediaTypes[DeviceExtension->MediaType].BytesPerSector;
|
||||||
|
// absolute sector right now
|
||||||
|
Cyl = Sector / MediaTypes[DeviceExtension->MediaType].SectorsPerTrack;
|
||||||
|
Head = Cyl % MediaTypes[DeviceExtension->MediaType].Heads;
|
||||||
|
// 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 );
|
||||||
|
//set up DMA and issue read command
|
||||||
|
IoMapTransfer( ControllerExtension->AdapterObject,
|
||||||
|
Irp->MdlAddress,
|
||||||
|
ControllerExtension->MapRegisterBase,
|
||||||
|
ControllerExtension->CurrentVa,
|
||||||
|
&MediaTypes[DeviceExtension->MediaType].BytesPerSector,
|
||||||
|
WriteToDevice );
|
||||||
|
ControllerExtension->IsrState = FloppyIsrReadWrite;
|
||||||
|
ControllerExtension->DpcState = FloppyDpcReadWrite;
|
||||||
|
CHECKPOINT;
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_READ );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, ( Head << 2 ) | DeviceExtension->DriveSelect );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, Cyl );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, Head );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, Sector );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorSizeCode );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, MediaTypes[DeviceExtension->MediaType].SectorsPerTrack );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, 0 );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, 0xFF );
|
||||||
|
CHECKPOINT;
|
||||||
|
// eventually, the FDC will interrupt and we will read results then
|
||||||
|
return KeepObject;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL FloppyDispatchOpenClose(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS STDCALL FloppyDispatchOpenClose(PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT("FloppyDispatchOpenClose\n");
|
DPRINT("FloppyDispatchOpenClose\n");
|
||||||
return(STATUS_UNSUCCESSFUL);
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS STDCALL FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT("FloppyDispatchReadWrite\n");
|
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
return(STATUS_UNSUCCESSFUL);
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)DeviceExtension->Controller->ControllerExtension;
|
||||||
|
PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation( Irp );
|
||||||
|
KIRQL oldlvl;
|
||||||
|
|
||||||
|
if( Stk->Parameters.Read.ByteOffset.u.HighPart )
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
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 );
|
||||||
|
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;
|
||||||
|
IoMarkIrpPending( Irp );
|
||||||
|
KeRaiseIrql( DISPATCH_LEVEL, &oldlvl );
|
||||||
|
IoAllocateController( ((PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Controller,
|
||||||
|
DeviceObject,
|
||||||
|
FloppyExecuteReadWrite,
|
||||||
|
Irp );
|
||||||
|
KeLowerIrql( oldlvl );
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_ALLOCATION_ACTION FloppyAdapterControl( PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID MapRegisterBase,
|
||||||
|
PVOID Context )
|
||||||
|
{
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Context;
|
||||||
|
|
||||||
|
// just set the event, and return KeepObject
|
||||||
|
CHECKPOINT;
|
||||||
|
ControllerExtension->MapRegisterBase = MapRegisterBase;
|
||||||
|
KeSetEvent( &ControllerExtension->Event, 0, FALSE );
|
||||||
|
return KeepObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL FloppyDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
|
NTSTATUS STDCALL FloppyDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
@ -536,7 +453,6 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||||
DbgPrint("Floppy driver\n");
|
DbgPrint("Floppy driver\n");
|
||||||
|
|
||||||
/* Export other driver entry points... */
|
/* Export other driver entry points... */
|
||||||
DriverObject->DriverStartIo = FloppyStartIo;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite;
|
DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite;
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
|
|
||||||
#define FLOPPY_MAX_STAT_RETRIES 10000
|
|
||||||
|
|
||||||
#define FLOPPY_NEEDS_OUTPUT -2
|
|
||||||
//
|
//
|
||||||
// Floppy register definitions
|
// Floppy register definitions
|
||||||
//
|
//
|
||||||
|
|
||||||
#define FLOPPY_REG_DOR 0x0002
|
#define FLOPPY_REG_DOR 0x0002
|
||||||
|
#define FLOPPY_DOR_ENABLE 0x04
|
||||||
|
#define FLOPPY_DOR_DMA 0x08
|
||||||
|
#define FLOPPY_DOR_MOTOR0 0x10
|
||||||
|
#define FLOPPY_DOR_MOTOR1 0x20
|
||||||
|
#define FLOPPY_DRIVE0_ON ( FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA | FLOPPY_DOR_MOTOR0 )
|
||||||
|
#define FLOPPY_DRIVE1_ON ( FLOPPY_DOR_ENABLE | FLOPPY_DOR_DMA | FLOPPY_DOR_MOTOR1 | 1 )
|
||||||
#define FLOPPY_REG_MSTAT 0x0004
|
#define FLOPPY_REG_MSTAT 0x0004
|
||||||
#define FLOPPY_MS_DRV0BUSY 0x01
|
#define FLOPPY_MS_DRV0BUSY 0x01
|
||||||
#define FLOPPY_MS_DRV1BUSY 0x02
|
#define FLOPPY_MS_DRV1BUSY 0x02
|
||||||
|
@ -15,7 +17,9 @@
|
||||||
#define FLOPPY_MS_FDCBUSY 0x10
|
#define FLOPPY_MS_FDCBUSY 0x10
|
||||||
#define FLOPPY_MS_DMAMODE 0x20
|
#define FLOPPY_MS_DMAMODE 0x20
|
||||||
#define FLOPPY_MS_DATADIR 0x40
|
#define FLOPPY_MS_DATADIR 0x40
|
||||||
#define FLOPPY_MS_DATARDY 0x80
|
#define FLOPPY_MS_RDYMASK 0xF0
|
||||||
|
#define FLOPPY_MS_DATARDYW 0x80
|
||||||
|
#define FLOPPY_MS_DATARDYR 0xC0
|
||||||
#define FLOPPY_REG_DATA 0x0005
|
#define FLOPPY_REG_DATA 0x0005
|
||||||
#define FLOPPY_REG_DIR 0x0007 /* READ ONLY */
|
#define FLOPPY_REG_DIR 0x0007 /* READ ONLY */
|
||||||
#define FLOPPY_DI_DSKCHNG 0x80
|
#define FLOPPY_DI_DSKCHNG 0x80
|
||||||
|
@ -32,10 +36,8 @@
|
||||||
#define FLOPPY_CMD_RD_DATA 0x06
|
#define FLOPPY_CMD_RD_DATA 0x06
|
||||||
#define FLOPPY_CMD_RECAL 0x07
|
#define FLOPPY_CMD_RECAL 0x07
|
||||||
#define FLOPPY_CMD_SNS_INTR 0x08
|
#define FLOPPY_CMD_SNS_INTR 0x08
|
||||||
#define FLOPPY_CSI_IC_MASK 0xe0
|
#define FLOPPY_ST0_SEEKGD 0x20
|
||||||
#define FLOPPY_CSI_IC_RDYCH 0x60
|
#define FLOPPY_ST0_GDMASK 0xd8
|
||||||
#define FLOPPY_CSI_IC_SEEKGD 0x80
|
|
||||||
#define FLOPPY_CSI_IC_SEEKBD 0xc0
|
|
||||||
#define FLOPPY_CMD_WRT_DEL 0x09
|
#define FLOPPY_CMD_WRT_DEL 0x09
|
||||||
#define FLOPPY_CMD_RD_ID 0x0a
|
#define FLOPPY_CMD_RD_ID 0x0a
|
||||||
#define FLOPPY_CMD_RD_DEL 0x0c
|
#define FLOPPY_CMD_RD_DEL 0x0c
|
||||||
|
@ -80,32 +82,12 @@
|
||||||
//
|
//
|
||||||
// HAL floppy register access commands
|
// HAL floppy register access commands
|
||||||
//
|
//
|
||||||
#define FloppyWriteDOR(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DOR, (V)))
|
#define FloppyWriteDOR(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DOR, (V)))
|
||||||
#define FloppyReadMSTAT(A) (READ_BYTE((A) + FLOPPY_REG_MSTAT))
|
#define FloppyReadMSTAT(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_MSTAT))
|
||||||
#define FloppyReadDATA(A) (READ_BYTE((A) + FLOPPY_REG_DATA))
|
#define FloppyReadDATA(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DATA))
|
||||||
#define FloppyWriteDATA(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DATA, (V)))
|
#define FloppyWriteDATA(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DATA, (V)))
|
||||||
#define FloppyReadDIR(A) (READ_BYTE((A) + FLOPPY_REG_DIR))
|
#define FloppyReadDIR(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DIR))
|
||||||
#define FloppyWriteCCNTL(A, V) (WRITE_BYTE((A) + FLOPPY_REG_CCNTL, (V)))
|
#define FloppyWriteCCNTL(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_CCNTL, (V)))
|
||||||
|
|
||||||
//
|
|
||||||
// Known Floppy controller types
|
|
||||||
//
|
|
||||||
typedef enum _FLOPPY_CONTROLLER_TYPE
|
|
||||||
{
|
|
||||||
FDC_NONE,
|
|
||||||
FDC_UNKNOWN,
|
|
||||||
FDC_8272A, /* Intel 8272a, NEC 765 */
|
|
||||||
FDC_765ED, /* Non-Intel 1MB-compatible FDC, can't detect */
|
|
||||||
FDC_82072, /* Intel 82072; 8272a + FIFO + DUMPREGS */
|
|
||||||
FDC_82072A, /* 82072A (on Sparcs) */
|
|
||||||
FDC_82077_ORIG, /* Original version of 82077AA, sans LOCK */
|
|
||||||
FDC_82077, /* 82077AA-1 */
|
|
||||||
FDC_82078_UNKN, /* Unknown 82078 variant */
|
|
||||||
FDC_82078, /* 44pin 82078 or 64pin 82078SL */
|
|
||||||
FDC_82078_1, /* 82078-1 (2Mbps fdc) */
|
|
||||||
FDC_S82078B, /* S82078B (first seen on Adaptec AVA-2825 VLB SCSI/EIDE/Floppy controller) */
|
|
||||||
FDC_87306 /* National Semiconductor PC 87306 */
|
|
||||||
} FLOPPY_CONTROLLER_TYPE, *PFLOPPY_CONTROLLER_TYPE;
|
|
||||||
|
|
||||||
typedef struct _FLOPPY_ERROR_THRESHOLDS
|
typedef struct _FLOPPY_ERROR_THRESHOLDS
|
||||||
{
|
{
|
||||||
|
@ -125,34 +107,134 @@ typedef struct _FLOPPY_ERROR_THRESHOLDS
|
||||||
unsigned int Reporting;
|
unsigned int Reporting;
|
||||||
} FLOPPY_ERROR_THRESHOLDS;
|
} FLOPPY_ERROR_THRESHOLDS;
|
||||||
|
|
||||||
|
typedef struct _FLOPPY_MEDIA_TYPE
|
||||||
|
{
|
||||||
|
BYTE SectorSizeCode;
|
||||||
|
BYTE MaximumTrack;
|
||||||
|
BYTE Heads;
|
||||||
|
DWORD SectorsPerTrack;
|
||||||
|
ULONG BytesPerSector;
|
||||||
|
} FLOPPY_MEDIA_TYPE;
|
||||||
|
|
||||||
#define FDP_DEBUG 0x02
|
#define FDP_DEBUG 0x02
|
||||||
#define FDP_SILENT_DCL_CLEAR 0x04
|
#define FDP_SILENT_DCL_CLEAR 0x04
|
||||||
#define FDP_MSG 0x10
|
#define FDP_MSG 0x10
|
||||||
#define FDP_BROKEN_DCL 0x20
|
#define FDP_BROKEN_DCL 0x20
|
||||||
#define FDP_INVERTED_DCL 0x80
|
#define FDP_INVERTED_DCL 0x80
|
||||||
|
|
||||||
typedef struct _FLOPPY_DEVICE_PARAMETERS
|
// 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
|
||||||
|
|
||||||
|
typedef BOOLEAN (*FloppyIsrStateRoutine)( PCONTROLLER_OBJECT Controller );
|
||||||
|
typedef PIO_DPC_ROUTINE FloppyDpcStateRoutine;
|
||||||
|
|
||||||
|
typedef struct _FLOPPY_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
char CMOSType;
|
PCONTROLLER_OBJECT Controller;
|
||||||
unsigned long MaxDTR; /* Step rate, usec */
|
CHAR DriveSelect;
|
||||||
unsigned long HLT; /* Head load/settle time, msec */
|
ULONG MediaType; // Media type index
|
||||||
unsigned long HUT; /* Head unload time (remnant of 8" drives) */
|
} FLOPPY_DEVICE_EXTENSION, *PFLOPPY_DEVICE_EXTENSION;
|
||||||
unsigned long SRT; /* Step rate, usec */
|
|
||||||
unsigned long Spinup; /* time needed for spinup */
|
|
||||||
unsigned long Spindown; /* timeout needed for spindown */
|
|
||||||
unsigned char SpindownOffset; /* decides in which position the disk will stop */
|
|
||||||
unsigned char SelectDelay; /* delay to wait after select */
|
|
||||||
unsigned char RPS; /* rotations per second */
|
|
||||||
unsigned char Tracks; /* maximum number of tracks */
|
|
||||||
unsigned long Timeout; /* timeout for interrupt requests */
|
|
||||||
unsigned char InterleaveSect; /* if there are more sectors, use interleave */
|
|
||||||
FLOPPY_ERROR_THRESHOLDS MaxErrors;
|
|
||||||
char Flags; /* various flags, including ftd_msg */
|
|
||||||
BOOLEAN ReadTrack; /* use readtrack during probing? */
|
|
||||||
short Autodetect[8]; /* autodetected formats */
|
|
||||||
int CheckFreq; /* how often should the drive be checked for disk changes */
|
|
||||||
int NativeFormat; /* native format of this drive */
|
|
||||||
char *DriveName; /* name of the drive for reporting */
|
|
||||||
} FLOPPY_DEVICE_PARAMETERS, *PFLOPPY_DEVICE_PARAMETERS;
|
|
||||||
|
|
||||||
|
typedef struct _FLOPPY_CONTROLLER_EXTENSION
|
||||||
|
{
|
||||||
|
PKINTERRUPT Interrupt;
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
ULONG Number;
|
||||||
|
ULONG PortBase;
|
||||||
|
ULONG Vector;
|
||||||
|
KEVENT Event; // Event set by ISR/DPC to wake DeviceEntry
|
||||||
|
PDEVICE_OBJECT Device; // Pointer to the primary device on this controller
|
||||||
|
PIRP Irp; // Current IRP
|
||||||
|
CHAR St0; // Status registers
|
||||||
|
CHAR St1;
|
||||||
|
CHAR St2;
|
||||||
|
CHAR SectorSizeCode;
|
||||||
|
FloppyIsrStateRoutine IsrState; // pointer to state routine handler for ISR
|
||||||
|
FloppyDpcStateRoutine DpcState; // pointer to state routine handler for DPC
|
||||||
|
CHAR MotorOn; // drive select for drive with motor on
|
||||||
|
KDPC MotorSpinupDpc; // DPC for motor spin up time
|
||||||
|
KTIMER SpinupTimer; // Timer for motor spin up time
|
||||||
|
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
|
||||||
|
{
|
||||||
|
ULONG PortBase;
|
||||||
|
ULONG Vector;
|
||||||
|
ULONG IrqL;
|
||||||
|
ULONG DmaChannel;
|
||||||
|
ULONG SynchronizeIrqL;
|
||||||
|
KINTERRUPT_MODE InterruptMode;
|
||||||
|
KAFFINITY Affinity;
|
||||||
|
} FLOPPY_CONTROLLER_PARAMETERS, *PFLOPPY_CONTROLLER_PARAMETERS;
|
||||||
|
|
||||||
|
#define FLOPPY_MAX_CONTROLLERS 1
|
||||||
|
|
||||||
|
VOID FloppyDpcDetectMedia( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context );
|
||||||
|
VOID FloppyDpcFailIrp( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context );
|
||||||
|
|
||||||
|
IO_ALLOCATION_ACTION FloppyExecuteReadWrite( PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID MapRegisterbase,
|
||||||
|
PVOID Context );
|
||||||
|
|
||||||
|
IO_ALLOCATION_ACTION FloppyExecuteSpindown( PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID MapRegisterbase,
|
||||||
|
PVOID Context );
|
||||||
|
|
||||||
|
VOID FloppyMotorSpinupDpc( PKDPC Dpc,
|
||||||
|
PVOID Context,
|
||||||
|
PVOID Arg1,
|
||||||
|
PVOID Arg2 );
|
||||||
|
|
||||||
|
VOID FloppyMotorSpindownDpc( PKDPC Dpc,
|
||||||
|
PVOID Context,
|
||||||
|
PVOID Arg1,
|
||||||
|
PVOID Arg2 );
|
||||||
|
|
||||||
|
VOID FloppyDpcDetect( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context );
|
||||||
|
|
||||||
|
VOID FloppyDpcReadWrite( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context );
|
||||||
|
|
||||||
|
VOID FloppyDpc( PKDPC Dpc,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context );
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrDetect( PCONTROLLER_OBJECT Controller );
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrReadWrite( PCONTROLLER_OBJECT Controller );
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrUnexpected( PCONTROLLER_OBJECT Controller );
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrDetectMedia( PCONTROLLER_OBJECT Controller );
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrRecal( PCONTROLLER_OBJECT Controller );
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsr(PKINTERRUPT Interrupt, PVOID ServiceContext);
|
||||||
|
|
||||||
|
IO_ALLOCATION_ACTION FloppyAdapterControl( PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID MapRegisterBase,
|
||||||
|
PVOID Context );
|
||||||
|
|
150
reactos/drivers/dd/floppy/isr.c
Normal file
150
reactos/drivers/dd/floppy/isr.c
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/************************************************************************
|
||||||
|
* Interrupt handlers for floppy disk driver, reactos project, created *
|
||||||
|
* by Phillip Susi on 2/25/2001. This software is publised under the *
|
||||||
|
* GNU General public license. See the README file for more details *
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include "floppy.h"
|
||||||
|
|
||||||
|
|
||||||
|
// ISR state machine function called when expecting an interrupt due to reset
|
||||||
|
// During reset, there is nothing ready to read, just issue sense interrupt status
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrDetect( PCONTROLLER_OBJECT Controller )
|
||||||
|
{
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
// 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
|
||||||
|
// now queue DPC to set the event
|
||||||
|
IoRequestDpc( ControllerExtension->Device,
|
||||||
|
0,
|
||||||
|
Controller );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISR state machine handler for unexpected interrupt
|
||||||
|
BOOLEAN FloppyIsrUnexpected( PCONTROLLER_OBJECT Controller )
|
||||||
|
{
|
||||||
|
DPRINT( "Unexpected interrupt!\n" );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrDetectMedia( PCONTROLLER_OBJECT Controller )
|
||||||
|
{
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
BYTE SectorSize;
|
||||||
|
// media detect in progress, read ID command already issued
|
||||||
|
// first, read result registers
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
ControllerExtension->St1 = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
ControllerExtension->St2 = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // ignore cyl
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // ignore head
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // ignore sector
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
SectorSize = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
DPRINT( "Sector Size Code: %2x\n", SectorSize );
|
||||||
|
DPRINT( "St0 = %2x, St1 = %2x, St2 = %2x\n", ControllerExtension->St0, ControllerExtension->St1, ControllerExtension->St2 );
|
||||||
|
DPRINT( "ControllerExtension->Device = %x, ControllerExtension->Irp = %x\n", ControllerExtension->Device, ControllerExtension->Irp );
|
||||||
|
// queue DPC
|
||||||
|
ControllerExtension->DpcState = FloppyDpcDetectMedia;
|
||||||
|
IoRequestDpc( ControllerExtension->Device,
|
||||||
|
ControllerExtension->Irp,
|
||||||
|
Controller );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsrRecal( PCONTROLLER_OBJECT Controller )
|
||||||
|
{
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
// issue sense interrupt status, and read St0 and cyl
|
||||||
|
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_SNS_INTR );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
ControllerExtension->St0 = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // ignore cyl number
|
||||||
|
DPRINT( "Recal St0: %2x\n", ControllerExtension->St0 );
|
||||||
|
|
||||||
|
// If recalibrate worked, issue read ID for each media type untill one works
|
||||||
|
if( ControllerExtension->St0 != FLOPPY_ST0_SEEKGD )
|
||||||
|
{
|
||||||
|
DPRINT( "Recalibrate failed, ST0 = %2x\n", ControllerExtension->St0 );
|
||||||
|
// queue DPC to fail IRP
|
||||||
|
ControllerExtension->DpcState = FloppyDpcFailIrp;
|
||||||
|
IoRequestDpc( ControllerExtension->Device,
|
||||||
|
ControllerExtension->Irp,
|
||||||
|
Controller );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// issue first read id, FloppyIsrDetectMedia will handle
|
||||||
|
DPRINT( "Recalibrate worked, issuing read ID mark command\n" );
|
||||||
|
ControllerExtension->IsrState = FloppyIsrDetectMedia;
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, FLOPPY_CMD_RD_ID | FLOPPY_C0M_MFM );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyWriteDATA( ControllerExtension->PortBase, ((PFLOPPY_DEVICE_EXTENSION)ControllerExtension->Device->DeviceExtension)->DriveSelect );
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
ControllerExtension->St2 = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // cyl
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // head
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
FloppyReadDATA( ControllerExtension->PortBase ); // sector
|
||||||
|
KeStallExecutionProcessor( 1000 );
|
||||||
|
ControllerExtension->SectorSizeCode = FloppyReadDATA( ControllerExtension->PortBase );
|
||||||
|
CHECKPOINT1;
|
||||||
|
IoRequestDpc( ControllerExtension->Device,
|
||||||
|
ControllerExtension->Irp,
|
||||||
|
Controller );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// actual ISR, passes controll to handler for current state in state machine
|
||||||
|
|
||||||
|
BOOLEAN FloppyIsr(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
||||||
|
{
|
||||||
|
PCONTROLLER_OBJECT Controller = (PCONTROLLER_OBJECT)ServiceContext;
|
||||||
|
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)Controller->ControllerExtension;
|
||||||
|
BYTE Byte;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
Byte = FloppyReadMSTAT( ControllerExtension->PortBase );
|
||||||
|
if( Byte == 0 )
|
||||||
|
{
|
||||||
|
DPRINT( "Ignoring interrupt, MSTAT = 0\n" );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return ControllerExtension->IsrState( Controller );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue