⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tape.c

📁 This sample is a working example of Exabyte2 Tape Minidriver. This module contains device-specific r
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -