mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +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 = ../../..
|
||||
|
||||
TARGET=floppy
|
||||
|
||||
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
|
||||
OBJECTS = floppy.o isr.o dpc.o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
CFLAGS = -I.
|
||||
|
||||
all: $(TARGET).sys
|
||||
|
||||
floppy.o: floppy.h
|
||||
|
||||
isr.o: floppy.h
|
||||
|
||||
dpc.o: floppy.h
|
||||
|
||||
.phony: all
|
||||
|
||||
clean:
|
||||
- $(RM) $(TARGET).o
|
||||
- $(RM) floppy.o
|
||||
- $(RM) isr.o
|
||||
- $(RM) dpc.o
|
||||
- $(RM) $(TARGET).coff
|
||||
- $(RM) junk.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:
|
||||
* 08/19/98 RJJ Created.
|
||||
* 01/31/01 PJS Heavy rewrite, most of code thrown out
|
||||
*
|
||||
* To do:
|
||||
* FIXME: get it working
|
||||
|
@ -19,390 +20,37 @@
|
|||
|
||||
#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] =
|
||||
{
|
||||
{0x03f0, 6, 6, 6, LevelSensitive, 0xffff},
|
||||
{0x0370, 6, 6, 6, LevelSensitive, 0xffff},
|
||||
{0x03f0, 6, 6, 2, 6, LevelSensitive, 0xffff}
|
||||
// {0x0370, 6, 6, 6, LevelSensitive, 0xffff},
|
||||
};
|
||||
|
||||
FLOPPY_DEVICE_PARAMETERS DeviceTypes[] =
|
||||
{
|
||||
/* Unknown */
|
||||
{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"}
|
||||
};
|
||||
const FLOPPY_MEDIA_TYPE MediaTypes[] = {
|
||||
{ 0x02, 9, 80, 18, 512 },
|
||||
{ 0, 0, 0, 0, 0 } };
|
||||
|
||||
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
|
||||
FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
||||
PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
|
||||
int Index)
|
||||
{
|
||||
FLOPPY_CONTROLLER_TYPE ControllerType;
|
||||
PCONTROLLER_OBJECT ControllerObject;
|
||||
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
|
||||
PFLOPPY_DEVICE_EXTENSION DeviceExtension;
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING SymlinkName;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PCONFIGURATION_INFORMATION ConfigInfo;
|
||||
|
||||
/* Detect controller and determine type */
|
||||
if (!FloppyGetControllerVersion(ControllerParameters, &ControllerType))
|
||||
{
|
||||
DPRINT("Failed to get controller version\n");
|
||||
return FALSE;
|
||||
}
|
||||
LARGE_INTEGER Timeout;
|
||||
BYTE Byte;
|
||||
int c;
|
||||
PCONFIGURATION_INFORMATION Config;
|
||||
DEVICE_DESCRIPTION DeviceDescription;
|
||||
ULONG MaxMapRegs;
|
||||
|
||||
/* FIXME: Register port ranges and interrupts with HAL */
|
||||
|
||||
|
@ -421,15 +69,18 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
|||
ControllerExtension->Number = Index;
|
||||
ControllerExtension->PortBase = ControllerParameters->PortBase;
|
||||
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 */
|
||||
KeInitializeSpinLock(&ControllerExtension->SpinLock);
|
||||
ControllerExtension->IsrState = FloppyIsrDetect;
|
||||
ControllerExtension->DpcState = FloppyDpcDetect;
|
||||
|
||||
/* Register an interrupt handler for this controller */
|
||||
Status = IoConnectInterrupt(&ControllerExtension->Interrupt,
|
||||
FloppyIsr,
|
||||
ControllerExtension,
|
||||
ControllerObject,
|
||||
&ControllerExtension->SpinLock,
|
||||
ControllerExtension->Vector,
|
||||
ControllerParameters->IrqL,
|
||||
|
@ -442,12 +93,26 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
|||
{
|
||||
DPRINT("Could not Connect Interrupt %d\n",
|
||||
ControllerExtension->Vector);
|
||||
IoDeleteController(ControllerObject);
|
||||
return FALSE;
|
||||
goto controllercleanup;
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
/* Check for each possible drive and create devices for them */
|
||||
for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++)
|
||||
|
@ -468,40 +133,292 @@ FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
|||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
IoDisconnectInterrupt(ControllerExtension->Interrupt);
|
||||
IoDeleteController(ControllerObject);
|
||||
goto interruptcleanup;
|
||||
}
|
||||
|
||||
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 */
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
||||
DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
||||
|
||||
/* count new floppy drive */
|
||||
/* NOTE: HalIoAssignDriveLetters assigns the drive letters! */
|
||||
ConfigInfo = IoGetConfigurationInformation ();
|
||||
ConfigInfo->FloppyCount++;
|
||||
|
||||
DeviceObject->AlignmentRequirement = FILE_512_BYTE_ALIGNMENT;
|
||||
// change state machine, no interrupt expected
|
||||
ControllerExtension->IsrState = FloppyIsrUnexpected;
|
||||
Config = IoGetConfigurationInformation();
|
||||
Config->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;
|
||||
|
||||
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,
|
||||
PIRP Irp)
|
||||
IO_ALLOCATION_ACTION FloppyExecuteSpindown( PDEVICE_OBJECT DeviceObject,
|
||||
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,
|
||||
PIRP Irp)
|
||||
{
|
||||
DPRINT("FloppyDispatchOpenClose\n");
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL FloppyDispatchReadWrite(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
DPRINT("FloppyDispatchReadWrite\n");
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
PFLOPPY_DEVICE_EXTENSION DeviceExtension = (PFLOPPY_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
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,
|
||||
|
@ -536,7 +453,6 @@ NTSTATUS STDCALL DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
|||
DbgPrint("Floppy driver\n");
|
||||
|
||||
/* Export other driver entry points... */
|
||||
DriverObject->DriverStartIo = FloppyStartIo;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite;
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
|
||||
#define FLOPPY_MAX_STAT_RETRIES 10000
|
||||
|
||||
#define FLOPPY_NEEDS_OUTPUT -2
|
||||
//
|
||||
// Floppy register definitions
|
||||
//
|
||||
|
||||
#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_MS_DRV0BUSY 0x01
|
||||
#define FLOPPY_MS_DRV1BUSY 0x02
|
||||
|
@ -15,7 +17,9 @@
|
|||
#define FLOPPY_MS_FDCBUSY 0x10
|
||||
#define FLOPPY_MS_DMAMODE 0x20
|
||||
#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_DIR 0x0007 /* READ ONLY */
|
||||
#define FLOPPY_DI_DSKCHNG 0x80
|
||||
|
@ -32,10 +36,8 @@
|
|||
#define FLOPPY_CMD_RD_DATA 0x06
|
||||
#define FLOPPY_CMD_RECAL 0x07
|
||||
#define FLOPPY_CMD_SNS_INTR 0x08
|
||||
#define FLOPPY_CSI_IC_MASK 0xe0
|
||||
#define FLOPPY_CSI_IC_RDYCH 0x60
|
||||
#define FLOPPY_CSI_IC_SEEKGD 0x80
|
||||
#define FLOPPY_CSI_IC_SEEKBD 0xc0
|
||||
#define FLOPPY_ST0_SEEKGD 0x20
|
||||
#define FLOPPY_ST0_GDMASK 0xd8
|
||||
#define FLOPPY_CMD_WRT_DEL 0x09
|
||||
#define FLOPPY_CMD_RD_ID 0x0a
|
||||
#define FLOPPY_CMD_RD_DEL 0x0c
|
||||
|
@ -80,32 +82,12 @@
|
|||
//
|
||||
// HAL floppy register access commands
|
||||
//
|
||||
#define FloppyWriteDOR(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DOR, (V)))
|
||||
#define FloppyReadMSTAT(A) (READ_BYTE((A) + FLOPPY_REG_MSTAT))
|
||||
#define FloppyReadDATA(A) (READ_BYTE((A) + FLOPPY_REG_DATA))
|
||||
#define FloppyWriteDATA(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DATA, (V)))
|
||||
#define FloppyReadDIR(A) (READ_BYTE((A) + FLOPPY_REG_DIR))
|
||||
#define FloppyWriteCCNTL(A, V) (WRITE_BYTE((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;
|
||||
#define FloppyWriteDOR(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DOR, (V)))
|
||||
#define FloppyReadMSTAT(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_MSTAT))
|
||||
#define FloppyReadDATA(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DATA))
|
||||
#define FloppyWriteDATA(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DATA, (V)))
|
||||
#define FloppyReadDIR(A) (READ_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_DIR))
|
||||
#define FloppyWriteCCNTL(A, V) (WRITE_PORT_UCHAR((PVOID)(A) + FLOPPY_REG_CCNTL, (V)))
|
||||
|
||||
typedef struct _FLOPPY_ERROR_THRESHOLDS
|
||||
{
|
||||
|
@ -125,34 +107,134 @@ typedef struct _FLOPPY_ERROR_THRESHOLDS
|
|||
unsigned int Reporting;
|
||||
} 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_SILENT_DCL_CLEAR 0x04
|
||||
#define FDP_MSG 0x10
|
||||
#define FDP_BROKEN_DCL 0x20
|
||||
#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;
|
||||
unsigned long MaxDTR; /* Step rate, usec */
|
||||
unsigned long HLT; /* Head load/settle time, msec */
|
||||
unsigned long HUT; /* Head unload time (remnant of 8" drives) */
|
||||
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;
|
||||
PCONTROLLER_OBJECT Controller;
|
||||
CHAR DriveSelect;
|
||||
ULONG MediaType; // Media type index
|
||||
} FLOPPY_DEVICE_EXTENSION, *PFLOPPY_DEVICE_EXTENSION;
|
||||
|
||||
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