Dear all:
I am writting a disk lower filter driver. This driver will pending all IRP(IO request packet) in a queue, copy new IRP, and then send new IRP to lower device, such as AHCI control driver.And the driver need cancel all submitted IRP when it get emergent notification.
But I am worried that the driver can not cancel the IRP that have been fill into NCQ command List quickly. So I want to cancel these IRP by sending reset device command. And I have sent reset device with two solutions. Unluckly, no IRP will be cancelled and no IRP return status is unsuccess after reset device command has been sent.
Currently, I do not known how to work out this issue. And I except you can give some ideas.
Thanks a lot!
The following is detail of these two solutions(The return vaule are also SUCCESS):
The first way:
context = &deviceExtension->resetContext;
if(context == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
// Save the device object in the context for use by the completion
// routine.
context->DeviceObject = deviceExtension->Self;
srb = &context->Srb;
// Zero out srb.
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
// Write length to SRB.
srb->Length = SCSI_REQUEST_BLOCK_SIZE;
srb->Function = SRB_FUNCTION_RESET_DEVICE;
// Build the asynchronous request to be sent to the port driver.
// Since this routine is called from a DPC the IRP should always be
// available.
irp = IoAllocateIrp(deviceExtension->Self->StackSize, FALSE);
if(irp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
IoSetCompletionRoutine(irp,
(PIO_COMPLETION_ROUTINE)ResetDevcieCompletion,
context,
TRUE,
TRUE,
TRUE);
irpStack = IoGetNextIrpStackLocation(irp);
irpStack->MajorFunction = IRP_MJ_SCSI;
srb->OriginalRequest = irp;
// Store the SRB address in next stack for port driver.
irpStack->Parameters.Scsi.Srb = srb;
// Call the port driver with the IRP.
IoCallDriver(deviceExtension->NextLowerDriver, irp);
The second way:
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
// Added by ZYQ. Check sleep flag again before sending unload command.
if(deviceExtension->PowerSleepOperationInProgress)
return STATUS_SUCCESS;
// Build the asynchronous request to be sent to the port driver.
// Since this routine is called from a DPC the IRP should always be
// available.
irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if(irp == NULL) {
#if DBG
#if UNLOAD_TESTING
deviceExtension->uloadCount–;
#endif
#endif
return STATUS_INSUFFICIENT_RESOURCES;
}
context = &deviceExtension->resetContextATA;
RtlZeroMemory(context, sizeof(COMPLETION_CONTEXT_ATACMD));
// Save the device object in the context for use by the completion
// routine.
context->DeviceObject = DeviceObject;
pApte = &context->Apte;
pApte->Length = sizeof(ATA_PASS_THROUGH_EX);
pApte->AtaFlags = ATA_FLAGS_DRDY_REQUIRED; // ATA_FLAGS_DATA_OUT;
pApte->DataTransferLength = 0;
pApte->TimeOutValue = DEFAULT_ATA_PASS_THROUGH_TIMEOUT;
pApte->DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
{
pApte->CurrentTaskFile[0] = 0x00; // na
pApte->CurrentTaskFile[1] = 0x00; // na
pApte->CurrentTaskFile[2] = 0x00; // na
pApte->CurrentTaskFile[3] = 0x00; // na
pApte->CurrentTaskFile[4] = 0x00; // na
pApte->CurrentTaskFile[5] = 0xA0; // Drive Select(A0:Master,B0:Slave)
pApte->CurrentTaskFile[6] = 0x08; // IDE_COMMAND_RESET_DEVICE
}
// Set complete routine.
IoSetCompletionRoutine(irp,
ResetDevcieCompletion,
context,
TRUE,
TRUE,
TRUE);
// Fill with next irp stack.
irpStack = IoGetNextIrpStackLocation(irp);
irpStack->DeviceObject = DeviceObject;
irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_ATA_PASS_THROUGH;
irpStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(ATA_PASS_THROUGH_EX)+sizeof(context->DataBuffer);
irpStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(ATA_PASS_THROUGH_EX)+sizeof(context->DataBuffer);
// Setup system buffer.
irp->AssociatedIrp.SystemBuffer = pApte;
DebugPrintEx((2, “%d:ResetDeviceByAtaCmd: DeviceObject %08X, Irp %08X, Context %08x\n”,
deviceExtension->HddNo, deviceExtension->NextLowerDriver, irp, context));
// Call the port driver with the IRP.
return IoCallDriver(deviceExtension->NextLowerDriver, irp);