{
BOOLEAN packetDone;
DBGTRACE(ClassDebugTrace, ("retrying failed transfer (pkt=%ph, op=%s)", Pkt, DBGGETSCSIOPSTR(&Pkt->Srb)));
ASSERT(Pkt->NumRetries > 0);
Pkt->NumRetries--;
/* * Tone down performance on the retry. * This increases the chance for success on the retry. * We've seen instances of drives that fail consistently but then start working * once this scale-down is applied. */SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
CLEAR_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
Pkt->Srb.QueueTag = SP_UNTAGGED;
if (Pkt->Irp->IoStatus.Status == STATUS_INSUFFICIENT_RESOURCES){
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
BOOLEAN isReadWrite = ((pCdb->CDB10.OperationCode == SCSIOP_READ) ||
(pCdb->CDB10.OperationCode == SCSIOP_WRITE));
if (Pkt->InLowMemRetry || !isReadWrite){
/* * This should never happen. * The memory manager guarantees that at least four pages will * be available to allow forward progress in the port driver. * So a one-page transfer should never fail with insufficient resources. */ASSERT(isReadWrite && !Pkt->InLowMemRetry);
packetDone = TRUE;
}
else {
/* * We are in low-memory stress. * Start the low-memory retry state machine, which tries to * resend the packet in little one-page chunks. */InitLowMemRetry( Pkt,
Pkt->BufPtrCopy,
Pkt->BufLenCopy,
Pkt->TargetLocationCopy);
StepLowMemRetry(Pkt);
packetDone = FALSE;
}
}
else {
/* * Retry the packet by simply resending it after a delay. * Put the packet back in the pending queue and * schedule a timer to retry the transfer. * * Do not call SetupReadWriteTransferPacket again because: * (1) The minidriver may have set some bits * in the SRB that it needs again and * (2) doing so would reset numRetries. * * BECAUSE we do not call SetupReadWriteTransferPacket again, * we have to reset a couple fields in the SRB that * some miniports overwrite when they fail an SRB. */
Pkt->Srb.DataBuffer = Pkt->BufPtrCopy;
Pkt->Srb.DataTransferLength = Pkt->BufLenCopy;
if (Pkt->RetryIntervalSec == 0){
/* * Always delay by at least a little when retrying. * Some problems (e.g. CRC errors) are not recoverable without a slight delay. */LARGE_INTEGER timerPeriod;
timerPeriod.HighPart = -1;
timerPeriod.LowPart = -(LONG)((ULONG)MINIMUM_RETRY_UNITS*KeQueryTimeIncrement());
KeInitializeTimer(&Pkt->RetryTimer);
KeInitializeDpc(&Pkt->RetryTimerDPC, TransferPacketRetryTimerDpc, Pkt);
KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
}
else {
LARGE_INTEGER timerPeriod;
ASSERT(Pkt->RetryIntervalSec < 100); // sanity check
timerPeriod.HighPart = -1;
timerPeriod.LowPart = Pkt->RetryIntervalSec*-10000000;
KeInitializeTimer(&Pkt->RetryTimer);
KeInitializeDpc(&Pkt->RetryTimerDPC, TransferPacketRetryTimerDpc, Pkt);
KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
}
packetDone = FALSE;
}
return packetDone;
}
Generated on Fri May 25 2012 05:23:47 for ReactOS by
1.7.6.1
ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.