Added Fix for >255 sector read/write and first hack at timeout code

svn path=/trunk/; revision=76
This commit is contained in:
Rex Jolliff 1998-10-20 06:00:13 +00:00
parent 267b8c4e8c
commit e68e2e431a
2 changed files with 268 additions and 85 deletions

View file

@ -44,7 +44,6 @@
// //
// //
// To Do: // To Do:
// FIXME: reads/writes that cause multiple calls to setup to device should be tested.
// FIXME: a timer should be used to watch for device timeouts and errors // FIXME: a timer should be used to watch for device timeouts and errors
// FIXME: errors should be retried // FIXME: errors should be retried
// FIXME: a drive reset/recalibrate should be attempted if errors occur // FIXME: a drive reset/recalibrate should be attempted if errors occur
@ -175,7 +174,6 @@ static int IDEPolledRead(IN WORD Address,
IN BYTE DrvHead, IN BYTE DrvHead,
IN BYTE Command, IN BYTE Command,
OUT BYTE *Buffer); OUT BYTE *Buffer);
static NTSTATUS IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp); static NTSTATUS IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
static NTSTATUS IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, IN PIRP Irp); static NTSTATUS IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
static NTSTATUS IDEDispatchDeviceControl(IN PDEVICE_OBJECT pDO, IN PIRP Irp); static NTSTATUS IDEDispatchDeviceControl(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
@ -185,11 +183,13 @@ static IO_ALLOCATION_ACTION IDEAllocateController(IN PDEVICE_OBJECT DeviceObjec
IN PVOID MapRegisterBase, IN PVOID MapRegisterBase,
IN PVOID Ccontext); IN PVOID Ccontext);
static BOOLEAN IDEStartController(IN OUT PVOID Context); static BOOLEAN IDEStartController(IN OUT PVOID Context);
VOID IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension);
static BOOLEAN IDEIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); static BOOLEAN IDEIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
static VOID IDEDpcForIsr(IN PKDPC Dpc, static VOID IDEDpcForIsr(IN PKDPC Dpc,
IN PDEVICE_OBJECT DpcDeviceObject, IN PDEVICE_OBJECT DpcDeviceObject,
IN PIRP DpcIrp, IN PIRP DpcIrp,
IN PVOID DpcContext); IN PVOID DpcContext);
static VOID IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension);
static VOID IDEIoTimer(PDEVICE_OBJECT DeviceObject, PVOID Context); static VOID IDEIoTimer(PDEVICE_OBJECT DeviceObject, PVOID Context);
// ---------------------------------------------------------------- Inlines // ---------------------------------------------------------------- Inlines
@ -393,23 +393,43 @@ IDEResetController(IN WORD CommandPort,
{ {
int Retries; int Retries;
// Send the controller reset command // Assert drive reset line
IDEWriteDriveControl(ControlPort, IDE_DC_SRST); IDEWriteDriveControl(ControlPort, IDE_DC_SRST);
KeStallExecutionProcessor(50);
// Wait for BUSY assertion
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
{
if (IDEReadStatus(CommandPort) & IDE_SR_BUSY)
{
break;
}
KeStallExecutionProcessor(10);
}
if (Retries >= IDE_MAX_BUSY_RETRIES)
{
return FALSE;
}
// Negate drive reset line
IDEWriteDriveControl(ControlPort, 0); IDEWriteDriveControl(ControlPort, 0);
// Loop on status register waiting for controller ready // Wait for BUSY negation
for (Retries = 0; Retries < IDE_MAX_RESET_RETRIES; Retries++) for (Retries = 0; Retries < IDE_RESET_BUSY_TIMEOUT * 1000; Retries++)
{ {
if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY)) if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY))
{
break; break;
}
KeStallExecutionProcessor(10); KeStallExecutionProcessor(10);
} }
if (Retries >= IDE_RESET_BUSY_TIMEOUT * 1000)
{
return FALSE;
}
// return TRUE if controller came back to life. and // return TRUE if controller came back to life. and
// the registers are initialized correctly // the registers are initialized correctly
return Retries < IDE_MAX_RESET_RETRIES && return IDEReadError(CommandPort) == 1 &&
IDEReadError(CommandPort) == 1 &&
IDEReadSectorCount(CommandPort) == 1 && IDEReadSectorCount(CommandPort) == 1 &&
IDEReadSectorNum(CommandPort) == 1 && IDEReadSectorNum(CommandPort) == 1 &&
IDEReadCylinderLow(CommandPort) == 0 && IDEReadCylinderLow(CommandPort) == 0 &&
@ -723,11 +743,10 @@ IDEGetDriveIdentification(IN int CommandPort,
DrvParms->ECCByteCnt, DrvParms->ECCByteCnt,
DrvParms->FirmwareRev); DrvParms->FirmwareRev);
DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber); DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber);
DPRINT("RWMult?:%02x DWrdIO?:%d LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n", DPRINT("RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n",
(DrvParms->RWMultImplemented) & 0xff, (DrvParms->RWMultImplemented) & 0xff,
DrvParms->DWordIOSupported, (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0,
(DrvParms->LBADMASupported & 0x0200) ? 1 : 0, (DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0,
(DrvParms->LBADMASupported & 0x0100) ? 1 : 0,
DrvParms->MinPIOTransTime, DrvParms->MinPIOTransTime,
DrvParms->MinDMATransTime); DrvParms->MinDMATransTime);
DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%d\n", DPRINT("TM:Cyls:%d Heads:%d Sectors/Trk:%d Capacity:%d\n",
@ -773,7 +792,7 @@ IDEGetPartitionTable(IN int CommandPort,
// Get sector at offset // Get sector at offset
SaveOffset = Offset; SaveOffset = Offset;
if (DrvParms->LBADMASupported & 0x0200) if (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED)
{ {
SectorNum = Offset & 0xff; SectorNum = Offset & 0xff;
CylinderLow = (Offset >> 8) & 0xff; CylinderLow = (Offset >> 8) & 0xff;
@ -913,8 +932,10 @@ IDECreateDevice(IN PDRIVER_OBJECT DriverObject,
DeviceExtension->DeviceObject = (*DeviceObject); DeviceExtension->DeviceObject = (*DeviceObject);
DeviceExtension->ControllerObject = ControllerObject; DeviceExtension->ControllerObject = ControllerObject;
DeviceExtension->UnitNumber = UnitNumber; DeviceExtension->UnitNumber = UnitNumber;
DeviceExtension->LBASupported = (DrvParms->LBADMASupported & 0x0200) ? 1 : 0; DeviceExtension->LBASupported =
DeviceExtension->DMASupported = (DrvParms->LBADMASupported & 0x0100) ? 1 : 0; (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0;
DeviceExtension->DMASupported =
(DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0;
// FIXME: deal with bizarre sector sizes // FIXME: deal with bizarre sector sizes
DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */; DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */;
DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads * DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads *
@ -1076,7 +1097,7 @@ IDEPolledRead(IN WORD Address,
} }
// Read data into buffer // Read data into buffer
IDEReadBlock(Address, Buffer); IDEReadBlock(Address, Buffer, IDE_SECTOR_BUF_SZ);
Buffer += IDE_SECTOR_BUF_SZ; Buffer += IDE_SECTOR_BUF_SZ;
// Check for more sectors to read // Check for more sectors to read
@ -1318,7 +1339,9 @@ IDEStartIo(IN PDEVICE_OBJECT DeviceObject,
DeviceExtension->TargetAddress = (BYTE *)MmGetSystemAddressForMdl(Irp->MdlAddress); DeviceExtension->TargetAddress = (BYTE *)MmGetSystemAddressForMdl(Irp->MdlAddress);
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
IoAllocateController(DeviceExtension->ControllerObject, IoAllocateController(DeviceExtension->ControllerObject,
DeviceObject, IDEAllocateController, NULL); DeviceObject,
IDEAllocateController,
NULL);
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
break; break;
@ -1346,6 +1369,7 @@ IDEAllocateController(IN PDEVICE_OBJECT DeviceObject,
ControllerExtension = (PIDE_CONTROLLER_EXTENSION) ControllerExtension = (PIDE_CONTROLLER_EXTENSION)
DeviceExtension->ControllerObject->ControllerExtension; DeviceExtension->ControllerObject->ControllerExtension;
ControllerExtension->CurrentIrp = Irp; ControllerExtension->CurrentIrp = Irp;
ControllerExtension->Retries = 0;
return KeSynchronizeExecution(ControllerExtension->Interrupt, return KeSynchronizeExecution(ControllerExtension->Interrupt,
IDEStartController, IDEStartController,
DeviceExtension) ? KeepObject : DeviceExtension) ? KeepObject :
@ -1429,14 +1453,23 @@ IDEStartController(IN OUT PVOID Context)
} }
KeStallExecutionProcessor(10); KeStallExecutionProcessor(10);
} }
/* FIXME: should reset controller and try again */ Retries = IDE_MAX_BUSY_RETRIES;
if (Retries >= IDE_MAX_BUSY_RETRIES) if (Retries >= IDE_MAX_BUSY_RETRIES)
{
if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES)
{ {
Irp = ControllerExtension->CurrentIrp; Irp = ControllerExtension->CurrentIrp;
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
return DeallocateObject; return FALSE;
}
else
{
IDEBeginControllerReset(ControllerExtension);
return TRUE;
}
} }
/* Select the desired drive */ /* Select the desired drive */
@ -1452,14 +1485,22 @@ IDEStartController(IN OUT PVOID Context)
} }
KeStallExecutionProcessor(10); KeStallExecutionProcessor(10);
} }
/* FIXME: should reset controller and try again */
if (Retries >= IDE_MAX_BUSY_RETRIES) if (Retries >= IDE_MAX_BUSY_RETRIES)
{
if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES)
{ {
Irp = ControllerExtension->CurrentIrp; Irp = ControllerExtension->CurrentIrp;
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
return DeallocateObject; return FALSE;
}
else
{
IDEBeginControllerReset(ControllerExtension);
return TRUE;
}
} }
/* Setup command parameters */ /* Setup command parameters */
@ -1472,6 +1513,9 @@ IDEStartController(IN OUT PVOID Context)
/* Issue command to drive */ /* Issue command to drive */
IDEWriteCommand(ControllerExtension->CommandPortBase, Command); IDEWriteCommand(ControllerExtension->CommandPortBase, Command);
ControllerExtension->TimerState = IDETimerCmdWait;
ControllerExtension->TimerCount = IDE_CMD_TIMEOUT;
IoStartTimer(ControllerExtension->TimerDevice);
if (DeviceExtension->Operation == IRP_MJ_WRITE) if (DeviceExtension->Operation == IRP_MJ_WRITE)
{ {
@ -1484,25 +1528,71 @@ IDEStartController(IN OUT PVOID Context)
{ {
break; break;
} }
KeStallExecutionProcessor(10);
} }
if (Retries >= IDE_MAX_BUSY_RETRIES) if (Retries >= IDE_MAX_BUSY_RETRIES)
{
if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES)
{ {
Irp = ControllerExtension->CurrentIrp; Irp = ControllerExtension->CurrentIrp;
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED; Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
return DeallocateObject; return FALSE;
}
else
{
IDEBeginControllerReset(ControllerExtension);
return TRUE;
}
} }
// Load the first sector of data into the controller // Load the first sector of data into the controller
IDEWriteBlock(ControllerExtension->CommandPortBase, DeviceExtension->TargetAddress); IDEWriteBlock(ControllerExtension->CommandPortBase,
DeviceExtension->TargetAddress,
IDE_SECTOR_BUF_SZ);
DeviceExtension->TargetAddress += IDE_SECTOR_BUF_SZ; DeviceExtension->TargetAddress += IDE_SECTOR_BUF_SZ;
DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector;
DeviceExtension->SectorsTransferred++;
} }
return TRUE; return TRUE;
} }
// IDEBeginControllerReset
VOID
IDEBeginControllerReset(PIDE_CONTROLLER_EXTENSION ControllerExtension)
{
int Retries;
// Assert drive reset line
IDEWriteDriveControl(ControllerExtension->ControlPortBase, IDE_DC_SRST);
// FIXME: wait for BSY assertion
for (Retries = 0; Retries < IDE_MAX_RESET_RETRIES; Retries++)
{
BYTE Status = IDEReadStatus(ControllerExtension->CommandPortBase);
if ((Status & IDE_SR_BUSY))
{
break;
}
KeStallExecutionProcessor(10);
}
// Negate drive reset line
IDEWriteDriveControl(ControllerExtension->ControlPortBase, 0);
// FIXME: handle case of no device 0
// FIXME: set timer to check for end of reset
ControllerExtension->TimerState = IDETimerResetWaitForBusyNegate;
ControllerExtension->TimerCount = IDE_RESET_BUSY_TIMEOUT;
IoStartTimer(ControllerExtension->TimerDevice);
}
// IDEIsr // IDEIsr
// //
// DESCIPTION: // DESCIPTION:
@ -1616,7 +1706,9 @@ IDEIsr(IN PKINTERRUPT Interrupt,
} }
// Copy the block of data // Copy the block of data
IDEReadBlock(ControllerExtension->CommandPortBase, TargetAddress); IDEReadBlock(ControllerExtension->CommandPortBase,
TargetAddress,
IDE_SECTOR_BUF_SZ);
// check DRQ // check DRQ
if (IsLastBlock) if (IsLastBlock)
@ -1716,9 +1808,12 @@ IDEIsr(IN PKINTERRUPT Interrupt,
TargetAddress = DeviceExtension->TargetAddress; TargetAddress = DeviceExtension->TargetAddress;
DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector; DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector;
DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector; DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector;
DeviceExtension->SectorsTransferred++;
// Write block to controller // Write block to controller
IDEWriteBlock(ControllerExtension->CommandPortBase, TargetAddress); IDEWriteBlock(ControllerExtension->CommandPortBase,
TargetAddress,
IDE_SECTOR_BUF_SZ);
} }
break; break;
} }
@ -1727,7 +1822,6 @@ IDEIsr(IN PKINTERRUPT Interrupt,
// If there was an error or the request is done, complete the packet // If there was an error or the request is done, complete the packet
if (AnErrorOccured || RequestIsComplete) if (AnErrorOccured || RequestIsComplete)
{ {
// Set the return status and info values // Set the return status and info values
Irp = ControllerExtension->CurrentIrp; Irp = ControllerExtension->CurrentIrp;
Irp->IoStatus.Status = ErrorStatus; Irp->IoStatus.Status = ErrorStatus;
@ -1768,15 +1862,22 @@ IDEDpcForIsr(IN PKDPC Dpc,
IN PIRP DpcIrp, IN PIRP DpcIrp,
IN PVOID DpcContext) IN PVOID DpcContext)
{ {
PIDE_CONTROLLER_EXTENSION ControllerExtension; IDEFinishOperation((PIDE_CONTROLLER_EXTENSION) DpcContext);
}
// IDEFinishOperation
static VOID
IDEFinishOperation(PIDE_CONTROLLER_EXTENSION ControllerExtension)
{
PIDE_DEVICE_EXTENSION DeviceExtension; PIDE_DEVICE_EXTENSION DeviceExtension;
PIRP Irp; PIRP Irp;
ULONG Operation; ULONG Operation;
ControllerExtension = (PIDE_CONTROLLER_EXTENSION) DpcContext;
DeviceExtension = ControllerExtension->DeviceForOperation; DeviceExtension = ControllerExtension->DeviceForOperation;
Irp = ControllerExtension->CurrentIrp; Irp = ControllerExtension->CurrentIrp;
Operation = DeviceExtension->Operation; Operation = DeviceExtension->Operation;
ControllerExtension->OperationInProgress = FALSE;
ControllerExtension->DeviceForOperation = 0; ControllerExtension->DeviceForOperation = 0;
ControllerExtension->CurrentIrp = 0; ControllerExtension->CurrentIrp = 0;
@ -1815,9 +1916,49 @@ IDEIoTimer(PDEVICE_OBJECT DeviceObject,
{ {
PIDE_CONTROLLER_EXTENSION ControllerExtension; PIDE_CONTROLLER_EXTENSION ControllerExtension;
DPRINT("entered timer\n");
// Setup Extension pointer // Setup Extension pointer
ControllerExtension = (PIDE_CONTROLLER_EXTENSION) Context; ControllerExtension = (PIDE_CONTROLLER_EXTENSION) Context;
// Handle state change if necessary
switch (ControllerExtension->TimerState)
{
case IDETimerResetWaitForBusyNegate:
if (!(IDEReadStatus(ControllerExtension->CommandPortBase) &
IDE_SR_BUSY))
{
ControllerExtension->TimerState = IDETimerResetWaitForDrdyAssert;
ControllerExtension->TimerCount = IDE_RESET_DRDY_TIMEOUT;
return;
}
break;
case IDETimerResetWaitForDrdyAssert:
if (IDEReadStatus(ControllerExtension->CommandPortBase) &
IDE_SR_DRQ)
{
ControllerExtension->TimerState = IDETimerIdle;
ControllerExtension->TimerCount = 0;
IoStopTimer(ControllerExtension->TimerDevice);
// FIXME: get diagnostic code from drive 0
// Start current packet command again
if (!KeSynchronizeExecution(ControllerExtension->Interrupt,
IDEStartController,
ControllerExtension->DeviceForOperation))
{
IDEFinishOperation(ControllerExtension);
}
return;
}
break;
default:
break;
}
// If we're counting down, then count. // If we're counting down, then count.
if (ControllerExtension->TimerCount > 0) if (ControllerExtension->TimerCount > 0)
{ {
@ -1831,6 +1972,29 @@ IDEIoTimer(PDEVICE_OBJECT DeviceObject,
{ {
case IDETimerIdle: case IDETimerIdle:
break; break;
case IDETimerCmdWait:
// Command timed out, reset drive and try again or fail
if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES)
{
ControllerExtension->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT;
ControllerExtension->CurrentIrp->IoStatus.Information = 0;
IoStopTimer(ControllerExtension->TimerDevice);
IDEFinishOperation(ControllerExtension);
}
else
{
IDEBeginControllerReset(ControllerExtension);
}
break;
case IDETimerResetWaitForBusyNegate:
case IDETimerResetWaitForDrdyAssert:
ControllerExtension->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT;
ControllerExtension->CurrentIrp->IoStatus.Information = 0;
IoStopTimer(ControllerExtension->TimerDevice);
IDEFinishOperation(ControllerExtension);
break;
} }
} }
} }

View file

@ -24,6 +24,10 @@ extern "C" {
#define IDE_MAX_WRITE_RETRIES 1000 #define IDE_MAX_WRITE_RETRIES 1000
#define IDE_MAX_BUSY_RETRIES 100 #define IDE_MAX_BUSY_RETRIES 100
#define IDE_MAX_DRQ_RETRIES 1000 #define IDE_MAX_DRQ_RETRIES 1000
#define IDE_MAX_CMD_RETRIES 1
#define IDE_CMD_TIMEOUT 5
#define IDE_RESET_BUSY_TIMEOUT 31
#define IDE_RESET_DRDY_TIMEOUT 120
#define IDE_REG_ALT_STATUS 0x0006 #define IDE_REG_ALT_STATUS 0x0006
#define IDE_REG_DEV_CNTRL 0x0006 /* device control register */ #define IDE_REG_DEV_CNTRL 0x0006 /* device control register */
@ -80,8 +84,14 @@ extern "C" {
#define IDEWriteDriveHead(Address, Data) (outb_p((Address) + IDE_REG_DRV_HEAD, (Data))) #define IDEWriteDriveHead(Address, Data) (outb_p((Address) + IDE_REG_DRV_HEAD, (Data)))
#define IDEReadStatus(Address) (inb_p((Address) + IDE_REG_STATUS)) #define IDEReadStatus(Address) (inb_p((Address) + IDE_REG_STATUS))
#define IDEWriteCommand(Address, Data) (outb_p((Address) + IDE_REG_COMMAND, (Data))) #define IDEWriteCommand(Address, Data) (outb_p((Address) + IDE_REG_COMMAND, (Data)))
#define IDEReadBlock(Address, Buffer) (insw((Address) + IDE_REG_DATA_PORT, (Buffer), IDE_SECTOR_BUF_SZ / 2))
#define IDEWriteBlock(Address, Buffer) (outsw((Address) + IDE_REG_DATA_PORT, (Buffer), IDE_SECTOR_BUF_SZ / 2)) //
// Data block read and write commands
//
#define IDEReadBlock(Address, Buffer, Count) \
(insw((Address) + IDE_REG_DATA_PORT, (Buffer), (Count) / 2))
#define IDEWriteBlock(Address, Buffer, Count) \
(outsw((Address) + IDE_REG_DATA_PORT, (Buffer), (Count) / 2))
// //
// Access macros for control registers // Access macros for control registers
@ -130,7 +140,10 @@ typedef struct _IDE_DEVICE_EXTENSION {
// //
typedef enum _IDE_TIMER_STATES { typedef enum _IDE_TIMER_STATES {
IDETimerIdle IDETimerIdle,
IDETimerCmdWait,
IDETimerResetWaitForBusyNegate,
IDETimerResetWaitForDrdyAssert
} IDE_TIMER_STATES; } IDE_TIMER_STATES;
// IDE_CONTROLLER_EXTENSION // IDE_CONTROLLER_EXTENSION
@ -157,6 +170,7 @@ typedef struct _IDE_CONTROLLER_EXTENSION {
BYTE DeviceStatus; BYTE DeviceStatus;
PIDE_DEVICE_EXTENSION DeviceForOperation; PIDE_DEVICE_EXTENSION DeviceForOperation;
PIRP CurrentIrp; PIRP CurrentIrp;
int Retries;
IDE_TIMER_STATES TimerState; IDE_TIMER_STATES TimerState;
LONG TimerCount; LONG TimerCount;
@ -186,8 +200,13 @@ typedef struct _IDE_DRIVE_IDENTIFY {
char FirmwareRev[8]; /*23*/ char FirmwareRev[8]; /*23*/
char ModelNumber[40]; /*27*/ char ModelNumber[40]; /*27*/
WORD RWMultImplemented; /*47*/ WORD RWMultImplemented; /*47*/
WORD DWordIOSupported; /*48*/ WORD Reserved48; /*48*/
WORD LBADMASupported; /*49*/ WORD Capabilities; /*49*/
#define IDE_DRID_STBY_SUPPORTED 0x2000
#define IDE_DRID_IORDY_SUPPORTED 0x0800
#define IDE_DRID_IORDY_DISABLE 0x0400
#define IDE_DRID_LBA_SUPPORTED 0x0200
#define IDE_DRID_DMA_SUPPORTED 0x0100
WORD Reserved50; /*50*/ WORD Reserved50; /*50*/
WORD MinPIOTransTime; /*51*/ WORD MinPIOTransTime; /*51*/
WORD MinDMATransTime; /*52*/ WORD MinDMATransTime; /*52*/