Esempio n. 1
0
NTSTATUS
DiskStartFdo(
    IN PDEVICE_OBJECT Fdo
    )

/*++

Routine Description:

    This routine will query the underlying device for any information necessary
    to complete initialization of the device.  This will include physical
    disk geometry, mode sense information and such.

    This routine does not perform partition enumeration - that is left to the
    re-enumeration routine

    If this routine fails it will return an error value.  It does not clean up
    any resources - that is left for the Stop/Remove routine.

Arguments:

    Fdo - a pointer to the functional device object for this device

Return Value:

    status

--*/

{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
    PDISK_DATA diskData = commonExtension->DriverData;
    STORAGE_HOTPLUG_INFO hotplugInfo = { 0 };
    DISK_CACHE_INFORMATION cacheInfo = { 0 };
    ULONG isPowerProtected = 0;
    NTSTATUS status;

    PAGED_CODE();

    //
    // Get the hotplug information, so we can turn off write cache if needed
    //
    // NOTE: Capabilities info is not good enough to determine hotplugedness
    //       as  we cannot determine device relations  information and other
    //       dependencies. Get the hotplug info instead
    //

    {
        PIRP irp;
        KEVENT event;
        IO_STATUS_BLOCK statusBlock = { 0 };

        KeInitializeEvent(&event, SynchronizationEvent, FALSE);

        irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_HOTPLUG_INFO,
                                            Fdo,
                                            NULL,
                                            0L,
                                            &hotplugInfo,
                                            sizeof(STORAGE_HOTPLUG_INFO),
                                            FALSE,
                                            &event,
                                            &statusBlock);

        if (irp != NULL) {

            // send to self -- classpnp handles this
            status = IoCallDriver(Fdo, irp);
            if (status == STATUS_PENDING) {
                KeWaitForSingleObject(&event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL);

                status = statusBlock.Status;
            }
            NT_ASSERT(NT_SUCCESS(status));
        }
    }

    //
    // Clear the DEV_WRITE_CACHE flag now  and set
    // it below only if we read that from the disk
    //
    CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
    ADJUST_FUA_FLAG(fdoExtension);

    diskData->WriteCacheOverride = DiskWriteCacheDefault;

    //
    // Look into the registry to  see if the user
    // has chosen to override the default setting
    //
    ClassGetDeviceParameter(fdoExtension,
                            DiskDeviceParameterSubkey,
                            DiskDeviceUserWriteCacheSetting,
                            (PULONG)&diskData->WriteCacheOverride);

    if (diskData->WriteCacheOverride == DiskWriteCacheDefault)
    {
        //
        // The user has not overridden the default settings
        //
        if (TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_DISABLE_WRITE_CACHE))
        {
            //
            // This flag indicates that we have faulty firmware and this
            // may cause the filesystem to refuse to mount on this media
            //
            TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to a firmware issue\n", Fdo));

            diskData->WriteCacheOverride = DiskWriteCacheDisable;
        }
        else if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
        {
            //
            // This flag indicates that the device is hotpluggable making it unsafe to enable caching
            //
            TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to hotpluggable device\n", Fdo));

            diskData->WriteCacheOverride = DiskWriteCacheDisable;
        }
        else if (hotplugInfo.MediaHotplug)
        {
            //
            // This flag indicates that the media in the device cannot be reliably locked
            //
            TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to unlockable media\n", Fdo));

            diskData->WriteCacheOverride = DiskWriteCacheDisable;
        }
        else
        {
            //
            // Even though the device does  not seem to have any obvious problems
            // we leave it to the user to modify the previous write cache setting
            //
        }
    }

    //
    // Query the disk to see if write cache is enabled
    // and  set the DEV_WRITE_CACHE flag appropriately
    //

    status = DiskGetCacheInformation(fdoExtension, &cacheInfo);

    if (NT_SUCCESS(status))
    {
        if (cacheInfo.WriteCacheEnabled == TRUE)
        {
            SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
            ADJUST_FUA_FLAG(fdoExtension);

            if (diskData->WriteCacheOverride == DiskWriteCacheDisable)
            {
                //
                // Write cache is currently enabled on this
                // device, but we would like to turn it off
                //
                cacheInfo.WriteCacheEnabled = FALSE;

                DiskSetCacheInformation(fdoExtension, &cacheInfo);
            }
        }
        else
        {
            if (diskData->WriteCacheOverride == DiskWriteCacheEnable)
            {
                //
                // Write cache is currently disabled on this
                // device, but we  would  like to turn it on
                //
                cacheInfo.WriteCacheEnabled = TRUE;

                DiskSetCacheInformation(fdoExtension, &cacheInfo);
            }
        }
    }

    //
    // Query the registry to see if this disk is power-protected or not
    //

    CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);

    ClassGetDeviceParameter(fdoExtension, DiskDeviceParameterSubkey, DiskDeviceCacheIsPowerProtected, &isPowerProtected);

    if (isPowerProtected == 1)
    {
        SET_FLAG(fdoExtension->DeviceFlags, DEV_POWER_PROTECTED);
    }

    ADJUST_FUA_FLAG(fdoExtension);

    return STATUS_SUCCESS;

} // end DiskStartFdo()
Esempio n. 2
0
NTSTATUS
NTAPI
DiskStartFdo(
    IN PDEVICE_OBJECT Fdo
    )

/*++

Routine Description:

    This routine will query the underlying device for any information necessary
    to complete initialization of the device.  This will include physical
    disk geometry, mode sense information and such.

    This routine does not perform partition enumeration - that is left to the
    re-enumeration routine

    If this routine fails it will return an error value.  It does not clean up
    any resources - that is left for the Stop/Remove routine.

Arguments:

    Fdo - a pointer to the functional device object for this device

Return Value:

    status

--*/

{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
    PDISK_DATA diskData = commonExtension->DriverData;
    STORAGE_HOTPLUG_INFO hotplugInfo;
    ULONG writeCacheOverride = DiskWriteCacheDefault;
    DISK_CACHE_INFORMATION cacheInfo;
    NTSTATUS status;

    PAGED_CODE();

    //
    // Get the hotplug information, so we can turn off write cache if needed
    //
    // NOTE: Capabilities info is not good enough to determine hotplugedness
    //       as  we cannot determine device relations  information and other
    //       dependencies. Get the hotplug info instead
    //

    {
        PIRP irp;
        KEVENT event;
        IO_STATUS_BLOCK statusBlock;

        KeInitializeEvent(&event, SynchronizationEvent, FALSE);
        RtlZeroMemory(&hotplugInfo, sizeof(STORAGE_HOTPLUG_INFO));

        irp = IoBuildDeviceIoControlRequest(IOCTL_STORAGE_GET_HOTPLUG_INFO,
                                            Fdo,
                                            NULL,
                                            0L,
                                            &hotplugInfo,
                                            sizeof(STORAGE_HOTPLUG_INFO),
                                            FALSE,
                                            &event,
                                            &statusBlock);

        if (irp != NULL) {

            // send to self -- classpnp handles this
            status = IoCallDriver(Fdo, irp);
            if (status == STATUS_PENDING) {
                KeWaitForSingleObject(&event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL);
                status = statusBlock.Status;
            }
        }
    }

    //
    // Clear the DEV_WRITE_CACHE flag now  and set
    // it below only if we read that from the disk
    //

    CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);

    if (TEST_FLAG(fdoExtension->ScanForSpecialFlags, CLASS_SPECIAL_DISABLE_WRITE_CACHE))
    {
        //
        // This flag overrides the user's  setting, because  faulty firmware
        // may cause the filesystem to refuse to format media on this device
        //
        DebugPrint((1,
                    "DiskStartFdo: Shutting off write cache for %p due to %s\n",
                    Fdo,
                    "Possible Firmware Issue"));

        writeCacheOverride = DiskWriteCacheDisable;
    }
    else
    {
        //
        // Look into the registry to  see if the user
        // has chosen to override the default setting
        //
        ClassGetDeviceParameter(fdoExtension,
                                DiskDeviceParameterSubkey,
                                DiskDeviceUserWriteCacheSetting,
                                &writeCacheOverride);

        if (writeCacheOverride == DiskWriteCacheDefault)
        {
            //
            // The user has not overridden the default settings
            //
            if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
            {
                DebugPrint((1,
                            "DiskStartFdo: Shutting off write cache for %p due to %s\n",
                            Fdo,
                            "Hotplug Device"));

                writeCacheOverride = DiskWriteCacheDisable;
            }
            else if (hotplugInfo.MediaHotplug)
            {
                DebugPrint((1,
                            "DiskStartFdo: Shutting off write cache for %p due to %s\n",
                            Fdo,
                            "Hotplug (unlockable) Media"));

                writeCacheOverride = DiskWriteCacheDisable;
            }
            else
            {
                //
                // We enable write cache if this device has no specific issues
                //
                writeCacheOverride = DiskWriteCacheEnable;
            }
        }
    }

    //
    // Query the disk to see if write cache is enabled
    // and  set the DEV_WRITE_CACHE flag appropriately
    //

    RtlZeroMemory(&cacheInfo, sizeof(DISK_CACHE_INFORMATION));

    status = DiskGetCacheInformation(fdoExtension, &cacheInfo);

    if (NT_SUCCESS(status))
    {
        if (cacheInfo.WriteCacheEnabled == TRUE)
        {
            if (writeCacheOverride == DiskWriteCacheDisable)
            {
                //
                // Write cache is currently enabled on this
                // device, but we would like to turn it off
                //
                cacheInfo.WriteCacheEnabled = FALSE;

                status = DiskSetCacheInformation(fdoExtension, &cacheInfo);
            }
            else
            {
                //
                // The write cache setting either matches
                // our needs or we don't care
                //
                SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
            }
        }
        else
        {
            if (writeCacheOverride == DiskWriteCacheEnable)
            {
                //
                // Write cache is currently disabled on this
                // device, but we  would  like to turn it on
                //
                cacheInfo.WriteCacheEnabled = TRUE;

                status = DiskSetCacheInformation(fdoExtension, &cacheInfo);

                SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
            }
        }
    }

    //
    // In the event that there's a cached partition table flush it now.
    //

    DiskAcquirePartitioningLock(fdoExtension);
    DiskInvalidatePartitionTable(fdoExtension, TRUE);
    DiskReleasePartitioningLock(fdoExtension);

    //
    // Get the SCSI address if it's available for use with SMART ioctls.
    //

    {
        PIRP irp;
        KEVENT event;
        IO_STATUS_BLOCK statusBlock;

        KeInitializeEvent(&event, SynchronizationEvent, FALSE);

        irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS,
                                            commonExtension->LowerDeviceObject,
                                            NULL,
                                            0L,
                                            &(diskData->ScsiAddress),
                                            sizeof(SCSI_ADDRESS),
                                            FALSE,
                                            &event,
                                            &statusBlock);

        if(irp != NULL) {


            status = IoCallDriver(commonExtension->LowerDeviceObject, irp);

            if(status == STATUS_PENDING) {
                KeWaitForSingleObject(&event,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      NULL);
                status = statusBlock.Status;
            }
        }
    }

    return STATUS_SUCCESS;

} // end DiskStartFdo()