ReactOS 0.4.15-dev-8241-g63935f8
pnp.c
Go to the documentation of this file.
1/*++
2
3Copyright (C) Microsoft Corporation, 1991 - 1999
4
5Module Name:
6
7 pnp.c
8
9Abstract:
10
11 SCSI disk class driver
12
13Environment:
14
15 kernel mode only
16
17Notes:
18
19Revision History:
20
21--*/
22
23#include "disk.h"
24
25
26#ifdef DEBUG_USE_WPP
27#include "pnp.tmh"
28#endif
29
30#ifndef __REACTOS__
32#else
34#endif
37
38
39#ifdef ALLOC_PRAGMA
40
41#pragma alloc_text(PAGE, DiskAddDevice)
42#pragma alloc_text(PAGE, DiskInitFdo)
43#pragma alloc_text(PAGE, DiskStartFdo)
44#pragma alloc_text(PAGE, DiskGenerateDeviceName)
45#pragma alloc_text(PAGE, DiskCreateSymbolicLinks)
46#pragma alloc_text(PAGE, DiskDeleteSymbolicLinks)
47#pragma alloc_text(PAGE, DiskRemoveDevice)
48#endif
49
50
52NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
56 )
57
58/*++
59
60Routine Description:
61
62 This routine gets a port drivers capabilities, obtains the
63 inquiry data, searches the SCSI bus for the port driver and creates
64 the device objects for the disks found.
65
66Arguments:
67
68 DriverObject - Pointer to driver object created by system.
69
70 Pdo - Device object use to send requests to port driver.
71
72Return Value:
73
74 True is returned if one disk was found and successfully created.
75
76--*/
77
78{
79 ULONG rootPartitionMountable = FALSE;
80
81 PCONFIGURATION_INFORMATION configurationInformation;
82 ULONG diskCount;
83
85
86 PAGED_CODE();
87
88 //
89 // See if we should be allowing file systems to mount on partition zero.
90 //
91
92 TRY {
93 HANDLE deviceKey = NULL;
94
95 UNICODE_STRING diskKeyName;
96 OBJECT_ATTRIBUTES objectAttributes = {0};
97 HANDLE diskKey;
98
99 RTL_QUERY_REGISTRY_TABLE queryTable[2] = { 0 };
100
103 KEY_READ,
104 &deviceKey);
105
106 if(!NT_SUCCESS(status)) {
107 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx opening device key "
108 "for pdo %p\n",
110 LEAVE;
111 }
112
113 RtlInitUnicodeString(&diskKeyName, L"Disk");
114 InitializeObjectAttributes(&objectAttributes,
115 &diskKeyName,
117 deviceKey,
118 NULL);
119
120 status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes);
121 ZwClose(deviceKey);
122
123 if(!NT_SUCCESS(status)) {
124 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx opening disk key "
125 "for pdo %p device key %p\n",
126 status, PhysicalDeviceObject, deviceKey));
127 LEAVE;
128 }
129
131 queryTable[0].Name = L"RootPartitionMountable";
132 queryTable[0].EntryContext = &(rootPartitionMountable);
134
135#ifdef _MSC_VER
136#pragma prefast(suppress:6309, "We don't have QueryRoutine so Context doesn't make any sense")
137#endif
139 diskKey,
140 queryTable,
141 NULL,
142 NULL);
143
144 if(!NT_SUCCESS(status)) {
145 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskAddDevice: Error %#08lx reading value from "
146 "disk key %p for pdo %p\n",
147 status, diskKey, PhysicalDeviceObject));
148 }
149
150 ZwClose(diskKey);
151
152 } FINALLY {
153
154 //
155 // Do nothing.
156 //
157
158 if(!NT_SUCCESS(status)) {
159 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskAddDevice: Will %sallow file system to mount on "
160 "partition zero of disk %p\n",
161 (rootPartitionMountable ? "" : "not "),
163 }
164 }
165
166 //
167 // Create device objects for disk
168 //
169
170 diskCount = 0;
171
175 &diskCount,
176 (BOOLEAN) !rootPartitionMountable
177 );
178
179 //
180 // Get the number of disks already initialized.
181 //
182
183 configurationInformation = IoGetConfigurationInformation();
184
185 if (NT_SUCCESS(status)) {
186
187 //
188 // Increment system disk device count.
189 //
190
191 configurationInformation->DiskCount++;
192
193 }
194
195 return status;
196
197} // end DiskAddDevice()
198
199
201NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
204 )
205
206/*++
207
208Routine Description:
209
210 This routine is called to do one-time initialization of new device objects
211
212
213Arguments:
214
215 Fdo - a pointer to the functional device object for this device
216
217Return Value:
218
219 status
220
221--*/
222
223{
224 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
225 PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
226
227 ULONG srbFlags = 0;
228 ULONG timeOut = 0;
229 ULONG bytesPerSector;
230
231 PULONG dmSkew;
232
234
235 PAGED_CODE();
236
237 //
238 // Build the lookaside list for srb's for the physical disk. Should only
239 // need a couple. If this fails then we don't have an emergency SRB so
240 // fail the call to initialize.
241 //
242
243 ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION) fdoExtension,
245
246 if (fdoExtension->DeviceDescriptor->RemovableMedia)
247 {
248 SET_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA);
249 }
250
251 //
252 // Initialize the srb flags.
253 //
254
255 //
256 // Because all requests share a common sense buffer, it is possible
257 // for the buffer to be overwritten if the port driver completes
258 // multiple failed requests that require a request sense before the
259 // class driver's completion routine can consume the data in the buffer.
260 // To prevent this, we allow the port driver to allocate a unique sense
261 // buffer each time it needs one. We are responsible for freeing this
262 // buffer. This also allows the adapter to be configured to support
263 // additional sense data beyond the minimum 18 bytes.
264 //
265
267
268 if (fdoExtension->DeviceDescriptor->CommandQueueing &&
269 fdoExtension->AdapterDescriptor->CommandQueueing) {
270
272
273 }
274
275 //
276 // Look for controllers that require special flags.
277 //
278
279 ClassScanForSpecial(fdoExtension, DiskBadControllers, DiskSetSpecialHacks);
280
281 //
282 // Clear buffer for drive geometry.
283 //
284
285 RtlZeroMemory(&(fdoExtension->DiskGeometry),
286 sizeof(DISK_GEOMETRY));
287
288 //
289 // Allocate request sense buffer.
290 //
291
292 fdoExtension->SenseData = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
295
296 if (fdoExtension->SenseData == NULL) {
297
298 //
299 // The buffer can not be allocated.
300 //
301
302 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskInitFdo: Can not allocate request sense buffer\n"));
303
305 return status;
306 }
307
308 //
309 // Set the buffer size of SenseData
310 //
311
313
314 //
315 // Physical device object will describe the entire
316 // device, starting at byte offset 0.
317 //
318
319 fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)(0);
320
321 //
322 // Set timeout value in seconds.
323 //
324 if ( (fdoExtension->MiniportDescriptor != NULL) &&
325 (fdoExtension->MiniportDescriptor->IoTimeoutValue > 0) ) {
326 //
327 // use the value set by Storport miniport driver
328 //
329 fdoExtension->TimeOutValue = fdoExtension->MiniportDescriptor->IoTimeoutValue;
330 } else {
331 //
332 // get timeout value from registry
333 //
334 timeOut = ClassQueryTimeOutRegistryValue(Fdo);
335
336 if (timeOut) {
337 fdoExtension->TimeOutValue = timeOut;
338 } else {
339 fdoExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
340 }
341 }
342 //
343 // If this is a removable drive, build an entry in devicemap\scsi
344 // indicating it's physicaldriveN name, set up the appropriate
345 // update partitions routine and set the flags correctly.
346 // note: only do this after the timeout value is set, above.
347 //
348
349 if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
350
351 ClassUpdateInformationInRegistry( Fdo,
352 "PhysicalDrive",
353 fdoExtension->DeviceNumber,
354 NULL,
355 0);
356 //
357 // Enable media change notification for removable disks
358 //
359 ClassInitializeMediaChangeDetection(fdoExtension,
360 (PUCHAR)"Disk");
361
362 } else {
363
366
367 }
368
369 //
370 // The commands we send during the init could cause the flags to change
371 // in case of any error. Save the SRB flags locally and restore it at
372 // the end of this function, so that the class driver can get it.
373 //
374
375 srbFlags = fdoExtension->SrbFlags;
376
377
378 //
379 // Read the drive capacity. Don't use the disk version of the routine here
380 // since we don't know the disk signature yet - the disk version will
381 // attempt to determine the BIOS reported geometry.
382 //
383
385
386 //
387 // Set up sector size fields.
388 //
389 // Stack variables will be used to update
390 // the partition device extensions.
391 //
392 // The device extension field SectorShift is
393 // used to calculate sectors in I/O transfers.
394 //
395 // The DiskGeometry structure is used to service
396 // IOCTls used by the format utility.
397 //
398
399 bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
400
401 //
402 // Make sure sector size is not zero.
403 //
404
405 if (bytesPerSector == 0) {
406
407 //
408 // Default sector size for disk is 512.
409 //
410
411 bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector = 512;
412 fdoExtension->SectorShift = 9;
413 }
414
415 //
416 // Determine is DM Driver is loaded on an IDE drive that is
417 // under control of Atapi - this could be either a crashdump or
418 // an Atapi device is sharing the controller with an IDE disk.
419 //
420
422 fdoExtension->DiskGeometry.BytesPerSector,
423 (ULONG)0x54,
424 (PVOID *)&dmSkew);
425
426 if (dmSkew) {
427
428 //
429 // Update the device extension, so that the call to IoReadPartitionTable
430 // will get the correct information. Any I/O to this disk will have
431 // to be skewed by *dmSkew sectors aka DMByteSkew.
432 //
433
434 fdoExtension->DMSkew = *dmSkew;
435 fdoExtension->DMActive = TRUE;
436 fdoExtension->DMByteSkew = fdoExtension->DMSkew * bytesPerSector;
437
438 FREE_POOL(dmSkew);
439 }
440
441#if defined(_X86_) || defined(_AMD64_)
442
443 //
444 // Try to read the signature off the disk and determine the correct drive
445 // geometry based on that. This requires rereading the disk size to get
446 // the cylinder count updated correctly.
447 //
448
449 if(!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
450
451 DiskReadSignature(Fdo);
453
454 if (diskData->GeometrySource == DiskGeometryUnknown)
455 {
456 //
457 // Neither the BIOS nor the port driver could provide us with a reliable
458 // geometry. Before we use the default, look to see if it was partitioned
459 // under Windows NT4 [or earlier] and apply the one that was used back then
460 //
461
462 if (DiskIsNT4Geometry(fdoExtension))
463 {
464 diskData->RealGeometry = fdoExtension->DiskGeometry;
465 diskData->RealGeometry.SectorsPerTrack = 0x20;
466 diskData->RealGeometry.TracksPerCylinder = 0x40;
467 fdoExtension->DiskGeometry = diskData->RealGeometry;
468
469 diskData->GeometrySource = DiskGeometryFromNT4;
470 }
471 }
472 }
473
474#endif
475
477
478 //
479 // Get the SCSI address if it's available for use with SMART ioctls.
480 // SMART ioctls are used for failure prediction, so we need to get
481 // the SCSI address before initializing failure prediction.
482 //
483
484 {
485 PIRP irp;
487 IO_STATUS_BLOCK statusBlock = { 0 };
488
490
493 NULL,
494 0L,
495 &(diskData->ScsiAddress),
496 sizeof(SCSI_ADDRESS),
497 FALSE,
498 &event,
499 &statusBlock);
500
502
503 if(irp != NULL) {
504
506
507 if(status == STATUS_PENDING) {
509 Executive,
511 FALSE,
512 NULL);
513 status = statusBlock.Status;
514 }
515 }
516 }
517
518 //
519 // Determine the type of disk and enable failure prediction in the hardware
520 // and enable failure prediction polling.
521 //
522
523 if (InitSafeBootMode == 0) // __REACTOS__
524 {
525 DiskDetectFailurePrediction(fdoExtension,
528
530 {
531 //
532 // Cool, we've got some sort of failure prediction, enable it
533 // at the hardware and then enable polling for it
534 //
535
536 //
537 // By default we allow performance to be degradeded if failure
538 // prediction is enabled.
539 //
540
541 diskData->AllowFPPerfHit = TRUE;
542
543 //
544 // Enable polling only after Atapi and SBP2 add support for the new
545 // SRB flag that indicates that the request should not reset the
546 // drive spin down idle timer.
547 //
548
550 TRUE,
552
553 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskInitFdo: Failure Prediction Poll enabled as "
554 "%d for device %p, Status = %lx\n",
556 Fdo,
557 status));
558 }
559 } else {
560
561 //
562 // In safe boot mode we do not enable failure prediction, as perhaps
563 // it is the reason why normal boot does not work
564 //
565
567
568 }
569
570 //
571 // Initialize the verify mutex
572 //
573
575
576 //
577 // Initialize the flush group context
578 //
579
580 RtlZeroMemory(&diskData->FlushContext, sizeof(DISK_GROUP_CONTEXT));
581
584
587
588
589 //
590 // Restore the saved value
591 //
592 fdoExtension->SrbFlags = srbFlags;
593
594 return STATUS_SUCCESS;
595
596} // end DiskInitFdo()
597
599NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
603 )
604
605{
608 return STATUS_SUCCESS;
609}
610
614 OUT PCCHAR *RawName
615 )
616
617/*++
618
619Routine Description:
620
621 This routine will allocate a unicode string buffer and then fill it in
622 with a generated name for the specified device object.
623
624 It is the responsibility of the user to allocate a UNICODE_STRING structure
625 to pass in and to free UnicodeName->Buffer when done with it.
626
627Arguments:
628
629 DeviceObject - a pointer to the device object
630
631 UnicodeName - a unicode string to put the name buffer into
632
633Return Value:
634
635 status
636
637--*/
638
639#define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d"
640
641{
642 CHAR rawName[64] = { 0 };
644
645 PAGED_CODE();
646
647 status = RtlStringCchPrintfA(rawName, sizeof(rawName) - 1, FDO_NAME_FORMAT, DeviceNumber,
649 if (!NT_SUCCESS(status)) {
650 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Format FDO name failed with error: 0x%X\n", status));
651 return status;
652 }
653
655 strlen(rawName) + 1,
657
658 if(*RawName == NULL) {
660 }
661
662 status = RtlStringCchCopyA(*RawName, strlen(rawName) + 1, rawName);
663 if (!NT_SUCCESS(status)) {
664 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Device name copy failed with error: 0x%X\n", status));
665 FREE_POOL(*RawName);
666 return status;
667 }
668
669 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskGenerateDeviceName: generated \"%s\"\n", rawName));
670
671 return STATUS_SUCCESS;
672}
673
674
675VOID
678 )
679
680/*++
681
682Routine Description:
683
684 This routine will generate a symbolic link for the specified device object
685 using the well known form \\Device\HarddiskX\PartitionY, where X and Y is
686 always 0 which represents the entire disk object.
687
688 This routine will not try to delete any previous symbolic link for the
689 same generated name - the caller must make sure the symbolic link has
690 been broken before calling this routine.
691
692Arguments:
693
694 DeviceObject - the device object to make a well known name for
695
696Return Value:
697
698 STATUS
699
700--*/
701
702{
703 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
704 PDISK_DATA diskData = commonExtension->DriverData;
705
706 WCHAR wideSourceName[64] = { 0 };
707 UNICODE_STRING unicodeSourceName;
708
710
711 PAGED_CODE();
712
713 //
714 // Build the destination for the link first using the device name
715 // stored in the device object
716 //
717
718 NT_ASSERT(commonExtension->DeviceName.Buffer);
719
720 if(!diskData->LinkStatus.WellKnownNameCreated) {
721 //
722 // Put together the source name using the partition and device number
723 // in the device extension and disk data segment
724 //
725
726 status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
727 L"\\Device\\Harddisk%d\\Partition0",
728 commonExtension->PartitionZeroExtension->DeviceNumber);
729
730 if (NT_SUCCESS(status)) {
731
732 RtlInitUnicodeString(&unicodeSourceName, wideSourceName);
733
734 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
735 &unicodeSourceName,
736 &commonExtension->DeviceName));
737
738 status = IoCreateSymbolicLink(&unicodeSourceName,
739 &commonExtension->DeviceName);
740
741 if(NT_SUCCESS(status)){
742 diskData->LinkStatus.WellKnownNameCreated = TRUE;
743 }
744 }
745 }
746
747 if (!diskData->LinkStatus.PhysicalDriveLinkCreated) {
748
749 //
750 // Create a physical drive N link using the device number we saved
751 // away during AddDevice.
752 //
753
754 status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1,
755 L"\\DosDevices\\PhysicalDrive%d",
756 commonExtension->PartitionZeroExtension->DeviceNumber);
757 if (NT_SUCCESS(status)) {
758
759 RtlInitUnicodeString(&unicodeSourceName, wideSourceName);
760
761 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n",
762 &unicodeSourceName,
763 &(commonExtension->DeviceName)));
764
765 status = IoCreateSymbolicLink(&unicodeSourceName,
766 &(commonExtension->DeviceName));
767
768 if(NT_SUCCESS(status)) {
769 diskData->LinkStatus.PhysicalDriveLinkCreated = TRUE;
770 }
771 }
772 }
773
774
775 return;
776}
777
778
779VOID
782 )
783
784/*++
785
786Routine Description:
787
788 This routine will delete the well known name (symlink) for the specified
789 device. It generates the link name using information stored in the
790 device extension
791
792Arguments:
793
794 DeviceObject - the device object we are unlinking
795
796Return Value:
797
798 status
799
800--*/
801
802{
803 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
804 PDISK_DATA diskData = commonExtension->DriverData;
805
806 WCHAR wideLinkName[64] = { 0 };
807 UNICODE_STRING unicodeLinkName;
809
810 PAGED_CODE();
811
812 if(diskData->LinkStatus.WellKnownNameCreated) {
813
814 status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
815 L"\\Device\\Harddisk%d\\Partition0",
816 commonExtension->PartitionZeroExtension->DeviceNumber);
817 if (NT_SUCCESS(status)) {
818 RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
819 IoDeleteSymbolicLink(&unicodeLinkName);
820 }
821 diskData->LinkStatus.WellKnownNameCreated = FALSE;
822 }
823
824 if(diskData->LinkStatus.PhysicalDriveLinkCreated) {
825
826 status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1,
827 L"\\DosDevices\\PhysicalDrive%d",
828 commonExtension->PartitionZeroExtension->DeviceNumber);
829 if (NT_SUCCESS(status)) {
830 RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
831 IoDeleteSymbolicLink(&unicodeLinkName);
832 }
833 diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE;
834 }
835
836
837 return;
838}
839
840
842NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
846 )
847
848/*++
849
850Routine Description:
851
852 This routine will release any resources the device may have allocated for
853 this device object and return.
854
855Arguments:
856
857 DeviceObject - the device object being removed
858
859Return Value:
860
861 status
862
863--*/
864
865{
866 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
867 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
868
869 PAGED_CODE();
870
871 //
872 // Handle query and cancel
873 //
874
877 return STATUS_SUCCESS;
878 }
879
880 //
881 // Delete our object directory.
882 //
883
884 if(fdoExtension->DeviceDirectory != NULL) {
886 ZwClose(fdoExtension->DeviceDirectory);
887 fdoExtension->DeviceDirectory = NULL;
888 }
889
891
892 FREE_POOL(fdoExtension->SenseData);
893
895
896 }
897
899
901 {
902 ClassDeleteSrbLookasideList(commonExtension);
903 }
904
905 return STATUS_SUCCESS;
906}
907
908
910NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
913 )
914
915/*++
916
917Routine Description:
918
919 This routine will query the underlying device for any information necessary
920 to complete initialization of the device. This will include physical
921 disk geometry, mode sense information and such.
922
923 This routine does not perform partition enumeration - that is left to the
924 re-enumeration routine
925
926 If this routine fails it will return an error value. It does not clean up
927 any resources - that is left for the Stop/Remove routine.
928
929Arguments:
930
931 Fdo - a pointer to the functional device object for this device
932
933Return Value:
934
935 status
936
937--*/
938
939{
940 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
941 PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
942 PDISK_DATA diskData = commonExtension->DriverData;
943 STORAGE_HOTPLUG_INFO hotplugInfo = { 0 };
944 DISK_CACHE_INFORMATION cacheInfo = { 0 };
945 ULONG isPowerProtected = 0;
947
948 PAGED_CODE();
949
950 //
951 // Get the hotplug information, so we can turn off write cache if needed
952 //
953 // NOTE: Capabilities info is not good enough to determine hotplugedness
954 // as we cannot determine device relations information and other
955 // dependencies. Get the hotplug info instead
956 //
957
958 {
959 PIRP irp;
961 IO_STATUS_BLOCK statusBlock = { 0 };
962
964
966 Fdo,
967 NULL,
968 0L,
969 &hotplugInfo,
970 sizeof(STORAGE_HOTPLUG_INFO),
971 FALSE,
972 &event,
973 &statusBlock);
974
975 if (irp != NULL) {
976
977 // send to self -- classpnp handles this
979 if (status == STATUS_PENDING) {
981 Executive,
983 FALSE,
984 NULL);
985
986 status = statusBlock.Status;
987 }
989 }
990 }
991
992 //
993 // Clear the DEV_WRITE_CACHE flag now and set
994 // it below only if we read that from the disk
995 //
996 CLEAR_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
997 ADJUST_FUA_FLAG(fdoExtension);
998
1000
1001 //
1002 // Look into the registry to see if the user
1003 // has chosen to override the default setting
1004 //
1005 ClassGetDeviceParameter(fdoExtension,
1008 (PULONG)&diskData->WriteCacheOverride);
1009
1011 {
1012 //
1013 // The user has not overridden the default settings
1014 //
1016 {
1017 //
1018 // This flag indicates that we have faulty firmware and this
1019 // may cause the filesystem to refuse to mount on this media
1020 //
1021 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to a firmware issue\n", Fdo));
1022
1024 }
1025 else if (hotplugInfo.DeviceHotplug && !hotplugInfo.WriteCacheEnableOverride)
1026 {
1027 //
1028 // This flag indicates that the device is hotpluggable making it unsafe to enable caching
1029 //
1030 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to hotpluggable device\n", Fdo));
1031
1033 }
1034 else if (hotplugInfo.MediaHotplug)
1035 {
1036 //
1037 // This flag indicates that the media in the device cannot be reliably locked
1038 //
1039 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_PNP, "DiskStartFdo: Turning off write cache for %p due to unlockable media\n", Fdo));
1040
1042 }
1043 else
1044 {
1045 //
1046 // Even though the device does not seem to have any obvious problems
1047 // we leave it to the user to modify the previous write cache setting
1048 //
1049 }
1050 }
1051
1052 //
1053 // Query the disk to see if write cache is enabled
1054 // and set the DEV_WRITE_CACHE flag appropriately
1055 //
1056
1057 status = DiskGetCacheInformation(fdoExtension, &cacheInfo);
1058
1059 if (NT_SUCCESS(status))
1060 {
1061 if (cacheInfo.WriteCacheEnabled == TRUE)
1062 {
1063 SET_FLAG(fdoExtension->DeviceFlags, DEV_WRITE_CACHE);
1064 ADJUST_FUA_FLAG(fdoExtension);
1065
1067 {
1068 //
1069 // Write cache is currently enabled on this
1070 // device, but we would like to turn it off
1071 //
1072 cacheInfo.WriteCacheEnabled = FALSE;
1073
1074 DiskSetCacheInformation(fdoExtension, &cacheInfo);
1075 }
1076 }
1077 else
1078 {
1080 {
1081 //
1082 // Write cache is currently disabled on this
1083 // device, but we would like to turn it on
1084 //
1085 cacheInfo.WriteCacheEnabled = TRUE;
1086
1087 DiskSetCacheInformation(fdoExtension, &cacheInfo);
1088 }
1089 }
1090 }
1091
1092 //
1093 // Query the registry to see if this disk is power-protected or not
1094 //
1095
1097
1098 ClassGetDeviceParameter(fdoExtension, DiskDeviceParameterSubkey, DiskDeviceCacheIsPowerProtected, &isPowerProtected);
1099
1100 if (isPowerProtected == 1)
1101 {
1103 }
1104
1105 ADJUST_FUA_FLAG(fdoExtension);
1106
1107 return STATUS_SUCCESS;
1108
1109} // end DiskStartFdo()
1110
#define PAGED_CODE()
unsigned char BOOLEAN
Type
Definition: Type.h:7
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
#define NTSYSAPI
Definition: ntoskrnl.h:12
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
#define DEV_SAFE_START_UNIT
Definition: cdrom.h:139
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define DEV_POWER_PROTECTED
Definition: cdrom.h:143
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define FINALLY
Definition: classpnp.h:116
#define LEAVE
Definition: classpnp.h:115
#define DEV_WRITE_CACHE
Definition: classpnp.h:178
#define CLASS_SPECIAL_DISABLE_WRITE_CACHE
Definition: classpnp.h:168
#define ADJUST_FUA_FLAG(fdoExt)
Definition: classpnp.h:53
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
@ FailurePredictionNone
Definition: classpnp.h:234
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[]
Definition: data.c:42
NTSTATUS NTAPI DiskGetCacheInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PDISK_CACHE_INFORMATION CacheInfo)
Definition: disk.c:3019
NTSTATUS NTAPI DiskSetCacheInformation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PDISK_CACHE_INFORMATION CacheInfo)
Definition: disk.c:3167
VOID NTAPI DiskSetSpecialHacks(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN ULONG_PTR Data)
Definition: disk.c:2602
NTSTATUS DiskCreateFdo(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject, IN PULONG DeviceCount, IN BOOLEAN DasdAccessOnly)
Definition: disk.c:307
#define DISK_TAG_NAME
Definition: disk.h:64
NTSTATUS DiskDetectFailurePrediction(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, PFAILURE_PREDICTION_METHOD FailurePredictCapability, BOOLEAN ScsiAddressAvailable)
Definition: diskwmi.c:2230
#define PARTITION0_LIST_SIZE
Definition: disk.h:413
#define DISK_TAG_START
Definition: disk.h:68
#define DISK_DEFAULT_FAILURE_POLLING_PERIOD
Definition: disk.h:456
#define DiskDeviceParameterSubkey
Definition: disk.h:403
#define DiskReadDriveCapacity(Fdo)
Definition: disk.h:818
#define MAX_SECTORS_PER_VERIFY
Definition: disk.h:435
#define DiskDeviceCacheIsPowerProtected
Definition: disk.h:405
struct _DISK_DATA * PDISK_DATA
#define DiskDeviceUserWriteCacheSetting
Definition: disk.h:404
#define SCSI_DISK_TIMEOUT
Definition: disk.h:412
NTSTATUS DiskEnableDisableFailurePredictPolling(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, BOOLEAN Enable, ULONG PollTimeInSeconds)
Definition: diskwmi.c:1193
@ DiskWriteCacheDefault
Definition: disk.h:181
@ DiskWriteCacheDisable
Definition: disk.h:179
@ DiskWriteCacheEnable
Definition: disk.h:180
NTSTATUS NTAPI DiskRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type)
Definition: pnp.c:843
NTSTATUS DiskGenerateDeviceName(IN ULONG DeviceNumber, OUT PCCHAR *RawName)
Definition: pnp.c:612
#define FDO_NAME_FORMAT
NTSTATUS NTAPI DiskStartFdo(IN PDEVICE_OBJECT Fdo)
Definition: pnp.c:911
NTSTATUS NTAPI DiskInitFdo(IN PDEVICE_OBJECT Fdo)
Definition: pnp.c:202
VOID DiskCreateSymbolicLinks(IN PDEVICE_OBJECT DeviceObject)
Definition: pnp.c:676
ULONG diskDeviceSequenceNumber
Definition: pnp.c:35
NTSTATUS NTAPI DiskAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject)
Definition: pnp.c:53
NTSTATUS NTAPI DiskStopDevice(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Type)
Definition: pnp.c:600
PULONG InitSafeBootMode
Definition: init.c:71
BOOLEAN DiskIsPastReinit
Definition: disk.c:81
VOID DiskDeleteSymbolicLinks(IN PDEVICE_OBJECT DeviceObject)
Definition: pnp.c:780
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:413
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
FxIrp * irp
struct _cl_event * event
Definition: glext.h:7739
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define KernelMode
Definition: asm.h:34
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI NTSTATUS NTAPI ZwMakeTemporaryObject(_In_ HANDLE Handle)
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define REG_NONE
Definition: nt_native.h:1492
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ SynchronizationEvent
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
#define STATUS_PENDING
Definition: ntstatus.h:82
NTSTRSAFEAPI RtlStringCchCopyA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:110
NTSTRSAFEVAPI RtlStringCchPrintfA(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1085
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
#define L(x)
Definition: ntvdm.h:50
#define HalExamineMBR
Definition: part_xbox.c:325
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:1621
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define REG_DWORD
Definition: sdbapi.c:596
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
LARGE_INTEGER StartingOffset
Definition: classpnp.h:619
PDEVICE_OBJECT DeviceObject
Definition: pci.h:46
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
UNICODE_STRING DeviceName
Definition: classpnp.h:615
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
BOOLEAN AllowFPPerfHit
Definition: disk.h:332
DISK_GROUP_CONTEXT FlushContext
Definition: disk.h:379
DISK_USER_WRITE_CACHE_SETTING WriteCacheOverride
Definition: disk.h:385
struct _DISK_DATA::@1064 LinkStatus
FAILURE_PREDICTION_METHOD FailurePredictionCapability
Definition: disk.h:331
KMUTEX VerifyMutex
Definition: disk.h:372
SCSI_ADDRESS ScsiAddress
Definition: disk.h:325
ULONG BytesPerSector
Definition: ntdddisk.h:409
LIST_ENTRY NextList
Definition: disk.h:118
KSPIN_LOCK Spinlock
Definition: disk.h:143
KEVENT Event
Definition: disk.h:148
LIST_ENTRY CurrList
Definition: disk.h:108
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: classpnp.h:876
BOOLEAN WriteCacheEnableOverride
Definition: imports.h:249
BOOLEAN DeviceHotplug
Definition: imports.h:248
BOOLEAN MediaHotplug
Definition: imports.h:247
Definition: ps.c:97
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
#define TRY(sps, bps)
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_CANCEL_REMOVE_DEVICE
#define IRP_MN_QUERY_REMOVE_DEVICE
@ Executive
Definition: ketypes.h:415
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define RTL_QUERY_REGISTRY_TYPECHECK
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175