📄 diskwmi.c
字号:
&DiskReregHead,
&reregRequest->Next,
&DiskReregSpinlock);
if (InterlockedIncrement(&DiskReregWorkItems) == 1)
{
ExQueueWorkItem( &DiskReregWorkItem, DelayedWorkQueue );
}
status = STATUS_SUCCESS;
} else {
DebugPrint((1, "DiskPostReregisterRequest: could not allocate reregRequest for %p\n",
DeviceObject));
status = STATUS_INSUFFICIENT_RESOURCES;
}
return(status);
}
NTSTATUS DiskInfoExceptionComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
PDISK_DATA diskData = (PDISK_DATA)(commonExtension->DriverData);
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
PSCSI_REQUEST_BLOCK srb = Context;
NTSTATUS status;
BOOLEAN retry;
ULONG retryInterval;
ULONG srbStatus;
BOOLEAN freeLockAndIrp = TRUE;
KIRQL oldIrql;
ASSERT(fdoExtension->CommonExtension.IsFdo);
srbStatus = SRB_STATUS(srb->SrbStatus);
//
// Check SRB status for success of completing request.
// SRB_STATUS_DATA_OVERRUN also indicates success.
//
if ((srbStatus != SRB_STATUS_SUCCESS) &&
(srbStatus != SRB_STATUS_DATA_OVERRUN))
{
DebugPrint((2, "DiskInfoExceptionComplete: IRP %p, SRB %p\n", Irp, srb));
retry = ClassInterpretSenseInfo(
DeviceObject,
srb,
irpStack->MajorFunction,
0,
MAXIMUM_RETRIES -
((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
&status,
&retryInterval);
//
// If the status is verified required and the this request
// should bypass verify required then retry the request.
//
if (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
status == STATUS_VERIFY_REQUIRED)
{
status = STATUS_IO_DEVICE_ERROR;
retry = TRUE;
}
if (retry && ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--)
{
//
// Retry request.
//
DebugPrint((1, "DiskInfoExceptionComplete: Retry request %p\n", Irp));
ASSERT(srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
//
// Reset byte count of transfer in SRB Extension.
//
srb->DataTransferLength = Irp->MdlAddress->ByteCount;
//
// 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.
//
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->QueueAction = SRB_SIMPLE_TAG_REQUEST;
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,
DiskInfoExceptionComplete,
srb,
TRUE, TRUE, TRUE);
(VOID)IoCallDriver(commonExtension->LowerDeviceObject, Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
} else {
//
// Get the results from the mode sense
//
PMODE_INFO_EXCEPTIONS pageData;
PMODE_PARAMETER_HEADER modeData;
ULONG modeDataLength;
modeData = srb->DataBuffer;
modeDataLength = srb->DataTransferLength;
pageData = ClassFindModePage((PUCHAR) modeData,
modeDataLength,
MODE_PAGE_FAULT_REPORTING,
TRUE);
if (pageData != NULL)
{
DebugPrint((1, "DiskInfoExceptionComplete: %p supports SMART\n",
DeviceObject));
if (pageData->Dexcpt == 0)
{
diskData->FailurePredictionCapability = FailurePredictionSense;
status = DiskPostReregisterRequest(DeviceObject, Irp);
if (NT_SUCCESS(status))
{
//
// Make sure we won't free the remove lock and the irp
// since we need to keep these until after the work
// item has completed running
//
freeLockAndIrp = FALSE;
}
} else {
DebugPrint((1, "DiskInfoExceptionComplete: %p is not enabled for SMART\n",
DeviceObject));
}
} else {
DebugPrint((1, "DiskInfoExceptionComplete: %p does not supports SMART\n",
DeviceObject));
}
//
// Set status for successful request
//
status = STATUS_SUCCESS;
} // end if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS)
//
// Free the srb
//
ExFreePool(srb->SenseInfoBuffer);
ExFreePool(srb->DataBuffer);
ExFreePool(srb);
if (freeLockAndIrp)
{
//
// Set status in completing IRP.
//
Irp->IoStatus.Status = status;
//
// If pending has be returned for this irp then mark the current stack as
// pending.
//
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
ClassReleaseRemoveLock(DeviceObject, Irp);
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
}
return(STATUS_MORE_PROCESSING_REQUIRED);
}
NTSTATUS DiskInfoExceptionCheck(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
)
{
PUCHAR modeData;
PSCSI_REQUEST_BLOCK srb;
PCDB cdb;
PIRP irp;
PIO_STACK_LOCATION irpStack;
PVOID senseInfoBuffer;
ULONG isRemoved;
modeData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
MODE_DATA_SIZE,
DISK_TAG_INFO_EXCEPTION);
if (modeData == NULL)
{
DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate mode data "
"buffer\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
srb = ExAllocatePoolWithTag(NonPagedPool,
SCSI_REQUEST_BLOCK_SIZE,
DISK_TAG_SRB);
if (srb == NULL)
{
ExFreePool(modeData);
DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate srb "
"buffer\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Build the MODE SENSE CDB.
//
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
cdb = (PCDB)srb->Cdb;
srb->CdbLength = 6;
cdb = (PCDB)srb->Cdb;
//
// Set timeout value from device extension.
//
srb->TimeOutValue = FdoExtension->TimeOutValue;
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
cdb->MODE_SENSE.PageCode = MODE_PAGE_FAULT_REPORTING;
cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
//
// Write length to SRB.
//
srb->Length = SCSI_REQUEST_BLOCK_SIZE;
//
// Set SCSI bus address.
//
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
//
// Enable auto request sense.
//
srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
//
// Sense buffer is in aligned nonpaged pool.
//
senseInfoBuffer = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
SENSE_BUFFER_SIZE,
'7CcS');
if (senseInfoBuffer == NULL)
{
ExFreePool(srb);
ExFreePool(modeData);
DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate request sense "
"buffer\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
srb->SenseInfoBuffer = senseInfoBuffer;
srb->DataBuffer = modeData;
srb->SrbFlags = FdoExtension->SrbFlags;
SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN);
//
// Disable synchronous transfer for these requests.
//
SET_FLAG(srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
//
// Don't freeze the queue on an error
//
SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
srb->QueueTag = SP_UNTAGGED;
//
// Build device I/O control request with METHOD_NEITHER data transfer.
// We'll queue a completion routine to cleanup the MDL's and such ourself.
//
irp = IoAllocateIrp(
(CCHAR) (FdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1),
FALSE);
if (irp == NULL)
{
ExFreePool(senseInfoBuffer);
ExFreePool(srb);
ExFreePool(modeData);
DebugPrint((1, "DiskInfoExceptionCheck: Can't allocate Irp\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
isRemoved = ClassAcquireRemoveLock(FdoExtension->DeviceObject, irp);
if (isRemoved)
{
ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
IoFreeIrp(irp);
ExFreePool(senseInfoBuffer);
ExFreePool(srb);
ExFreePool(modeData);
DebugPrint((1, "DiskInfoExceptionCheck: RemoveLock says isRemoved\n"));
return(STATUS_DEVICE_DOES_NOT_EXIST);
}
//
// Get next stack location.
//
IoSetNextIrpStackLocation(irp);
irpStack = IoGetCurrentIrpStackLocation(irp);
irpStack->DeviceObject = FdoExtension->DeviceObject;
//
// Save retry count in current Irp stack.
//
irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
irpStack = IoGetNextIrpStackLocation(irp);
//
// Set up SRB for execute scsi request. Save SRB address in next stack
// for the port driver.
//
irpStack->MajorFunction = IRP_MJ_SCSI;
irpStack->Parameters.Scsi.Srb = srb;
IoSetCompletionRoutine(irp,
DiskInfoExceptionComplete,
srb,
TRUE,
TRUE,
TRUE);
irp->MdlAddress = IoAllocateMdl( modeData,
MODE_DATA_SIZE,
FALSE,
FALSE,
irp );
if (irp->MdlAddress == NULL)
{
ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
ExFreePool(srb);
ExFreePool(modeData);
ExFreePool(senseInfoBuffer);
IoFreeIrp( irp );
DebugPrint((1, "DiskINfoExceptionCheck: Can't allocate MDL\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(irp->MdlAddress);
//
// Set the transfer length.
//
srb->DataTransferLength = MODE_DATA_SIZE;
//
// Zero out status.
//
srb->ScsiStatus = srb->SrbStatus = 0;
srb->NextSrb = 0;
//
// Set up IRP Address.
//
srb->OriginalRequest = irp;
//
// Call the port driver with the request and wait for it to complete.
//
IoMarkIrpPending(irp);
IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject,
irp);
return(STATUS_PENDING);
}
NTSTATUS
DiskDetectFailurePrediction(
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
PFAILURE_PREDICTION_METHOD FailurePredictCapability
)
/*++
Routine Description:
Detect if device has any failure prediction capabilities. First we
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -