/*++//////////////////////////////////////////////////////////////////////////// RetryRequest() Routine Description: This is a wrapper around the delayed retry DPC routine, RetryRequestDPC. This reinitializes the necessary fields, queues the request, and sets a timer to call the DPC if someone hasn't already done so. Arguments: DeviceObject - Supplies the device object associated with this request. Irp - Supplies the request to be retried. Srb - Supplies a Pointer to the SCSI request block to be retied. Associated - Indicates this is an associated Irp created by split request. RetryInterval - How long, in seconds, before retrying the request. Return Value: None --*/ VOID NTAPI RetryRequest( PDEVICE_OBJECT DeviceObject, PIRP Irp, PSCSI_REQUEST_BLOCK Srb, BOOLEAN Associated, ULONG RetryInterval ) { PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); ULONG transferByteCount; // This function is obsolete but is still used by some of our class drivers. // DBGWARN(("RetryRequest is OBSOLETE !")); // // Determine the transfer count of the request. If this is a read or a // write then the transfer count is in the Irp stack. Otherwise assume // the MDL contains the correct length. If there is no MDL then the // transfer length must be zero. // if (currentIrpStack->MajorFunction == IRP_MJ_READ || currentIrpStack->MajorFunction == IRP_MJ_WRITE) { transferByteCount = currentIrpStack->Parameters.Read.Length; } else if (Irp->MdlAddress != NULL) { // // Note this assumes that only read and write requests are spilt and // other request do not need to be. If the data buffer address in // the MDL and the SRB don't match then transfer length is most // likely incorrect. // ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress)); transferByteCount = Irp->MdlAddress->ByteCount; } else { transferByteCount = 0; } // // this is a safety net. this should not normally be hit, since we are // not guaranteed to be an fdoExtension // ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); // // Reset byte count of transfer in SRB Extension. // Srb->DataTransferLength = transferByteCount; // // Zero SRB statuses. // Srb->SrbStatus = Srb->ScsiStatus = 0; // // Set the no disconnect flag, disable synchronous data transfers and // disable tagged queuing. This fixes some errors. // NOTE: Cannot clear these flags, just add to them // SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT); SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER); CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE); Srb->QueueTag = SP_UNTAGGED; // // Set up major SCSI function. // nextIrpStack->MajorFunction = IRP_MJ_SCSI; // // Save SRB address in next stack for port driver. // nextIrpStack->Parameters.Scsi.Srb = Srb; IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE); { LARGE_INTEGER retry100ns; retry100ns.QuadPart = RetryInterval; // seconds retry100ns.QuadPart *= (LONGLONG)1000 * 1000 * 10; ClassRetryRequest(DeviceObject, Irp, retry100ns); } return; } // end RetryRequest()
/*++//////////////////////////////////////////////////////////////////////////// RetryPowerRequest() Routine Description: This routine reinitializes the necessary fields, and sends the request to the lower driver. Arguments: DeviceObject - Supplies the device object associated with this request. Irp - Supplies the request to be retried. Context - Supplies a pointer to the power up context for this request. Return Value: None --*/ VOID NTAPI RetryPowerRequest( PDEVICE_OBJECT DeviceObject, PIRP Irp, PCLASS_POWER_CONTEXT Context ) { PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); PSCSI_REQUEST_BLOCK srb = &(Context->Srb); LARGE_INTEGER dueTime; DebugPrint((1, "(%p)\tDelaying retry by queueing DPC\n", Irp)); ASSERT(Context->Irp == Irp); ASSERT(Context->DeviceObject == DeviceObject); ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER)); ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE)); // // reset the retry interval // Context->RetryInterval = 0; // // Reset byte count of transfer in SRB Extension. // srb->DataTransferLength = 0; // // Zero SRB statuses. // srb->SrbStatus = srb->ScsiStatus = 0; // // Set up major SCSI function. // nextIrpStack->MajorFunction = IRP_MJ_SCSI; // // Save SRB address in next stack for port driver. // nextIrpStack->Parameters.Scsi.Srb = srb; // // Set the completion routine up again. // IoSetCompletionRoutine(Irp, Context->CompletionRoutine, Context, TRUE, TRUE, TRUE); if (Context->RetryInterval == 0) { DebugPrint((2, "(%p)\tDelaying minimum time (.2 sec)\n", Irp)); dueTime.QuadPart = (LONGLONG)1000000 * 2; } else { DebugPrint((2, "(%p)\tDelaying %x seconds\n", Irp, Context->RetryInterval)); dueTime.QuadPart = (LONGLONG)1000000 * 10 * Context->RetryInterval; } ClassRetryRequest(DeviceObject, Irp, dueTime); return; } // end RetryRequest()