📄 class2.c
字号:
NULL,
0,
BufferAddress,
BufferLength,
TRUE,
&event,
&ioStatus);
if (irp == NULL) {
ExFreePool(senseInfoBuffer);
DebugPrint((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n"));
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Disable synchronous transfer for these requests.
//
Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
//
// Set the transfer length.
//
Srb->DataTransferLength = BufferLength;
//
// Zero out status.
//
Srb->ScsiStatus = Srb->SrbStatus = 0;
Srb->NextSrb = 0;
//
// Get next stack location.
//
irpStack = IoGetNextIrpStackLocation(irp);
//
// Set up SRB for execute scsi request. Save SRB address in next stack
// for the port driver.
//
irpStack->Parameters.Scsi.Srb = Srb;
//
// Set up IRP Address.
//
Srb->OriginalRequest = irp;
//
// Call the port driver with the request and wait for it to complete.
//
status = IoCallDriver(deviceExtension->PortDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
}
//
// Check that request completed without error.
//
if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {
//
// Release the queue if it is frozen.
//
if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
ScsiClassReleaseQueue(DeviceObject);
}
//
// Update status and determine if request should be retried.
//
retry = ScsiClassInterpretSenseInfo(DeviceObject,
Srb,
IRP_MJ_SCSI,
0,
MAXIMUM_RETRIES - retryCount,
&status);
if (retry) {
if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer)
->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) ||
SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) {
LARGE_INTEGER delay;
//
// Delay for 2 seconds.
//
delay.QuadPart = (LONGLONG)( - 10 * 1000 * 1000 * 2 );
//
// Stall for a while to let the controller spinup.
//
KeDelayExecutionThread(KernelMode,
FALSE,
&delay);
}
//
// If retries are not exhausted then retry this operation.
//
if (retryCount--) {
goto retry;
}
}
} else {
status = STATUS_SUCCESS;
}
ExFreePool(senseInfoBuffer);
return status;
} // end ScsiClassSendSrbSynchronous()
BOOLEAN
STDCALL
ScsiClassInterpretSenseInfo(
IN PDEVICE_OBJECT DeviceObject,
IN PSCSI_REQUEST_BLOCK Srb,
IN UCHAR MajorFunctionCode,
IN ULONG IoDeviceCode,
IN ULONG RetryCount,
OUT NTSTATUS *Status
)
/*++
Routine Description:
This routine interprets the data returned from the SCSI
request sense. It determines the status to return in the
IRP and whether this request can be retried.
Arguments:
DeviceObject - Supplies the device object associated with this request.
Srb - Supplies the scsi request block which failed.
MajorFunctionCode - Supplies the function code to be used for logging.
IoDeviceCode - Supplies the device code to be used for logging.
Status - Returns the status for the request.
Return Value:
BOOLEAN TRUE: Drivers should retry this request.
FALSE: Drivers should not retry this request.
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension;
PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
BOOLEAN retry = TRUE;
BOOLEAN logError = FALSE;
ULONG badSector = 0;
ULONG uniqueId = 0;
NTSTATUS logStatus;
ULONG readSector;
ULONG index;
PIO_ERROR_LOG_PACKET errorLogEntry;
#if DBG
ULONG i;
#endif
//
// Check that request sense buffer is valid.
//
#if DBG
DebugPrint((3, "Opcode %x\nParameters: ",Srb->Cdb[0]));
for (i = 1; i < 12; i++) {
DebugPrint((3,"%x ",Srb->Cdb[i]));
}
DebugPrint((3,"\n"));
#endif
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID &&
Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) {
DebugPrint((1,"ScsiClassInterpretSenseInfo: Error code is %x\n",
senseBuffer->ErrorCode));
DebugPrint((1,"ScsiClassInterpretSenseInfo: Sense key is %x\n",
senseBuffer->SenseKey));
DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code is %x\n",
senseBuffer->AdditionalSenseCode));
DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code qualifier is %x\n",
senseBuffer->AdditionalSenseCodeQualifier));
//
// Zero the additional sense code and additional sense code qualifier
// if they were not returned by the device.
//
readSector = senseBuffer->AdditionalSenseLength +
FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
if (readSector > Srb->SenseInfoBufferLength) {
readSector = Srb->SenseInfoBufferLength;
}
if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCode)) {
senseBuffer->AdditionalSenseCode = 0;
}
if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier)) {
senseBuffer->AdditionalSenseCodeQualifier = 0;
}
switch (senseBuffer->SenseKey & 0xf) {
case SCSI_SENSE_NOT_READY:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Device not ready\n"));
*Status = STATUS_DEVICE_NOT_READY;
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_LUN_NOT_READY:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Lun not ready\n"));
switch (senseBuffer->AdditionalSenseCodeQualifier) {
case SCSI_SENSEQ_BECOMING_READY:
DebugPrint((1, "ScsiClassInterpretSenseInfo:"
" In process of becoming ready\n"));
break;
case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:
DebugPrint((1, "ScsiClassInterpretSenseInfo:"
" Manual intervention required\n"));
*Status = STATUS_NO_MEDIA_IN_DEVICE;
retry = FALSE;
break;
case SCSI_SENSEQ_FORMAT_IN_PROGRESS:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Format in progress\n"));
retry = FALSE;
break;
case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:
default:
DebugPrint((1, "ScsiClassInterpretSenseInfo:"
" Initializing command required\n"));
//
// This sense code/additional sense code
// combination may indicate that the device
// needs to be started. Send an start unit if this
// is a disk device.
//
if (deviceExtension->DeviceFlags & DEV_SAFE_START_UNIT) {
StartUnit(DeviceObject);
}
break;
} // end switch (senseBuffer->AdditionalSenseCodeQualifier)
break;
case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
DebugPrint((1,
"ScsiClassInterpretSenseInfo:"
" No Media in device.\n"));
*Status = STATUS_NO_MEDIA_IN_DEVICE;
retry = FALSE;
//
// signal autorun that there isn't any media in the device
//
if((deviceExtension->MediaChangeEvent != NULL)&&
(!deviceExtension->MediaChangeNoMedia)) {
KeSetEvent(deviceExtension->MediaChangeEvent,
(KPRIORITY) 0,
FALSE);
DebugPrint((0, "ScsiClassInterpretSenseInfo:"
"Detected No Media In Device "
"[irp = 0x%lx]\n", Srb->OriginalRequest));
deviceExtension->MediaChangeNoMedia = TRUE;
}
break;
} // end switch (senseBuffer->AdditionalSenseCode)
break;
case SCSI_SENSE_DATA_PROTECT:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Media write protected\n"));
*Status = STATUS_MEDIA_WRITE_PROTECTED;
retry = FALSE;
break;
case SCSI_SENSE_MEDIUM_ERROR:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Bad media\n"));
*Status = STATUS_DEVICE_DATA_ERROR;
retry = FALSE;
logError = TRUE;
uniqueId = 256;
logStatus = 0;//IO_ERR_BAD_BLOCK;
break;
case SCSI_SENSE_HARDWARE_ERROR:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Hardware error\n"));
*Status = STATUS_IO_DEVICE_ERROR;
logError = TRUE;
uniqueId = 257;
logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
break;
case SCSI_SENSE_ILLEGAL_REQUEST:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal SCSI request\n"));
*Status = STATUS_INVALID_DEVICE_REQUEST;
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_ILLEGAL_COMMAND:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal command\n"));
retry = FALSE;
break;
case SCSI_ADSENSE_ILLEGAL_BLOCK:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal block address\n"));
*Status = STATUS_NONEXISTENT_SECTOR;
retry = FALSE;
break;
case SCSI_ADSENSE_INVALID_LUN:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Invalid LUN\n"));
*Status = STATUS_NO_SUCH_DEVICE;
retry = FALSE;
break;
case SCSI_ADSENSE_MUSIC_AREA:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Music area\n"));
retry = FALSE;
break;
case SCSI_ADSENSE_DATA_AREA:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Data area\n"));
retry = FALSE;
break;
case SCSI_ADSENSE_VOLUME_OVERFLOW:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Volume overflow\n"));
retry = FALSE;
break;
case SCSI_ADSENSE_INVALID_CDB:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Invalid CDB\n"));
//
// Check if write cache enabled.
//
if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
//
// Assume FUA is not supported.
//
deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
retry = TRUE;
} else {
retry = FALSE;
}
break;
} // end switch (senseBuffer->AdditionalSenseCode)
break;
case SCSI_SENSE_UNIT_ATTENTION:
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_MEDIUM_CHANGED:
DebugPrint((1, "ScsiClassInterpretSenseInfo: Media changed\n"));
if(deviceExtension->MediaChangeEvent != NULL) {
KeSetEvent(deviceExtension->MediaChangeEvent,
(KPRIORITY) 0,
FALSE);
DebugPrint((0, "ScsiClassInterpretSenseInfo:"
"New Media Found - Setting MediaChanged event"
" [irp = 0x%lx]\n", Srb->OriginalRequest));
deviceExtension->MediaChangeNoMedia = FALSE;
}
break;
case SCSI_ADSENSE_BUS_RESET:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Bus reset\n"));
break;
default:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Unit attention\n"));
break;
} // end switch (senseBuffer->AdditionalSenseCode)
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
DeviceObject->Vpb->Flags & VPB_MOUNTED) {
//
// Set bit to indicate that media may have changed
// and volume needs verification.
//
DeviceObject->Flags |= DO_VERIFY_VOLUME;
*Status = STATUS_VERIFY_REQUIRED;
retry = FALSE;
} else {
*Status = STATUS_IO_DEVICE_ERROR;
}
//
// A media change may have occured so increment the change
// count for the physical device
//
physicalExtension->MediaChangeCount++;
DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change "
"count for device %d is %d\n",
physicalExtension->DeviceNumber,
physicalExtension->MediaChangeCount));
break;
case SCSI_SENSE_ABORTED_COMMAND:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Command aborted\n"));
*Status = STATUS_IO_DEVICE_ERROR;
break;
case SCSI_SENSE_RECOVERED_ERROR:
DebugPrint((1,"ScsiClassInterpretSenseInfo: Recovered error\n"));
*Status = STATUS_SUCCESS;
retry = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -