mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2601 lines
69 KiB
2601 lines
69 KiB
/*++
|
|
|
|
Copyright (c) 1994 Arcada Software Inc. - All rights reserved
|
|
|
|
Module Name:
|
|
|
|
4mmsony.c
|
|
|
|
Abstract:
|
|
|
|
This module contains device-specific routines for 4mm DAT drives:
|
|
SONY SDT-2000, SONY SDT-4000, SDT-5000, and SDT-5200.
|
|
|
|
Author:
|
|
|
|
Mike Colandreo (Arcada Software)
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Revision History:
|
|
|
|
|
|
$Log$
|
|
|
|
|
|
--*/
|
|
|
|
#include "ntddk.h"
|
|
#include "4mmsony.h"
|
|
|
|
//
|
|
// Internal (module wide) defines that symbolize
|
|
// the 4mm DAT drives supported by this module.
|
|
//
|
|
#define SONY_SDT2000 1
|
|
#define SONY_SDT4000 2
|
|
#define SONY_SDT5000 3
|
|
#define SONY_SDT5200 4
|
|
|
|
//
|
|
// Internal (module wide) defines that symbolize
|
|
// various 4mm DAT "partitioned" states.
|
|
//
|
|
#define NOT_PARTITIONED 0 // must be zero -- != 0 means partitioned
|
|
#define SELECT_PARTITIONED 1
|
|
#define INITIATOR_PARTITIONED 2
|
|
#define FIXED_PARTITIONED 3
|
|
|
|
//
|
|
// Internal (module wide) define that symbolizes
|
|
// the 4mm DAT "no partitions" partition method.
|
|
//
|
|
#define NO_PARTITIONS 0xFFFFFFFF
|
|
|
|
//
|
|
// Function prototype(s) for internal function(s)
|
|
//
|
|
static ULONG WhichIsIt(IN PINQUIRYDATA InquiryData);
|
|
|
|
|
|
NTSTATUS
|
|
TapeCreatePartition(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine creates partitions on a 4mm DAT tape or returns
|
|
the tape to a not partitioned state (where the whole, entire
|
|
tape is a single, and the only, "partition").
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer;
|
|
PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
|
|
PMODE_DEVICE_CONFIG_PAGE deviceConfigModeSenseBuffer;
|
|
PMODE_MEDIUM_PART_PAGE modeSelectBuffer;
|
|
ULONG partitionMethod;
|
|
ULONG partitionCount;
|
|
ULONG partition;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
DebugPrint((3,"TapeCreatePartition: Enter routine\n"));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeCreatePartition: SendSrb (test unit ready)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeCreatePartition: test unit ready, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
partitionMethod = tapePartition->Method;
|
|
partitionCount = tapePartition->Count;
|
|
|
|
//
|
|
// Filter out invalid partition counts.
|
|
//
|
|
|
|
switch (partitionCount) {
|
|
case 0:
|
|
partitionMethod = NO_PARTITIONS;
|
|
break;
|
|
|
|
case 1:
|
|
case 2:
|
|
break;
|
|
|
|
default:
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeCreatePartition: "));
|
|
DebugPrint((1,"partitionCount -- invalid request\n"));
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Filter out the partition methods that
|
|
// are not implemented on the Sony drives.
|
|
//
|
|
|
|
switch (partitionMethod) {
|
|
case TAPE_FIXED_PARTITIONS:
|
|
DebugPrint((3,"TapeCreatePartition: fixed partitions\n"));
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case TAPE_SELECT_PARTITIONS:
|
|
DebugPrint((3,"TapeCreatePartition: select partitions\n"));
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
|
|
case TAPE_INITIATOR_PARTITIONS:
|
|
DebugPrint((3,"TapeCreatePartition: initiator partitions\n"));
|
|
if (--partitionCount == 0) {
|
|
|
|
DebugPrint((3,"TapeCreatePartition: no partitions\n"));
|
|
partitionMethod = NO_PARTITIONS;
|
|
|
|
}
|
|
break;
|
|
|
|
case NO_PARTITIONS:
|
|
DebugPrint((3,"TapeCreatePartition: no partitions\n"));
|
|
partitionCount = 0;
|
|
break;
|
|
|
|
default:
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeCreatePartition: "));
|
|
DebugPrint((1,"partitionMethod -- operation not supported\n"));
|
|
return status;
|
|
}
|
|
|
|
modeSelectBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_MEDIUM_PART_PAGE));
|
|
|
|
if (!modeSelectBuffer) {
|
|
DebugPrint((1,"TapeCreatePartition: insufficient resources (modeSelectBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(modeSelectBuffer, sizeof(MODE_MEDIUM_PART_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.AllocationLength = 12;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeCreatePartition: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
modeSelectBuffer,
|
|
12,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeCreatePartition: mode sense, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
modeSelectBuffer->ParameterListHeader.ModeDataLength = 0;
|
|
modeSelectBuffer->ParameterListHeader.MediumType = 0;
|
|
modeSelectBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
|
|
|
|
modeSelectBuffer->ParameterListBlock.DensityCode = 0x7F;
|
|
|
|
modeSelectBuffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION;
|
|
modeSelectBuffer->MediumPartPage.PageLength = 10;
|
|
modeSelectBuffer->MediumPartPage.AdditionalPartitionDefined = (CHAR)partitionCount;
|
|
modeSelectBuffer->MediumPartPage.PSUMBit = 2;
|
|
modeSelectBuffer->MediumPartPage.IDPBit = SETBITON;
|
|
modeSelectBuffer->MediumPartPage.MediumFormatRecognition = 3;
|
|
if (partitionCount) {
|
|
partition = INITIATOR_PARTITIONED;
|
|
modeSelectBuffer->MediumPartPage.Partition1Size[0] =
|
|
(CHAR)((tapePartition->Size >> 8) & 0xFF);
|
|
modeSelectBuffer->MediumPartPage.Partition1Size[1] =
|
|
(CHAR)(tapePartition->Size & 0xFF);
|
|
} else {
|
|
partition = NOT_PARTITIONED;
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
|
|
cdb->MODE_SELECT.PFBit = SETBITON;
|
|
cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = 16500;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeCreatePartition: SendSrb (mode select)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
modeSelectBuffer,
|
|
sizeof(MODE_MEDIUM_PART_PAGE),
|
|
TRUE);
|
|
|
|
ExFreePool(modeSelectBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeCreatePartition: mode select, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
tapeData->CurrentPartition = partition;
|
|
|
|
if (partition != NOT_PARTITIONED) {
|
|
|
|
deviceConfigModeSenseBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
if (!deviceConfigModeSenseBuffer) {
|
|
DebugPrint((1,"TapeCreatePartition: insufficient resources (deviceConfigModeSenseBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(deviceConfigModeSenseBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeCreatePartition: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
deviceConfigModeSenseBuffer,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE),
|
|
FALSE);
|
|
|
|
ExFreePool(deviceConfigModeSenseBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeCreatePartition: mode sense, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
tapeData->CurrentPartition =
|
|
deviceConfigModeSenseBuffer->DeviceConfigPage.ActivePartition + 1;
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeCreatePartition()
|
|
|
|
|
|
NTSTATUS
|
|
TapeErase(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine "erases" tape: a "short" erase simply writes on
|
|
tape at its current position in a manner which causes an "End
|
|
of Data" condition to be indicated if/when a subsequent read
|
|
is done at, into, or over that point on tape; a "long" erase
|
|
writes an "erase" data pattern on tape at/from its current
|
|
position and on until End of Partition (End of Tape if the
|
|
tape is not partitioned).
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_ERASE tapeErase = Irp->AssociatedIrp.SystemBuffer;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeErase: Enter routine\n"));
|
|
|
|
if (tapeErase->Immediate) {
|
|
switch (tapeErase->Type) {
|
|
case TAPE_ERASE_LONG:
|
|
case TAPE_ERASE_SHORT:
|
|
DebugPrint((3,"TapeErase: immediate\n"));
|
|
break;
|
|
|
|
default:
|
|
DebugPrint((1,"TapeErase: EraseType, immediate -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
switch (tapeErase->Type) {
|
|
case TAPE_ERASE_LONG:
|
|
DebugPrint((3,"TapeErase: long\n"));
|
|
break;
|
|
|
|
case TAPE_ERASE_SHORT:
|
|
DebugPrint((3,"TapeErase: short\n"));
|
|
break;
|
|
|
|
default:
|
|
DebugPrint((1,"TapeErase: EraseType -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->ERASE.OperationCode = SCSIOP_ERASE;
|
|
cdb->ERASE.Immediate = tapeErase->Immediate;
|
|
if (tapeErase->Type == TAPE_ERASE_LONG) {
|
|
cdb->ERASE.Long = SETBITON;
|
|
} else {
|
|
cdb->ERASE.Long = SETBITOFF;
|
|
}
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
if (tapeErase->Type == TAPE_ERASE_LONG) {
|
|
srb.TimeOutValue = 16500;
|
|
} else {
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
}
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeErase: SendSrb (erase)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeErase: erase, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeErase()
|
|
|
|
|
|
VOID
|
|
TapeError(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PSCSI_REQUEST_BLOCK Srb,
|
|
NTSTATUS *Status,
|
|
BOOLEAN *Retry
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
When a request completes with error, the routine InterpretSenseInfo
|
|
is called to examine the sense data, determine whether the request
|
|
should be retried, and store an NT status in the IRP. This routine
|
|
is thence called, if the request was a tape request, to handle tape
|
|
specific errors: it may/can update the NT status and/or the retry
|
|
boolean for tape specific conditions.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
|
|
NTSTATUS status = *Status;
|
|
BOOLEAN retry = *Retry;
|
|
UCHAR adsenseq = senseBuffer->AdditionalSenseCodeQualifier;
|
|
UCHAR adsense = senseBuffer->AdditionalSenseCode;
|
|
|
|
DebugPrint((3,"TapeError: Enter routine\n"));
|
|
DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", status, retry));
|
|
|
|
if (status == STATUS_DEVICE_NOT_READY) {
|
|
if ((adsense == SCSI_ADSENSE_LUN_NOT_READY) &&
|
|
(adsenseq == SCSI_SENSEQ_BECOMING_READY) ) {
|
|
|
|
*Status = STATUS_NO_MEDIA;
|
|
*Retry = FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
if (status == STATUS_IO_DEVICE_ERROR) {
|
|
if ((senseBuffer->SenseKey & 0x0F) == SCSI_SENSE_ABORTED_COMMAND) {
|
|
|
|
*Status = STATUS_DEVICE_NOT_READY;
|
|
*Retry = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", *Status, *Retry));
|
|
|
|
return;
|
|
|
|
} // end TapeError()
|
|
|
|
|
|
NTSTATUS
|
|
TapeGetDriveParameters(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine determines and returns the "drive parameters" of the
|
|
4mm DAT drive associated with "DeviceObject": Set Mark reporting
|
|
enabled/disabled, default block size, maximum block size, minimum
|
|
block size, maximum number of partitions, device features flags,
|
|
etc. From time to time, this set of drive parameters for a given
|
|
drive is variable. It changes as drive operating characteristics
|
|
change: e.g., tape media type loaded, recording density and/or
|
|
recording mode of the media type loaded, etc.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
|
|
PMODE_DEVICE_CONFIG_PAGE deviceConfigModeSenseBuffer;
|
|
PMODE_DATA_COMPRESS_PAGE compressionModeSenseBuffer;
|
|
PREAD_BLOCK_LIMITS_DATA blockLimitsBuffer;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeGetDriveParameters: Enter routine\n"));
|
|
|
|
RtlZeroMemory(tapeGetDriveParams, sizeof(TAPE_GET_DRIVE_PARAMETERS));
|
|
Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
|
|
|
|
deviceConfigModeSenseBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
if (!deviceConfigModeSenseBuffer) {
|
|
DebugPrint((1,"TapeGetDriveParameters: insufficient resources (deviceConfigModeSenseBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(deviceConfigModeSenseBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
deviceConfigModeSenseBuffer,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE),
|
|
FALSE);
|
|
|
|
if (status == STATUS_NO_MEDIA) {
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
tapeGetDriveParams->ReportSetmarks =
|
|
(deviceConfigModeSenseBuffer->DeviceConfigPage.RSmk? 1 : 0 );
|
|
|
|
}
|
|
|
|
ExFreePool(deviceConfigModeSenseBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetDriveParameters: mode sense, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
compressionModeSenseBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_DATA_COMPRESS_PAGE));
|
|
|
|
if (!compressionModeSenseBuffer) {
|
|
DebugPrint((1,"TapeGetDriveParameters: insufficient resources (compressionModeSenseBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(compressionModeSenseBuffer, sizeof(MODE_DATA_COMPRESS_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
compressionModeSenseBuffer,
|
|
sizeof(MODE_DATA_COMPRESS_PAGE),
|
|
FALSE);
|
|
|
|
if (status == STATUS_NO_MEDIA) {
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if (compressionModeSenseBuffer->DataCompressPage.DCC) {
|
|
|
|
tapeGetDriveParams->FeaturesLow |= TAPE_DRIVE_COMPRESSION;
|
|
tapeGetDriveParams->FeaturesHigh |= TAPE_DRIVE_SET_COMPRESSION;
|
|
tapeGetDriveParams->Compression =
|
|
(compressionModeSenseBuffer->DataCompressPage.DCE? TRUE : FALSE);
|
|
|
|
if (!compressionModeSenseBuffer->DataCompressPage.DDE) {
|
|
|
|
compressionModeSenseBuffer->ParameterListHeader.ModeDataLength = 0;
|
|
compressionModeSenseBuffer->ParameterListHeader.MediumType = 0;
|
|
compressionModeSenseBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
|
|
|
|
compressionModeSenseBuffer->ParameterListBlock.DensityCode = 0x7F;
|
|
|
|
compressionModeSenseBuffer->DataCompressPage.DDE = SETBITON;
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
|
|
cdb->MODE_SELECT.PFBit = SETBITON;
|
|
cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DATA_COMPRESS_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode select)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
compressionModeSenseBuffer,
|
|
sizeof(MODE_DATA_COMPRESS_PAGE),
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetDriveParameters: mode select, SendSrb unsuccessful\n"));
|
|
ExFreePool(compressionModeSenseBuffer);
|
|
return status;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExFreePool(compressionModeSenseBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetDriveParameters: mode sense, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
blockLimitsBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(READ_BLOCK_LIMITS_DATA));
|
|
|
|
if (!blockLimitsBuffer) {
|
|
DebugPrint((1,"TapeGetDriveParameters: insufficient resources (blockLimitsBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(blockLimitsBuffer, sizeof(READ_BLOCK_LIMITS_DATA));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetDriveParameters: SendSrb (read block limits)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
blockLimitsBuffer,
|
|
sizeof(READ_BLOCK_LIMITS_DATA),
|
|
FALSE);
|
|
|
|
if (status == STATUS_NO_MEDIA) {
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
tapeGetDriveParams->MaximumBlockSize = blockLimitsBuffer->BlockMaximumSize[2];
|
|
tapeGetDriveParams->MaximumBlockSize += (blockLimitsBuffer->BlockMaximumSize[1] << 8);
|
|
tapeGetDriveParams->MaximumBlockSize += (blockLimitsBuffer->BlockMaximumSize[0] << 16);
|
|
|
|
tapeGetDriveParams->MinimumBlockSize = blockLimitsBuffer->BlockMinimumSize[1];
|
|
tapeGetDriveParams->MinimumBlockSize += (blockLimitsBuffer->BlockMinimumSize[0] << 8);
|
|
|
|
}
|
|
|
|
ExFreePool(blockLimitsBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetDriveParameters: read block limits, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
tapeGetDriveParams->DefaultBlockSize = 0x200;
|
|
tapeGetDriveParams->MaximumPartitionCount = 2;
|
|
|
|
tapeGetDriveParams->FeaturesLow |=
|
|
TAPE_DRIVE_INITIATOR |
|
|
TAPE_DRIVE_ERASE_SHORT |
|
|
TAPE_DRIVE_ERASE_LONG |
|
|
TAPE_DRIVE_ERASE_IMMEDIATE |
|
|
TAPE_DRIVE_TAPE_CAPACITY |
|
|
TAPE_DRIVE_FIXED_BLOCK |
|
|
TAPE_DRIVE_VARIABLE_BLOCK |
|
|
TAPE_DRIVE_WRITE_PROTECT |
|
|
TAPE_DRIVE_REPORT_SMKS |
|
|
TAPE_DRIVE_GET_ABSOLUTE_BLK |
|
|
TAPE_DRIVE_GET_LOGICAL_BLK;
|
|
|
|
tapeGetDriveParams->FeaturesHigh |=
|
|
TAPE_DRIVE_LOAD_UNLOAD |
|
|
TAPE_DRIVE_TENSION |
|
|
TAPE_DRIVE_LOCK_UNLOCK |
|
|
TAPE_DRIVE_REWIND_IMMEDIATE |
|
|
TAPE_DRIVE_SET_BLOCK_SIZE |
|
|
TAPE_DRIVE_LOAD_UNLD_IMMED |
|
|
TAPE_DRIVE_TENSION_IMMED |
|
|
TAPE_DRIVE_SET_REPORT_SMKS |
|
|
TAPE_DRIVE_ABSOLUTE_BLK |
|
|
TAPE_DRIVE_ABS_BLK_IMMED |
|
|
TAPE_DRIVE_LOGICAL_BLK |
|
|
TAPE_DRIVE_LOG_BLK_IMMED |
|
|
TAPE_DRIVE_END_OF_DATA |
|
|
TAPE_DRIVE_RELATIVE_BLKS |
|
|
TAPE_DRIVE_FILEMARKS |
|
|
TAPE_DRIVE_SEQUENTIAL_FMKS |
|
|
TAPE_DRIVE_SETMARKS |
|
|
TAPE_DRIVE_SEQUENTIAL_SMKS |
|
|
TAPE_DRIVE_REVERSE_POSITION |
|
|
TAPE_DRIVE_WRITE_SETMARKS |
|
|
TAPE_DRIVE_WRITE_FILEMARKS |
|
|
TAPE_DRIVE_WRITE_MARK_IMMED;
|
|
|
|
tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
|
|
|
|
DebugPrint((3,"TapeGetDriveParameters: FeaturesLow == 0x%.8X\n",
|
|
tapeGetDriveParams->FeaturesLow));
|
|
DebugPrint((3,"TapeGetDriveParameters: FeaturesHigh == 0x%.8X\n",
|
|
tapeGetDriveParams->FeaturesHigh));
|
|
|
|
return status;
|
|
|
|
} // end TapeGetDriveParameters()
|
|
|
|
|
|
NTSTATUS
|
|
TapeGetMediaParameters(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine determines and returns the "media parameters" of a
|
|
tape in the 4mm DAT drive associated with "DeviceObject": maximum
|
|
tape capacity, remaining tape capacity, block size, number of
|
|
partitions, write protect indicator, etc. Tape media must be
|
|
present (loaded) in the drive for this function to return "no
|
|
error".
|
|
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
|
|
PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
|
|
PMODE_DEVICE_CONFIG_PAGE deviceConfigModeSenseBuffer;
|
|
PMODE_TAPE_MEDIA_INFORMATION modeSenseBuffer;
|
|
LARGE_INTEGER remaining;
|
|
LARGE_INTEGER capacity;
|
|
ULONG partitionCount;
|
|
ULONG partition;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeGetMediaParameters: Enter routine\n"));
|
|
|
|
RtlZeroMemory(tapeGetMediaParams, sizeof(TAPE_GET_MEDIA_PARAMETERS));
|
|
Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetMediaParameters: SendSrb (test unit ready)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
deviceConfigModeSenseBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
if (!deviceConfigModeSenseBuffer) {
|
|
DebugPrint((1,"TapeGetMediaParameters: insufficient resources (deviceConfigModeSenseBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(deviceConfigModeSenseBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
deviceConfigModeSenseBuffer,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE),
|
|
FALSE);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
partition = deviceConfigModeSenseBuffer->DeviceConfigPage.ActivePartition;
|
|
|
|
}
|
|
|
|
ExFreePool(deviceConfigModeSenseBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetMediaParameters: mode sense, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
modeSenseBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_TAPE_MEDIA_INFORMATION));
|
|
|
|
if (!modeSenseBuffer) {
|
|
DebugPrint((1,"TapeGetMediaParameters: insufficient resources (modeSenseBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(modeSenseBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
modeSenseBuffer,
|
|
sizeof(MODE_TAPE_MEDIA_INFORMATION),
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetMediaParameters: mode sense, SendSrb unsuccessful\n"));
|
|
ExFreePool(modeSenseBuffer);
|
|
return status;
|
|
}
|
|
|
|
tapeGetMediaParams->BlockSize = modeSenseBuffer->ParameterListBlock.BlockLength[2];
|
|
tapeGetMediaParams->BlockSize += modeSenseBuffer->ParameterListBlock.BlockLength[1] << 8;
|
|
tapeGetMediaParams->BlockSize += modeSenseBuffer->ParameterListBlock.BlockLength[0] << 16;
|
|
|
|
partitionCount = modeSenseBuffer->MediumPartPage.AdditionalPartitionDefined;
|
|
tapeGetMediaParams->PartitionCount = partitionCount + 1;
|
|
|
|
tapeGetMediaParams->WriteProtected =
|
|
((modeSenseBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & 0x01);
|
|
|
|
if (partition) {
|
|
|
|
capacity.LowPart =
|
|
modeSenseBuffer->MediumPartPage.Partition1Size[1];
|
|
capacity.LowPart +=
|
|
modeSenseBuffer->MediumPartPage.Partition1Size[0] << 8;
|
|
capacity.HighPart = 0;
|
|
|
|
} else {
|
|
|
|
capacity.LowPart =
|
|
modeSenseBuffer->MediumPartPage.Partition0Size[1];
|
|
capacity.LowPart +=
|
|
modeSenseBuffer->MediumPartPage.Partition0Size[0] << 8;
|
|
capacity.HighPart = 0;
|
|
|
|
}
|
|
capacity.QuadPart *= 1048576;
|
|
remaining.HighPart = 0;
|
|
remaining.LowPart = 0;
|
|
|
|
tapeGetMediaParams->Remaining = remaining;
|
|
tapeGetMediaParams->Capacity = capacity;
|
|
|
|
tapeData->CurrentPartition = partitionCount? partition + 1 : NOT_PARTITIONED;
|
|
|
|
ExFreePool(modeSenseBuffer);
|
|
|
|
return status;
|
|
|
|
} // end TapeGetMediaParameters()
|
|
|
|
|
|
NTSTATUS
|
|
TapeGetPosition(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine returns the current position of the tape.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_GET_POSITION tapeGetPosition = Irp->AssociatedIrp.SystemBuffer;
|
|
PTAPE_POSITION_DATA positionBuffer;
|
|
ULONG type;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeGetPosition: Enter routine\n"));
|
|
|
|
type = tapeGetPosition->Type;
|
|
RtlZeroMemory(tapeGetPosition, sizeof(TAPE_GET_POSITION));
|
|
Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
|
|
tapeGetPosition->Type = type;
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetPosition: SendSrb (test unit ready)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetPosition: test unit ready, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
switch (tapeGetPosition->Type) {
|
|
case TAPE_ABSOLUTE_POSITION:
|
|
DebugPrint((3,"TapeGetPosition: absolute logical\n"));
|
|
break;
|
|
|
|
case TAPE_LOGICAL_POSITION:
|
|
DebugPrint((3,"TapeGetPosition: logical\n"));
|
|
break;
|
|
|
|
default:
|
|
DebugPrint((1,"TapeGetPosition: PositionType -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
positionBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(TAPE_POSITION_DATA));
|
|
|
|
if (!positionBuffer) {
|
|
DebugPrint((1,"TapeGetPosition: insufficient resources (positionBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(positionBuffer, sizeof(TAPE_POSITION_DATA));
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB10GENERIC_LENGTH;
|
|
|
|
cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetPosition: SendSrb (read position)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
positionBuffer,
|
|
sizeof(TAPE_POSITION_DATA),
|
|
FALSE);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if (positionBuffer->BlockPositionUnsupported) {
|
|
DebugPrint((1,"TapeGetPosition: read position -- block position unsupported\n"));
|
|
ExFreePool(positionBuffer);
|
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
if (tapeGetPosition->Type == TAPE_LOGICAL_POSITION) {
|
|
tapeGetPosition->Partition = positionBuffer->PartitionNumber + 1;
|
|
}
|
|
|
|
tapeGetPosition->Offset.HighPart = 0;
|
|
REVERSE_BYTES((PFOUR_BYTE)&tapeGetPosition->Offset.LowPart,
|
|
(PFOUR_BYTE)positionBuffer->FirstBlock);
|
|
|
|
}
|
|
|
|
ExFreePool(positionBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetPosition: read position, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeGetPosition()
|
|
|
|
|
|
NTSTATUS
|
|
TapeGetStatus(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine returns the status of the device.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeGetStatus: Enter routine\n"));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeGetStatus: SendSrb (test unit ready)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeGetStatus: test unit ready, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeGetStatus()
|
|
|
|
|
|
NTSTATUS
|
|
TapePrepare(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine loads, unloads, tensions, locks, or unlocks the tape.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_PREPARE tapePrepare = Irp->AssociatedIrp.SystemBuffer;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapePrepare: Enter routine\n"));
|
|
|
|
switch (tapePrepare->Operation) {
|
|
case TAPE_LOAD:
|
|
DebugPrint((3,"TapePrepare: load\n"));
|
|
break;
|
|
|
|
case TAPE_UNLOAD:
|
|
DebugPrint((3,"TapePrepare: unload\n"));
|
|
break;
|
|
|
|
case TAPE_LOCK:
|
|
DebugPrint((3,"TapePrepare: lock\n"));
|
|
break;
|
|
|
|
case TAPE_UNLOCK:
|
|
DebugPrint((3,"TapePrepare: unlock\n"));
|
|
break;
|
|
|
|
case TAPE_TENSION:
|
|
DebugPrint((3,"TapePrepare: tension\n"));
|
|
break;
|
|
|
|
default:
|
|
DebugPrint((1,"TapePrepare: Operation -- not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
if (tapePrepare->Immediate) {
|
|
switch (tapePrepare->Operation) {
|
|
case TAPE_LOAD:
|
|
case TAPE_UNLOAD:
|
|
case TAPE_TENSION:
|
|
DebugPrint((3,"TapePrepare: immediate\n"));
|
|
break;
|
|
|
|
case TAPE_LOCK:
|
|
case TAPE_UNLOCK:
|
|
default:
|
|
DebugPrint((1,"TapePrepare: Operation, immediate -- not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
|
|
|
|
switch (tapePrepare->Operation) {
|
|
case TAPE_LOAD:
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
|
|
cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
|
|
srb.TimeOutValue = 390;
|
|
break;
|
|
|
|
case TAPE_UNLOAD:
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
|
|
srb.TimeOutValue = 390;
|
|
break;
|
|
|
|
case TAPE_TENSION:
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
|
|
cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x03;
|
|
srb.TimeOutValue = 390;
|
|
break;
|
|
|
|
case TAPE_LOCK:
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
|
cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
|
|
srb.TimeOutValue = 180;
|
|
break;
|
|
|
|
case TAPE_UNLOCK:
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
|
srb.TimeOutValue = 180;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapePrepare: SendSrb (Operation)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapePrepare: Operation, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapePrepare()
|
|
|
|
|
|
NTSTATUS
|
|
TapeReadWrite(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine builds SRBs and CDBs for read and write requests
|
|
to 4MM DAT drive devices.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
Returns STATUS_PENDING.
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
|
|
PSCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb;
|
|
ULONG transferBlocks;
|
|
LARGE_INTEGER startingOffset =
|
|
currentIrpStack->Parameters.Read.ByteOffset;
|
|
|
|
DebugPrint((3,"TapeReadWrite: Enter routine\n"));
|
|
|
|
//
|
|
// Allocate an Srb.
|
|
//
|
|
|
|
if (deviceExtension->SrbZone != NULL &&
|
|
(srb = ExInterlockedAllocateFromZone(
|
|
deviceExtension->SrbZone,
|
|
deviceExtension->SrbZoneSpinLock)) != NULL) {
|
|
|
|
srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Allocate Srb from non-paged pool.
|
|
// This call must succeed.
|
|
//
|
|
|
|
srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
|
|
|
|
srb->SrbFlags = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// Write length to SRB.
|
|
//
|
|
|
|
srb->Length = SCSI_REQUEST_BLOCK_SIZE;
|
|
|
|
//
|
|
// Set up IRP Address.
|
|
//
|
|
|
|
srb->OriginalRequest = Irp;
|
|
|
|
//
|
|
// Set up target id and logical unit number.
|
|
//
|
|
|
|
srb->PathId = deviceExtension->PathId;
|
|
srb->TargetId = deviceExtension->TargetId;
|
|
srb->Lun = deviceExtension->Lun;
|
|
|
|
|
|
srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
|
|
|
|
srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
|
|
|
//
|
|
// Save byte count of transfer in SRB Extension.
|
|
//
|
|
|
|
srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
|
|
|
|
//
|
|
// Indicate auto request sense by specifying buffer and size.
|
|
//
|
|
|
|
srb->SenseInfoBuffer = deviceExtension->SenseData;
|
|
|
|
srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
|
|
|
|
//
|
|
// Initialize the queue actions field.
|
|
//
|
|
|
|
srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
|
|
|
//
|
|
// Indicate auto request sense by specifying buffer and size.
|
|
//
|
|
|
|
srb->SenseInfoBuffer = deviceExtension->SenseData;
|
|
|
|
srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
|
|
|
|
//
|
|
// Set timeout value in seconds.
|
|
//
|
|
|
|
srb->TimeOutValue = 900;
|
|
|
|
//
|
|
// Zero statuses.
|
|
//
|
|
|
|
srb->SrbStatus = srb->ScsiStatus = 0;
|
|
|
|
srb->NextSrb = 0;
|
|
|
|
//
|
|
// Indicate that 6-byte CDB's will be used.
|
|
//
|
|
|
|
srb->CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
//
|
|
// Fill in CDB fields.
|
|
//
|
|
|
|
cdb = (PCDB)srb->Cdb;
|
|
|
|
//
|
|
// Zero CDB in SRB.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
if (deviceExtension->DiskGeometry->BytesPerSector) {
|
|
|
|
//
|
|
// Since we are writing fixed block mode, normalize transfer count
|
|
// to number of blocks.
|
|
//
|
|
|
|
transferBlocks =
|
|
currentIrpStack->Parameters.Read.Length /
|
|
deviceExtension->DiskGeometry->BytesPerSector;
|
|
|
|
//
|
|
// Tell the device that we are in fixed block mode.
|
|
//
|
|
|
|
cdb->CDB6READWRITETAPE.VendorSpecific = 1;
|
|
} else {
|
|
|
|
//
|
|
// Variable block mode transfer.
|
|
//
|
|
|
|
transferBlocks = currentIrpStack->Parameters.Read.Length;
|
|
cdb->CDB6READWRITETAPE.VendorSpecific = 0;
|
|
}
|
|
|
|
//
|
|
// Set up transfer length
|
|
//
|
|
|
|
cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
|
|
cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff);
|
|
cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
|
|
|
|
//
|
|
// Set transfer direction flag and Cdb command.
|
|
//
|
|
|
|
if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
|
|
|
|
DebugPrint((3, "TapeRequest: Read Command\n"));
|
|
|
|
srb->SrbFlags = SRB_FLAGS_DATA_IN;
|
|
cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
|
|
|
|
} else {
|
|
|
|
DebugPrint((3, "TapeRequest: Write Command\n"));
|
|
|
|
srb->SrbFlags = SRB_FLAGS_DATA_OUT;
|
|
cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
|
|
}
|
|
|
|
//
|
|
// Or in the default flags from the device object.
|
|
//
|
|
|
|
srb->SrbFlags |= deviceExtension->SrbFlags;
|
|
|
|
//
|
|
// Set up major SCSI function.
|
|
//
|
|
|
|
nextIrpStack->MajorFunction = IRP_MJ_SCSI;
|
|
|
|
//
|
|
// Save SRB address in next stack for port driver.
|
|
//
|
|
|
|
nextIrpStack->Parameters.Scsi.Srb = srb;
|
|
|
|
//
|
|
// Save retry count in current IRP stack.
|
|
//
|
|
|
|
currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
|
|
|
|
//
|
|
// Set up IoCompletion routine address.
|
|
//
|
|
|
|
IoSetCompletionRoutine(Irp,
|
|
ScsiClassIoComplete,
|
|
srb,
|
|
TRUE,
|
|
TRUE,
|
|
FALSE);
|
|
|
|
return STATUS_PENDING;
|
|
|
|
} // end TapeReadWrite()
|
|
|
|
|
|
NTSTATUS
|
|
TapeSetDriveParameters(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine "sets" the "drive parameters" of the 4mm DAT drive
|
|
associated with "DeviceObject": Set Mark reporting enable/disable,
|
|
compression enable/disable, etc.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_SET_DRIVE_PARAMETERS tapeSetDriveParams = Irp->AssociatedIrp.SystemBuffer;
|
|
PMODE_DATA_COMPRESS_PAGE compressionBuffer;
|
|
PMODE_DEVICE_CONFIG_PAGE configBuffer;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeSetDriveParameters: Enter routine\n"));
|
|
|
|
configBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
if (!configBuffer) {
|
|
DebugPrint((1,"TapeSetDriveParameters: insufficient resources (configBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(configBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
configBuffer,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE),
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
if (status == STATUS_NO_MEDIA) {
|
|
|
|
ExFreePool(configBuffer);
|
|
|
|
} else {
|
|
|
|
DebugPrint((1,"TapeSetDriveParameters: mode sense, SendSrb unsuccessful\n"));
|
|
ExFreePool(configBuffer);
|
|
return status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
configBuffer->ParameterListHeader.ModeDataLength = 0;
|
|
configBuffer->ParameterListHeader.MediumType = 0;
|
|
configBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
|
|
|
|
configBuffer->ParameterListBlock.DensityCode = 0x7F;
|
|
|
|
configBuffer->DeviceConfigPage.PageCode = MODE_PAGE_DEVICE_CONFIG;
|
|
configBuffer->DeviceConfigPage.PageLength = 0x0E;
|
|
|
|
if (tapeSetDriveParams->ReportSetmarks) {
|
|
configBuffer->DeviceConfigPage.RSmk = SETBITON;
|
|
} else {
|
|
configBuffer->DeviceConfigPage.RSmk = SETBITOFF;
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
|
|
cdb->MODE_SELECT.PFBit = SETBITON;
|
|
cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeSetDriveParameters: SendSrb (mode select)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
configBuffer,
|
|
sizeof(MODE_DEVICE_CONFIG_PAGE),
|
|
TRUE);
|
|
|
|
ExFreePool(configBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeSetDriveParameters: mode select, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
}
|
|
|
|
compressionBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_DATA_COMPRESS_PAGE));
|
|
|
|
if (!compressionBuffer) {
|
|
DebugPrint((1,"TapeSetDriveParameters: insufficient resources (compressionBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(compressionBuffer, sizeof(MODE_DATA_COMPRESS_PAGE));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
|
cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS;
|
|
cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeSetDriveParameters: SendSrb (mode sense)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
compressionBuffer,
|
|
sizeof(MODE_DATA_COMPRESS_PAGE),
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeSetDriveParameters: mode sense, SendSrb unsuccessful\n"));
|
|
ExFreePool(compressionBuffer);
|
|
return status;
|
|
}
|
|
|
|
if (NT_SUCCESS(status) && compressionBuffer->DataCompressPage.DCC) {
|
|
|
|
compressionBuffer->ParameterListHeader.ModeDataLength = 0;
|
|
compressionBuffer->ParameterListHeader.MediumType = 0;
|
|
compressionBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
|
|
|
|
compressionBuffer->ParameterListBlock.DensityCode = 0x7F;
|
|
|
|
compressionBuffer->DataCompressPage.PageCode = MODE_PAGE_DATA_COMPRESS;
|
|
compressionBuffer->DataCompressPage.PageLength = 0x0E;
|
|
|
|
if (tapeSetDriveParams->Compression) {
|
|
compressionBuffer->DataCompressPage.DCE = SETBITON;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[0] = 0;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[1] = 0;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[2] = 0;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[3] = 0x20;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[0] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[1] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[2] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[3] = 0;
|
|
} else {
|
|
compressionBuffer->DataCompressPage.DCE = SETBITOFF;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[0] = 0;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[1] = 0;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[2] = 0;
|
|
compressionBuffer->DataCompressPage.CompressionAlgorithm[3] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[0] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[1] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[2] = 0;
|
|
compressionBuffer->DataCompressPage.DecompressionAlgorithm[3] = 0;
|
|
}
|
|
|
|
compressionBuffer->DataCompressPage.DDE = SETBITON;
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
|
|
cdb->MODE_SELECT.PFBit = SETBITON;
|
|
cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DATA_COMPRESS_PAGE);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeSetDriveParameters: SendSrb (mode select)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
compressionBuffer,
|
|
sizeof(MODE_DATA_COMPRESS_PAGE),
|
|
TRUE);
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeSetDriveParameters: mode select, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
}
|
|
|
|
ExFreePool(compressionBuffer);
|
|
|
|
return status;
|
|
|
|
} // end TapeSetDriveParameters()
|
|
|
|
|
|
NTSTATUS
|
|
TapeSetMediaParameters(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine "sets" the "media parameters" of a tape in the 4mm
|
|
DAT drive associated with "DeviceObject": the block size. Tape media
|
|
must be present (loaded) in the drive for this function to return
|
|
"no error".
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
|
|
PMODE_PARM_READ_WRITE_DATA modeBuffer;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeSetMediaParameters: Enter routine\n"));
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeSetMediaParameters: SendSrb (test unit ready)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeSetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
|
|
return status;
|
|
}
|
|
|
|
modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
|
|
sizeof(MODE_PARM_READ_WRITE_DATA));
|
|
|
|
if (!modeBuffer) {
|
|
DebugPrint((1,"TapeSetMediaParameters: insufficient resources (modeBuffer)\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(modeBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
|
|
|
|
modeBuffer->ParameterListHeader.ModeDataLength = 0;
|
|
modeBuffer->ParameterListHeader.MediumType = 0;
|
|
modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
|
|
modeBuffer->ParameterListHeader.BlockDescriptorLength =
|
|
MODE_BLOCK_DESC_LENGTH;
|
|
|
|
modeBuffer->ParameterListBlock.DensityCode = 0x7F;
|
|
modeBuffer->ParameterListBlock.BlockLength[0] =
|
|
(UCHAR)((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
|
|
modeBuffer->ParameterListBlock.BlockLength[1] =
|
|
(UCHAR)((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
|
|
modeBuffer->ParameterListBlock.BlockLength[2] =
|
|
(UCHAR)(tapeSetMediaParams->BlockSize & 0xFF);
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
|
|
cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = deviceExtension->TimeOutValue;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeSetMediaParameters: SendSrb (mode select)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
modeBuffer,
|
|
sizeof(MODE_PARM_READ_WRITE_DATA),
|
|
TRUE);
|
|
|
|
ExFreePool(modeBuffer);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeSetMediaParameters: mode select, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeSetMediaParameters()
|
|
|
|
|
|
NTSTATUS
|
|
TapeSetPosition(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine sets the position of the tape.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1);
|
|
PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
|
|
ULONG partition = 0;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeSetPosition: Enter routine\n"));
|
|
|
|
if (tapeSetPosition->Immediate) {
|
|
switch (tapeSetPosition->Method) {
|
|
case TAPE_REWIND:
|
|
case TAPE_ABSOLUTE_BLOCK:
|
|
case TAPE_LOGICAL_BLOCK:
|
|
DebugPrint((3,"TapeSetPosition: immediate\n"));
|
|
break;
|
|
|
|
case TAPE_SPACE_END_OF_DATA:
|
|
case TAPE_SPACE_RELATIVE_BLOCKS:
|
|
case TAPE_SPACE_FILEMARKS:
|
|
case TAPE_SPACE_SEQUENTIAL_FMKS:
|
|
case TAPE_SPACE_SETMARKS:
|
|
case TAPE_SPACE_SEQUENTIAL_SMKS:
|
|
default:
|
|
DebugPrint((1,"TapeSetPosition: PositionMethod, immediate -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
|
|
|
|
switch (tapeSetPosition->Method) {
|
|
case TAPE_REWIND:
|
|
DebugPrint((3,"TapeSetPosition: method == rewind\n"));
|
|
cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
|
|
srb.TimeOutValue = 360;
|
|
break;
|
|
|
|
case TAPE_ABSOLUTE_BLOCK:
|
|
DebugPrint((3,"TapeSetPosition: method == locate (absolute logical)\n"));
|
|
srb.CdbLength = CDB10GENERIC_LENGTH;
|
|
cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
|
|
cdb->LOCATE.LogicalBlockAddress[0] =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 24) & 0xFF);
|
|
cdb->LOCATE.LogicalBlockAddress[1] =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->LOCATE.LogicalBlockAddress[2] =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->LOCATE.LogicalBlockAddress[3] =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_LOGICAL_BLOCK:
|
|
DebugPrint((3,"TapeSetPosition: method == locate (logical)\n"));
|
|
srb.CdbLength = CDB10GENERIC_LENGTH;
|
|
cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
|
|
cdb->LOCATE.LogicalBlockAddress[0] =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 24) & 0xFF);
|
|
cdb->LOCATE.LogicalBlockAddress[1] =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->LOCATE.LogicalBlockAddress[2] =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->LOCATE.LogicalBlockAddress[3] =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
if ((tapeSetPosition->Partition != 0) &&
|
|
(tapeData->CurrentPartition != NOT_PARTITIONED) &&
|
|
(tapeSetPosition->Partition != tapeData->CurrentPartition)) {
|
|
partition = tapeSetPosition->Partition;
|
|
cdb->LOCATE.Partition = (UCHAR)(partition- 1);
|
|
cdb->LOCATE.CPBit = SETBITON;
|
|
} else {
|
|
partition = tapeData->CurrentPartition;
|
|
}
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_SPACE_END_OF_DATA:
|
|
DebugPrint((3,"TapeSetPosition: method == space to end-of-data\n"));
|
|
cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
|
|
cdb->SPACE_TAPE_MARKS.Code = 3;
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_SPACE_RELATIVE_BLOCKS:
|
|
DebugPrint((3,"TapeSetPosition: method == space blocks\n"));
|
|
cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
|
|
cdb->SPACE_TAPE_MARKS.Code = 0;
|
|
cdb->SPACE_TAPE_MARKS.NumMarksMSB =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarks =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarksLSB =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_SPACE_FILEMARKS:
|
|
DebugPrint((3,"TapeSetPosition: method == space filemarks\n"));
|
|
cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
|
|
cdb->SPACE_TAPE_MARKS.Code = 1;
|
|
cdb->SPACE_TAPE_MARKS.NumMarksMSB =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarks =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarksLSB =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_SPACE_SEQUENTIAL_FMKS:
|
|
DebugPrint((3,"TapeSetPosition: method == space sequential filemarks\n"));
|
|
cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
|
|
cdb->SPACE_TAPE_MARKS.Code = 2;
|
|
cdb->SPACE_TAPE_MARKS.NumMarksMSB =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarks =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarksLSB =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_SPACE_SETMARKS:
|
|
DebugPrint((3,"TapeSetPosition: method == space setmarks\n"));
|
|
cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
|
|
cdb->SPACE_TAPE_MARKS.Code = 4;
|
|
cdb->SPACE_TAPE_MARKS.NumMarksMSB =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarks =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarksLSB =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
case TAPE_SPACE_SEQUENTIAL_SMKS:
|
|
DebugPrint((3,"TapeSetPosition: method == space sequential setmarks\n"));
|
|
cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
|
|
cdb->SPACE_TAPE_MARKS.Code = 5;
|
|
cdb->SPACE_TAPE_MARKS.NumMarksMSB =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarks =
|
|
(UCHAR)((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
|
|
cdb->SPACE_TAPE_MARKS.NumMarksLSB =
|
|
(UCHAR)(tapeSetPosition->Offset.LowPart & 0xFF);
|
|
srb.TimeOutValue = 480;
|
|
break;
|
|
|
|
default:
|
|
DebugPrint((1,"TapeSetPosition: PositionMethod -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeSetPosition: SendSrb (method)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if (tapeSetPosition->Method == TAPE_LOGICAL_BLOCK) {
|
|
tapeData->CurrentPartition = partition;
|
|
}
|
|
|
|
} else {
|
|
|
|
DebugPrint((1,"TapeSetPosition: method, SendSrb unsuccessful\n"));
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeSetPosition()
|
|
|
|
|
|
BOOLEAN
|
|
TapeVerifyInquiry(
|
|
IN PSCSI_INQUIRY_DATA LunInfo
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine determines if this driver should claim this drive.
|
|
|
|
Arguments:
|
|
|
|
LunInfo
|
|
|
|
Return Value:
|
|
|
|
TRUE - driver should claim this drive.
|
|
FALSE - driver should not claim this drive.
|
|
|
|
--*/
|
|
|
|
{
|
|
PINQUIRYDATA inquiryData;
|
|
|
|
DebugPrint((3,"TapeVerifyInquiry: Enter routine\n"));
|
|
|
|
inquiryData = (PVOID)LunInfo->InquiryData;
|
|
|
|
//
|
|
// Determine, from the Product ID field in the
|
|
// inquiry data, whether or not to "claim" this drive.
|
|
//
|
|
|
|
return WhichIsIt(inquiryData)? TRUE : FALSE;
|
|
|
|
} // end TapeVerifyInquiry()
|
|
|
|
|
|
NTSTATUS
|
|
TapeWriteMarks(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine writes tapemarks on the tape.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject
|
|
Irp
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
|
PTAPE_WRITE_MARKS tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
|
|
SCSI_REQUEST_BLOCK srb;
|
|
PCDB cdb = (PCDB)srb.Cdb;
|
|
NTSTATUS status;
|
|
|
|
DebugPrint((3,"TapeWriteMarks: Enter routine\n"));
|
|
|
|
if (tapeWriteMarks->Immediate) {
|
|
switch (tapeWriteMarks->Type) {
|
|
case TAPE_SETMARKS:
|
|
case TAPE_FILEMARKS:
|
|
DebugPrint((3,"TapeWriteMarks: immediate\n"));
|
|
break;
|
|
|
|
case TAPE_SHORT_FILEMARKS:
|
|
case TAPE_LONG_FILEMARKS:
|
|
default:
|
|
DebugPrint((1,"TapeWriteMarks: TapemarkType, immediate -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Zero CDB in SRB on stack.
|
|
//
|
|
|
|
RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
|
|
|
|
//
|
|
// Prepare SCSI command (CDB)
|
|
//
|
|
|
|
srb.CdbLength = CDB6GENERIC_LENGTH;
|
|
|
|
cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
|
|
cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate;
|
|
|
|
switch (tapeWriteMarks->Type) {
|
|
case TAPE_SETMARKS:
|
|
DebugPrint((3,"TapeWriteMarks: TapemarkType == setmarks\n"));
|
|
cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON;
|
|
break;
|
|
|
|
case TAPE_FILEMARKS:
|
|
DebugPrint((3,"TapeWriteMarks: TapemarkType == filemarks\n"));
|
|
break;
|
|
|
|
case TAPE_SHORT_FILEMARKS:
|
|
case TAPE_LONG_FILEMARKS:
|
|
default:
|
|
DebugPrint((1,"TapeWriteMarks: TapemarkType -- operation not supported\n"));
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
cdb->WRITE_TAPE_MARKS.TransferLength[0] =
|
|
(UCHAR)((tapeWriteMarks->Count >> 16) & 0xFF);
|
|
cdb->WRITE_TAPE_MARKS.TransferLength[1] =
|
|
(UCHAR)((tapeWriteMarks->Count >> 8) & 0xFF);
|
|
cdb->WRITE_TAPE_MARKS.TransferLength[2] =
|
|
(UCHAR)(tapeWriteMarks->Count & 0xFF);
|
|
|
|
//
|
|
// Set timeout value.
|
|
//
|
|
|
|
srb.TimeOutValue = 360;
|
|
|
|
//
|
|
// Send SCSI command (CDB) to device
|
|
//
|
|
|
|
DebugPrint((3,"TapeWriteMarks: SendSrb (TapemarkType)\n"));
|
|
|
|
status = ScsiClassSendSrbSynchronous(DeviceObject,
|
|
&srb,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DebugPrint((1,"TapeWriteMarks: TapemarkType, SendSrb unsuccessful\n"));
|
|
}
|
|
|
|
return status;
|
|
|
|
} // end TapeWriteMarks()
|
|
|
|
|
|
static
|
|
ULONG
|
|
WhichIsIt(
|
|
IN PINQUIRYDATA InquiryData
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine determines a drive's identity from the Product ID field
|
|
in its inquiry data.
|
|
|
|
Arguments:
|
|
|
|
InquiryData (from an Inquiry command)
|
|
|
|
Return Value:
|
|
|
|
driveID
|
|
|
|
--*/
|
|
|
|
{
|
|
if (RtlCompareMemory(InquiryData->VendorId,"SONY ",8) == 8) {
|
|
|
|
if (RtlCompareMemory(InquiryData->ProductId,"SDT-2000",8) == 8) {
|
|
return SONY_SDT2000;
|
|
}
|
|
|
|
if (RtlCompareMemory(InquiryData->ProductId,"SDT-4000",8) == 8) {
|
|
return SONY_SDT4000;
|
|
}
|
|
|
|
if (RtlCompareMemory(InquiryData->ProductId,"SDT-5000",8) == 8) {
|
|
return SONY_SDT5000;
|
|
}
|
|
|
|
if (RtlCompareMemory(InquiryData->ProductId,"SDT-5200",8) == 8) {
|
|
return SONY_SDT5200;
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|