mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Added write cache flushing (untested).
svn path=/trunk/; revision=4087
This commit is contained in:
parent
ec65b164ca
commit
6c8aa0f44c
3 changed files with 120 additions and 64 deletions
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: atapi.c,v 1.36 2003/01/28 17:34:20 hbirr Exp $
|
/* $Id: atapi.c,v 1.37 2003/01/30 22:08:15 ekohl Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS ATAPI miniport driver
|
* PROJECT: ReactOS ATAPI miniport driver
|
||||||
|
@ -233,6 +233,9 @@ static ULONG
|
||||||
AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
IN PSCSI_REQUEST_BLOCK Srb);
|
IN PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
|
||||||
|
static ULONG
|
||||||
|
AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
|
||||||
static UCHAR
|
static UCHAR
|
||||||
AtapiErrorToScsi(PVOID DeviceExtension,
|
AtapiErrorToScsi(PVOID DeviceExtension,
|
||||||
|
@ -491,9 +494,9 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension,
|
||||||
SlotNumber.u.bits.DeviceNumber = DeviceNumber;
|
SlotNumber.u.bits.DeviceNumber = DeviceNumber;
|
||||||
for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
|
for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
|
||||||
{
|
{
|
||||||
SlotNumber.u.bits.FunctionNumber = FunctionNumber;
|
SlotNumber.u.bits.FunctionNumber = FunctionNumber;
|
||||||
ChannelFound = FALSE;
|
ChannelFound = FALSE;
|
||||||
DeviceFound = FALSE;
|
DeviceFound = FALSE;
|
||||||
|
|
||||||
DataSize = ScsiPortGetBusData(DeviceExtension,
|
DataSize = ScsiPortGetBusData(DeviceExtension,
|
||||||
PCIConfiguration,
|
PCIConfiguration,
|
||||||
|
@ -514,7 +517,7 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension,
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("%x %x\n", PciConfig.BaseClass, PciConfig.SubClass);
|
DPRINT("%x %x\n", PciConfig.BaseClass, PciConfig.SubClass);
|
||||||
if (PciConfig.BaseClass == 0x01 &&
|
if (PciConfig.BaseClass == 0x01 &&
|
||||||
PciConfig.SubClass == 0x01) // &&
|
PciConfig.SubClass == 0x01) // &&
|
||||||
// (PciConfig.ProgIf & 0x05) == 0)
|
// (PciConfig.ProgIf & 0x05) == 0)
|
||||||
{
|
{
|
||||||
|
@ -1755,7 +1758,7 @@ AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow);
|
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow);
|
||||||
|
|
||||||
/* Issue command to drive */
|
/* Issue command to drive */
|
||||||
IDEWriteCommand(DeviceExtension->CommandPortBase, 0xA0); /* Packet command */
|
IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_PACKET);
|
||||||
|
|
||||||
/* Wait for DRQ to assert */
|
/* Wait for DRQ to assert */
|
||||||
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
|
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
|
||||||
|
@ -1815,6 +1818,11 @@ AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
Srb);
|
Srb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCSIOP_SYNCHRONIZE_CACHE:
|
||||||
|
SrbStatus = AtapiFlushCache(DeviceExtension,
|
||||||
|
Srb);
|
||||||
|
break;
|
||||||
|
|
||||||
case SCSIOP_MODE_SENSE:
|
case SCSIOP_MODE_SENSE:
|
||||||
case SCSIOP_TEST_UNIT_READY:
|
case SCSIOP_TEST_UNIT_READY:
|
||||||
case SCSIOP_VERIFY:
|
case SCSIOP_VERIFY:
|
||||||
|
@ -2132,24 +2140,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
{
|
{
|
||||||
DPRINT ("Drive is BUSY for too long\n");
|
DPRINT ("Drive is BUSY for too long\n");
|
||||||
return(SRB_STATUS_BUSY);
|
return(SRB_STATUS_BUSY);
|
||||||
#if 0
|
|
||||||
if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES)
|
|
||||||
{
|
|
||||||
DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
|
|
||||||
Irp = ControllerExtension->CurrentIrp;
|
|
||||||
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT ("Beginning drive reset sequence\n");
|
|
||||||
IDEBeginControllerReset(ControllerExtension);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select the desired drive */
|
/* Select the desired drive */
|
||||||
|
@ -2173,24 +2163,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
{
|
{
|
||||||
DPRINT("Drive is BUSY for too long after drive select\n");
|
DPRINT("Drive is BUSY for too long after drive select\n");
|
||||||
return(SRB_STATUS_BUSY);
|
return(SRB_STATUS_BUSY);
|
||||||
#if 0
|
|
||||||
if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES)
|
|
||||||
{
|
|
||||||
DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
|
|
||||||
Irp = ControllerExtension->CurrentIrp;
|
|
||||||
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("Beginning drive reset sequence\n");
|
|
||||||
IDEBeginControllerReset(ControllerExtension);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2225,22 +2197,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
{
|
{
|
||||||
DPRINT1("Drive is BUSY for too long after sending write command\n");
|
DPRINT1("Drive is BUSY for too long after sending write command\n");
|
||||||
return(SRB_STATUS_BUSY);
|
return(SRB_STATUS_BUSY);
|
||||||
#if 0
|
|
||||||
if (DeviceExtension->Retries++ > IDE_MAX_CMD_RETRIES)
|
|
||||||
{
|
|
||||||
Irp = ControllerExtension->CurrentIrp;
|
|
||||||
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IDEBeginControllerReset(ControllerExtension);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update DeviceExtension data */
|
/* Update DeviceExtension data */
|
||||||
|
@ -2278,6 +2234,94 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ULONG
|
||||||
|
AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
ULONG Retries;
|
||||||
|
UCHAR Status;
|
||||||
|
|
||||||
|
DPRINT1("AtapiFlushCache() called!\n");
|
||||||
|
|
||||||
|
if (Srb->PathId != 0)
|
||||||
|
{
|
||||||
|
Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
|
||||||
|
return(SRB_STATUS_INVALID_PATH_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Srb->TargetId > 1)
|
||||||
|
{
|
||||||
|
Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
|
||||||
|
return(SRB_STATUS_INVALID_TARGET_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Srb->Lun != 0)
|
||||||
|
{
|
||||||
|
Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
|
||||||
|
return(SRB_STATUS_INVALID_LUN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
|
||||||
|
{
|
||||||
|
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
||||||
|
return(SRB_STATUS_NO_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("SCSIOP_SYNCRONIZE_CACHE: TargetId: %lu\n",
|
||||||
|
Srb->TargetId);
|
||||||
|
|
||||||
|
/* Wait for BUSY to clear */
|
||||||
|
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
|
||||||
|
{
|
||||||
|
Status = IDEReadStatus(DeviceExtension->CommandPortBase);
|
||||||
|
if (!(Status & IDE_SR_BUSY))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ScsiPortStallExecution(10);
|
||||||
|
}
|
||||||
|
DPRINT1("Status=%02x\n", Status);
|
||||||
|
DPRINT1("Waited %ld usecs for busy to clear\n", Retries * 10);
|
||||||
|
if (Retries >= IDE_MAX_BUSY_RETRIES)
|
||||||
|
{
|
||||||
|
DPRINT1("Drive is BUSY for too long\n");
|
||||||
|
return(SRB_STATUS_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select the desired drive */
|
||||||
|
IDEWriteDriveHead(DeviceExtension->CommandPortBase,
|
||||||
|
IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
|
||||||
|
ScsiPortStallExecution(10);
|
||||||
|
|
||||||
|
/* Issue command to drive */
|
||||||
|
IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_FLUSH_CACHE);
|
||||||
|
|
||||||
|
/* Wait for controller ready */
|
||||||
|
for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
|
||||||
|
{
|
||||||
|
BYTE Status = IDEReadStatus(DeviceExtension->CommandPortBase);
|
||||||
|
if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
KeStallExecutionProcessor(10);
|
||||||
|
}
|
||||||
|
if (Retries >= IDE_MAX_WRITE_RETRIES)
|
||||||
|
{
|
||||||
|
DPRINT1("Drive is BUSY for too long after sending write command\n");
|
||||||
|
return(SRB_STATUS_BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Indicate expecting an interrupt. */
|
||||||
|
DeviceExtension->ExpectingInterrupt = TRUE;
|
||||||
|
|
||||||
|
DPRINT1("AtapiFlushCache() done!\n");
|
||||||
|
|
||||||
|
/* Wait for interrupt. */
|
||||||
|
return(SRB_STATUS_PENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static UCHAR
|
static UCHAR
|
||||||
AtapiErrorToScsi(PVOID DeviceExtension,
|
AtapiErrorToScsi(PVOID DeviceExtension,
|
||||||
PSCSI_REQUEST_BLOCK Srb)
|
PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
|
|
@ -61,15 +61,21 @@ extern "C" {
|
||||||
#define IDE_SR_DRQ 0x08
|
#define IDE_SR_DRQ 0x08
|
||||||
#define IDE_SR_ERR 0x01
|
#define IDE_SR_ERR 0x01
|
||||||
#define IDE_REG_COMMAND 0x0007
|
#define IDE_REG_COMMAND 0x0007
|
||||||
|
|
||||||
|
/* IDE/ATA commands */
|
||||||
#define IDE_CMD_RESET 0x08
|
#define IDE_CMD_RESET 0x08
|
||||||
#define IDE_CMD_READ 0x20
|
#define IDE_CMD_READ 0x20
|
||||||
#define IDE_CMD_READ_RETRY 0x21
|
#define IDE_CMD_READ_RETRY 0x21
|
||||||
#define IDE_CMD_WRITE 0x30
|
#define IDE_CMD_WRITE 0x30
|
||||||
#define IDE_CMD_WRITE_RETRY 0x31
|
#define IDE_CMD_WRITE_RETRY 0x31
|
||||||
|
#define IDE_CMD_PACKET 0xA0
|
||||||
#define IDE_CMD_READ_MULTIPLE 0xC4
|
#define IDE_CMD_READ_MULTIPLE 0xC4
|
||||||
#define IDE_CMD_WRITE_MULTIPLE 0xC5
|
#define IDE_CMD_WRITE_MULTIPLE 0xC5
|
||||||
|
#define IDE_CMD_FLUSH_CACHE 0xE7
|
||||||
|
#define IDE_CMD_FLUSH_CACHE_EXT 0xEA
|
||||||
#define IDE_CMD_IDENT_ATA_DRV 0xEC
|
#define IDE_CMD_IDENT_ATA_DRV 0xEC
|
||||||
#define IDE_CMD_IDENT_ATAPI_DRV 0xA1
|
#define IDE_CMD_IDENT_ATAPI_DRV 0xA1
|
||||||
|
|
||||||
//
|
//
|
||||||
// Access macros for command registers
|
// Access macros for command registers
|
||||||
// Each macro takes an address of the command port block, and data
|
// Each macro takes an address of the command port block, and data
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: disk.c,v 1.20 2002/12/15 14:34:06 ekohl Exp $
|
/* $Id: disk.c,v 1.21 2003/01/30 22:09:15 ekohl Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -979,14 +979,20 @@ DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
|
||||||
Srb->TargetId = DeviceExtension->TargetId;
|
Srb->TargetId = DeviceExtension->TargetId;
|
||||||
Srb->Lun = DeviceExtension->Lun;
|
Srb->Lun = DeviceExtension->Lun;
|
||||||
|
|
||||||
|
/* Flush write cache */
|
||||||
/* FIXME: Flush write cache */
|
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
|
||||||
|
Srb->CdbLength = 10;
|
||||||
|
Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
|
||||||
|
ScsiClassSendSrbSynchronous(DeviceObject,
|
||||||
|
Srb,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
/* Get current stack location */
|
/* Get current stack location */
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: Unlock removable media upon shutdown */
|
/* FIXME: Unlock removable media upon shutdown */
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue