📄 tape.c
字号:
case STATUS_IO_TIMEOUT:
*TapeStatus = TAPE_STATUS_IO_TIMEOUT;
break;
case STATUS_DEVICE_NOT_CONNECTED:
*TapeStatus = TAPE_STATUS_DEVICE_NOT_CONNECTED;
break;
case STATUS_DATA_OVERRUN:
*TapeStatus = TAPE_STATUS_DATA_OVERRUN;
break;
case STATUS_DEVICE_BUSY:
*TapeStatus = TAPE_STATUS_DEVICE_BUSY;
break;
case STATUS_CLEANER_CARTRIDGE_INSTALLED:
*TapeStatus = TAPE_STATUS_CLEANER_CARTRIDGE_INSTALLED;
break;
default:
return FALSE;
}
return TRUE;
}
BOOLEAN
ScsiTapeTapeStatusToNtStatus(
IN TAPE_STATUS TapeStatus,
OUT PNTSTATUS NtStatus
)
/*++
Routine Description:
This routine translates a TAPE status code to an NT status code.
Arguments:
TapeStatus - Supplies the tape status code.
NtStatus - Returns the NT status code.
Return Value:
FALSE - No tranlation was possible.
TRUE - Success.
--*/
{
switch (TapeStatus) {
case TAPE_STATUS_SUCCESS:
*NtStatus = STATUS_SUCCESS;
break;
case TAPE_STATUS_INSUFFICIENT_RESOURCES:
*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
case TAPE_STATUS_NOT_IMPLEMENTED:
*NtStatus = STATUS_NOT_IMPLEMENTED;
break;
case TAPE_STATUS_INVALID_DEVICE_REQUEST:
*NtStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
case TAPE_STATUS_INVALID_PARAMETER:
*NtStatus = STATUS_INVALID_PARAMETER;
break;
case TAPE_STATUS_MEDIA_CHANGED:
*NtStatus = STATUS_VERIFY_REQUIRED;
break;
case TAPE_STATUS_BUS_RESET:
*NtStatus = STATUS_BUS_RESET;
break;
case TAPE_STATUS_SETMARK_DETECTED:
*NtStatus = STATUS_SETMARK_DETECTED;
break;
case TAPE_STATUS_FILEMARK_DETECTED:
*NtStatus = STATUS_FILEMARK_DETECTED;
break;
case TAPE_STATUS_BEGINNING_OF_MEDIA:
*NtStatus = STATUS_BEGINNING_OF_MEDIA;
break;
case TAPE_STATUS_END_OF_MEDIA:
*NtStatus = STATUS_END_OF_MEDIA;
break;
case TAPE_STATUS_BUFFER_OVERFLOW:
*NtStatus = STATUS_BUFFER_OVERFLOW;
break;
case TAPE_STATUS_NO_DATA_DETECTED:
*NtStatus = STATUS_NO_DATA_DETECTED;
break;
case TAPE_STATUS_EOM_OVERFLOW:
*NtStatus = STATUS_EOM_OVERFLOW;
break;
case TAPE_STATUS_NO_MEDIA:
*NtStatus = STATUS_NO_MEDIA;
break;
case TAPE_STATUS_IO_DEVICE_ERROR:
*NtStatus = STATUS_IO_DEVICE_ERROR;
break;
case TAPE_STATUS_UNRECOGNIZED_MEDIA:
*NtStatus = STATUS_UNRECOGNIZED_MEDIA;
break;
case TAPE_STATUS_DEVICE_NOT_READY:
*NtStatus = STATUS_DEVICE_NOT_READY;
break;
case TAPE_STATUS_MEDIA_WRITE_PROTECTED:
*NtStatus = STATUS_MEDIA_WRITE_PROTECTED;
break;
case TAPE_STATUS_DEVICE_DATA_ERROR:
*NtStatus = STATUS_DEVICE_DATA_ERROR;
break;
case TAPE_STATUS_NO_SUCH_DEVICE:
*NtStatus = STATUS_NO_SUCH_DEVICE;
break;
case TAPE_STATUS_INVALID_BLOCK_LENGTH:
*NtStatus = STATUS_INVALID_BLOCK_LENGTH;
break;
case TAPE_STATUS_IO_TIMEOUT:
*NtStatus = STATUS_IO_TIMEOUT;
break;
case TAPE_STATUS_DEVICE_NOT_CONNECTED:
*NtStatus = STATUS_DEVICE_NOT_CONNECTED;
break;
case TAPE_STATUS_DATA_OVERRUN:
*NtStatus = STATUS_DATA_OVERRUN;
break;
case TAPE_STATUS_DEVICE_BUSY:
*NtStatus = STATUS_DEVICE_BUSY;
break;
case TAPE_STATUS_REQUIRES_CLEANING:
*NtStatus = STATUS_DEVICE_REQUIRES_CLEANING;
break;
case TAPE_STATUS_CLEANER_CARTRIDGE_INSTALLED:
*NtStatus = STATUS_CLEANER_CARTRIDGE_INSTALLED;
break;
default:
return FALSE;
}
return TRUE;
}
VOID
TapeError(
IN PDEVICE_OBJECT FDO,
IN PSCSI_REQUEST_BLOCK Srb,
IN OUT PNTSTATUS Status,
IN OUT PBOOLEAN Retry
)
/*++
Routine Description:
When a request completes with error, the routine ScsiClassInterpretSenseInfo is
called to determine from the sense data whether the request should be
retried and what NT status to set in the IRP. Then this routine is called
for tape requests to handle tape-specific errors and update the nt status
and retry boolean.
Arguments:
DeviceObject - Supplies a pointer to the device object.
Srb - Supplies a pointer to the failing Srb.
Status - NT Status used to set the IRP's completion status.
Retry - Indicates that this request should be retried.
Return Value:
None.
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = FDO->DeviceExtension;
PTAPE_DATA tapeData = (PTAPE_DATA)(fdoExtension->CommonExtension.DriverData);
PTAPE_INIT_DATA_EX tapeInitData = &tapeData->TapeInitData;
PVOID minitapeExtension = (tapeData + 1);
PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
PIRP irp = Srb->OriginalRequest;
LONG residualBlocks;
LONG length;
TAPE_STATUS tapeStatus, oldTapeStatus;
TARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure[2];
//
// Never retry tape requests.
//
*Retry = FALSE;
//
// Check that request sense buffer is valid.
//
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) {
DebugPrint((1,
"Sense Code : %x, Ad Sense : %x, Ad Sense Qual : %x\n",
((senseBuffer->SenseKey) & 0xf),
(senseBuffer->AdditionalSenseCode),
(senseBuffer->AdditionalSenseCodeQualifier)));
switch (senseBuffer->SenseKey & 0xf) {
case SCSI_SENSE_UNIT_ATTENTION:
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_MEDIUM_CHANGED:
DebugPrint((1,
"InterpretSenseInfo: Media changed\n"));
*Status = STATUS_MEDIA_CHANGED;
break;
default:
DebugPrint((1,
"InterpretSenseInfo: Bus reset\n"));
*Status = STATUS_BUS_RESET;
break;
}
break;
case SCSI_SENSE_RECOVERED_ERROR:
//
// Check other indicators
//
if (senseBuffer->FileMark) {
switch (senseBuffer->AdditionalSenseCodeQualifier) {
case SCSI_SENSEQ_SETMARK_DETECTED :
DebugPrint((1,
"InterpretSenseInfo: Setmark detected\n"));
*Status = STATUS_SETMARK_DETECTED;
break ;
case SCSI_SENSEQ_FILEMARK_DETECTED :
default:
DebugPrint((1,
"InterpretSenseInfo: Filemark detected\n"));
*Status = STATUS_FILEMARK_DETECTED;
break ;
}
} else if ( senseBuffer->EndOfMedia ) {
switch ( senseBuffer->AdditionalSenseCodeQualifier ) {
case SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED :
DebugPrint((1,
"InterpretSenseInfo: Beginning of media detected\n"));
*Status = STATUS_BEGINNING_OF_MEDIA;
break ;
case SCSI_SENSEQ_END_OF_MEDIA_DETECTED :
default:
DebugPrint((1,
"InterpretSenseInfo: End of media detected\n"));
*Status = STATUS_END_OF_MEDIA;
break ;
}
}
break;
case SCSI_SENSE_NO_SENSE:
//
// Check other indicators
//
if (senseBuffer->FileMark) {
switch ( senseBuffer->AdditionalSenseCodeQualifier ) {
case SCSI_SENSEQ_SETMARK_DETECTED :
DebugPrint((1,
"InterpretSenseInfo: Setmark detected\n"));
*Status = STATUS_SETMARK_DETECTED;
break ;
case SCSI_SENSEQ_FILEMARK_DETECTED :
default:
DebugPrint((1,
"InterpretSenseInfo: Filemark detected\n"));
*Status = STATUS_FILEMARK_DETECTED;
break ;
}
} else if (senseBuffer->EndOfMedia) {
switch (senseBuffer->AdditionalSenseCodeQualifier) {
case SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED :
DebugPrint((1,
"InterpretSenseInfo: Beginning of media detected\n"));
*Status = STATUS_BEGINNING_OF_MEDIA;
break ;
case SCSI_SENSEQ_END_OF_MEDIA_DETECTED :
default:
DebugPrint((1,
"InterpretSenseInfo: End of media detected\n"));
*Status = STATUS_END_OF_MEDIA;
break;
}
} else if (senseBuffer->IncorrectLength) {
//
// If we're in variable block mode then ignore
// incorrect length.
//
if (fdoExtension->DiskGeometry.BytesPerSector == 0 &&
Srb->Cdb[0] == SCSIOP_READ6) {
REVERSE_BYTES((FOUR_BYTE UNALIGNED *)&residualBlocks,
(FOUR_BYTE UNALIGNED *)(senseBuffer->Information));
if (residualBlocks >= 0) {
DebugPrint((1,"InterpretSenseInfo: In variable block mode :We read less than specified\n"));
*Status = STATUS_SUCCESS;
} else {
DebugPrint((1,"InterpretSenseInfo: In variable block mode :Data left in block\n"));
*Status = STATUS_BUFFER_OVERFLOW;
}
}
}
break;
case SCSI_SENSE_BLANK_CHECK:
DebugPrint((1,
"InterpretSenseInfo: Media blank check\n"));
*Status = STATUS_NO_DATA_DETECTED;
break;
case SCSI_SENSE_VOL_OVERFLOW:
DebugPrint((1,
"InterpretSenseInfo: End of Media Overflow\n"));
*Status = STATUS_EOM_OVERFLOW;
break;
case SCSI_SENSE_NOT_READY:
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_LUN_NOT_READY:
switch (senseBuffer->AdditionalSenseCodeQualifier) {
case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:
*Status = STATUS_NO_MEDIA;
break;
case SCSI_SENSEQ_FORMAT_IN_PROGRESS:
break;
case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:
default:
//
// Allow retries, if the drive isn't ready.
//
*Retry = TRUE;
break;
}
break;
case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
DebugPrint((1,
"InterpretSenseInfo:"
" No Media in device.\n"));
*Status = STATUS_NO_MEDIA;
break;
}
break;
} // end switch
//
// Check if a filemark or setmark was encountered,
// or an end-of-media or no-data condition exists.
//
if ((NT_WARNING(*Status) || NT_SUCCESS( *Status)) &&
(Srb->Cdb[0] == SCSIOP_WRITE6 || Srb->Cdb[0] == SCSIOP_READ6)) {
LONG actualLength;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -