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()
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()