📄 tape.c
字号:
fdoExtension = deviceObject->DeviceExtension;
//
// Back pointer to device object.
//
fdoExtension->CommonExtension.DeviceObject = deviceObject;
//
// This is the physical device.
//
fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension;
//
// Initialize lock count to zero. The lock count is used to
// disable the ejection mechanism when media is mounted.
//
fdoExtension->LockCount = 0;
//
// Save system tape number
//
fdoExtension->DeviceNumber = tapeCount - 1;
//
// Set the alignment requirements for the device based on the
// host adapter requirements
//
if (lowerDevice->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = lowerDevice->AlignmentRequirement;
}
//
// Save the device descriptors
//
fdoExtension->AdapterDescriptor = NULL;
fdoExtension->DeviceDescriptor = NULL;
//
// Attach to the PDO
//
fdoExtension->LowerPdo = PhysicalDeviceObject;
fdoExtension->CommonExtension.LowerDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {
//
// The attach failed. Cleanup and return.
//
status = STATUS_UNSUCCESSFUL;
goto CreateTapeDeviceObjectExit;
}
//
// Save the tape initialization data.
//
RtlCopyMemory(fdoExtension->CommonExtension.DriverData, TapeInitData,sizeof(TAPE_INIT_DATA_EX));
//
// Initialize the splitrequest spinlock.
//
tapeData = (PTAPE_DATA)fdoExtension->CommonExtension.DriverData;
KeInitializeSpinLock(&tapeData->SplitRequestSpinLock);
//
// Create the dos port driver name.
//
swprintf(dosNameBuffer,
L"\\DosDevices\\TAPE%d",
fdoExtension->DeviceNumber);
RtlInitUnicodeString(&dosUnicodeString, dosNameBuffer);
//
// Recreate the deviceName
//
swprintf(wideNameBuffer,
L"\\Device\\Tape%d",
fdoExtension->DeviceNumber);
RtlInitUnicodeString(&deviceUnicodeString,
wideNameBuffer);
status = IoAssignArcName(&dosUnicodeString,
&deviceUnicodeString);
if (NT_SUCCESS(status)) {
tapeData->DosNameCreated = TRUE;
} else {
tapeData->DosNameCreated = FALSE;
}
//
// The device is initialized properly - mark it as such.
//
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
ObDereferenceObject(lowerDevice);
return(STATUS_SUCCESS);
CreateTapeDeviceObjectExit:
//
// Release the device since an error occured.
//
// ClassClaimDevice(PortDeviceObject,
// LunInfo,
// TRUE,
// NULL);
ObDereferenceObject(lowerDevice);
if (deviceObject != NULL) {
IoDeleteDevice(deviceObject);
}
return status;
} // end CreateTapeDeviceObject()
NTSTATUS
TapeStartDevice(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine is called after InitDevice, and creates the symbolic link,
and sets up information in the registry.
The routine could be called multiple times, in the event of a StopDevice.
Arguments:
Fdo - a pointer to the functional device object for this device
Return Value:
status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PTAPE_DATA tapeData;
PTAPE_INIT_DATA_EX tapeInitData;
PINQUIRYDATA inquiryData;
ULONG inquiryLength;
SCSI_REQUEST_BLOCK srb;
PCDB cdb;
NTSTATUS status;
PVOID minitapeExtension;
PMODE_CAP_PAGE capPage = NULL ;
PMODE_CAPABILITIES_PAGE capabilitiesPage;
ULONG pageLength;
PAGED_CODE();
//
// Build and send request to get inquiry data.
//
inquiryData = ExAllocatePool(NonPagedPoolCacheAligned, MAXIMUM_TAPE_INQUIRY_DATA);
if (!inquiryData) {
//
// The buffer cannot be allocated.
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Get the tape init data again.
//
tapeData = (PTAPE_DATA)(fdoExtension->CommonExtension.DriverData);
tapeInitData = &tapeData->TapeInitData;
RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
//
// Set timeout value.
//
srb.TimeOutValue = 2;
srb.CdbLength = 6;
cdb = (PCDB)srb.Cdb;
//
// Set CDB operation code.
//
cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
//
// Set allocation length to inquiry data buffer size.
//
cdb->CDB6INQUIRY.AllocationLength = MAXIMUM_TAPE_INQUIRY_DATA;
status = ClassSendSrbSynchronous(Fdo,
&srb,
inquiryData,
MAXIMUM_TAPE_INQUIRY_DATA,
FALSE);
if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_SUCCESS ||
SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
srb.SrbStatus = SRB_STATUS_SUCCESS;
}
if (srb.SrbStatus == SRB_STATUS_SUCCESS) {
inquiryLength = inquiryData->AdditionalLength + FIELD_OFFSET(INQUIRYDATA, Reserved);
if (inquiryLength > srb.DataTransferLength) {
inquiryLength = srb.DataTransferLength;
}
//
// Verify that we really want this device.
//
if (tapeInitData->QueryModeCapabilitiesPage ) {
capPage = ExAllocatePool(NonPagedPoolCacheAligned,
sizeof(MODE_CAP_PAGE));
}
if (capPage) {
pageLength = ClassModeSense(Fdo,
(PCHAR) capPage,
sizeof(MODE_CAP_PAGE),
MODE_PAGE_CAPABILITIES);
if (pageLength == 0) {
pageLength = ClassModeSense(Fdo,
(PCHAR) capPage,
sizeof(MODE_CAP_PAGE),
MODE_PAGE_CAPABILITIES);
}
if (pageLength < (sizeof(MODE_CAP_PAGE) - 1)) {
ExFreePool(capPage);
capPage = NULL;
}
}
if (capPage) {
capabilitiesPage = &(capPage->CapabilitiesPage);
} else {
capabilitiesPage = NULL;
}
//
// Initialize the minitape extension.
//
if (tapeInitData->ExtensionInit) {
minitapeExtension = tapeData + 1;
tapeInitData->ExtensionInit(minitapeExtension,
inquiryData,
capabilitiesPage);
}
if (capPage) {
ExFreePool(capPage);
}
} else {
inquiryLength = 0;
}
//
// Add tape device number to registry
//
ClassUpdateInformationInRegistry(Fdo,
"Tape",
fdoExtension->DeviceNumber,
inquiryData,
inquiryLength);
ExFreePool(inquiryData);
status = IoSetDeviceInterfaceState(&(tapeData->TapeInterfaceString),
TRUE);
if(!NT_SUCCESS(status)) {
DebugPrint((1,
"TapeStartDevice: Unable to register Tape%x interface name - %x.\n",
fdoExtension->DeviceNumber,
status));
}
return STATUS_SUCCESS;
}
NTSTATUS
TapeInitDevice(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine will complete the tape miniclass initialization. This includes
allocating sense info buffers and srb s-lists.
This routine will not clean up allocate resources if it fails - that
is left for device stop/removal
Arguments:
Fdo - a pointer to the functional device object for this device
Return Value:
status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PVOID senseData = NULL;
PTAPE_DATA tapeData;
PTAPE_INIT_DATA_EX tapeInitData;
NTSTATUS status;
PVOID minitapeExtension;
STORAGE_PROPERTY_ID propertyId;
UNICODE_STRING interfaceName;
PAGED_CODE();
//
// Allocate request sense buffer.
//
senseData = ExAllocatePool(NonPagedPoolCacheAligned,
SENSE_BUFFER_SIZE);
if (senseData == NULL) {
//
// The buffer cannot be allocated.
//
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple.
//
ClassInitializeSrbLookasideList(&(fdoExtension->CommonExtension),
TAPE_SRB_LIST_SIZE);
//
// Set the sense data pointer in the device extension.
//
fdoExtension->SenseData = senseData;
fdoExtension->DiskGeometry.BytesPerSector = UNDEFINED_BLOCK_SIZE;
//
// Get the tape init data again.
//
tapeData = (PTAPE_DATA)(fdoExtension->CommonExtension.DriverData);
tapeInitData = &tapeData->TapeInitData;
//
// Set timeout value in seconds.
//
if (tapeInitData->DefaultTimeOutValue) {
fdoExtension->TimeOutValue = tapeInitData->DefaultTimeOutValue;
} else {
fdoExtension->TimeOutValue = 180;
}
//
// Used to keep track of the last time a drive clean
// notification was sent by the driver
//
tapeData->LastDriveCleanRequestTime.QuadPart = 0;
//
// SRB Timeout delta is used to increase the timeout for certain
// commands - typically, commands such as SET_POSITION, ERASE, etc.
//
tapeData->SrbTimeoutDelta = GetTimeoutDeltaFromRegistry(fdoExtension->LowerPdo);
if ((tapeData->SrbTimeoutDelta) == 0) {
tapeData->SrbTimeoutDelta = fdoExtension->TimeOutValue;
}
//
// Call port driver to get adapter capabilities.
//
propertyId = StorageAdapterProperty;
status = ClassGetDescriptor(fdoExtension->CommonExtension.LowerDeviceObject,
&propertyId,
&(fdoExtension->AdapterDescriptor));
if(!NT_SUCCESS(status)) {
DebugPrint((1,
"TapeStartDevice: Unable to get adapter descriptor. Status %x\n",
status));
ExFreePool(senseData);
return status;
}
//
// Register for media change notification
//
ClassInitializeMediaChangeDetection(fdoExtension,
"Tape");
//
// Register interfaces for this device.
//
RtlInitUnicodeString(&tapeData->TapeInterfaceString, NULL);
status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
(LPGUID) &TapeClassGuid,
NULL,
&(tapeData->TapeInterfaceString));
if(!NT_SUCCESS(status)) {
DebugPrint((1,
"TapeInitDevice: Unable to register Tape%x interface name - %x.\n",
fdoExtension->DeviceNumber,
status));
status = STATUS_SUCCESS;
}
return STATUS_SUCCESS;
} // End TapeStartDevice
NTSTATUS
TapeRemoveDevice(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Type
)
/*++
Routine Description:
This routine is responsible for releasing any resources in use by the
tape driver.
Arguments:
DeviceObject - the device object being removed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -