3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI floppy class driver
24 02/28/96 georgioc Merged this code with code developed by compaq in
25 parallel with microsoft, for 120MB floppy support.
27 01/17/96 georgioc Made code PNP aware (uses the new \storage\classpnp/scsiport)
31 #if !defined(__REACTOS__) || defined(_MSC_VER)
32 #pragma warning(disable:4214) // nonstandard extension used : bit field types other than int
33 #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
46 #include <ntstrsafe.h>
50 // Downgrade unsupported NT6.2+ features.
51 #define NonPagedPoolNx NonPagedPool
52 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
55 #define MODE_DATA_SIZE 192
56 #define SCSI_FLOPPY_TIMEOUT 20
57 #define SFLOPPY_SRB_LIST_SIZE 4
59 // Define all possible drive/media combinations, given drives listed above
60 // and media types in ntdddisk.h.
62 // These values are used to index the DriveMediaConstants table.
65 #define NUMBER_OF_DRIVE_TYPES 7
66 #define DRIVE_TYPE_120M 4 //120MB Floptical
67 #define DRIVE_TYPE_NONE NUMBER_OF_DRIVE_TYPES
70 // This array describes all media types we support.
71 // It should be arranged in the increasing order of density
73 // For a given drive, we list all the mediatypes that will
74 // work with that drive. For instance, a 120MB drive will
75 // take 720KB media, 1.44MB media, and 120MB media.
77 // Note that, DriveMediaConstants given below is grouped
78 // as drive and media combination
80 typedef enum _DRIVE_MEDIA_TYPE
{
81 Drive360Media160
, // 5.25" 360k drive; 160k media
82 Drive360Media180
, // 5.25" 360k drive; 180k media
83 Drive360Media320
, // 5.25" 360k drive; 320k media
84 Drive360Media32X
, // 5.25" 360k drive; 320k 1k secs
85 Drive360Media360
, // 5.25" 360k drive; 360k media
86 Drive720Media720
, // 3.5" 720k drive; 720k media
87 Drive120Media160
, // 5.25" 1.2Mb drive; 160k media
88 Drive120Media180
, // 5.25" 1.2Mb drive; 180k media
89 Drive120Media320
, // 5.25" 1.2Mb drive; 320k media
90 Drive120Media32X
, // 5.25" 1.2Mb drive; 320k 1k secs
91 Drive120Media360
, // 5.25" 1.2Mb drive; 360k media
92 Drive120Media120
, // 5.25" 1.2Mb drive; 1.2Mb media
93 Drive144Media720
, // 3.5" 1.44Mb drive; 720k media
94 Drive144Media144
, // 3.5" 1.44Mb drive; 1.44Mb media
95 Drive288Media720
, // 3.5" 2.88Mb drive; 720k media
96 Drive288Media144
, // 3.5" 2.88Mb drive; 1.44Mb media
97 Drive288Media288
, // 3.5" 2.88Mb drive; 2.88Mb media
98 Drive2080Media720
, // 3.5" 20.8Mb drive; 720k media
99 Drive2080Media144
, // 3.5" 20.8Mb drive; 1.44Mb media
100 Drive2080Media2080
, // 3.5" 20.8Mb drive; 20.8Mb media
101 Drive32MMedia32M
, // 3.5" 32Mb drive; 32MB media
102 Drive120MMedia720
, // 3.5" 120Mb drive; 720k media
103 Drive120MMedia144
, // 3.5" 120Mb drive; 1.44Mb media
104 Drive120MMedia120M
, // 3.5" 120Mb drive; 120Mb media
105 Drive240MMedia144M
, // 3.5" 240Mb drive; 1.44Mb media
106 Drive240MMedia120M
, // 3.5" 240Mb drive; 120Mb media
107 Drive240MMedia240M
// 3.5" 240Mb drive; 240Mb media
111 // When we want to determine the media type in a drive, we will first
112 // guess that the media with highest possible density is in the drive,
113 // and keep trying lower densities until we can successfully read from
116 // These values are used to select a DRIVE_MEDIA_TYPE value.
118 // The following table defines ranges that apply to the DRIVE_MEDIA_TYPE
119 // enumerated values when trying media types for a particular drive type.
120 // Note that for this to work, the DRIVE_MEDIA_TYPE values must be sorted
121 // by ascending densities within drive types. Also, for maximum track
122 // size to be determined properly, the drive types must be in ascending
126 typedef struct _DRIVE_MEDIA_LIMITS
{
127 DRIVE_MEDIA_TYPE HighestDriveMediaType
;
128 DRIVE_MEDIA_TYPE LowestDriveMediaType
;
129 } DRIVE_MEDIA_LIMITS
, *PDRIVE_MEDIA_LIMITS
;
132 DRIVE_MEDIA_LIMITS DriveMediaLimits
[NUMBER_OF_DRIVE_TYPES
] = {
134 { Drive360Media360
, Drive360Media160
}, // DRIVE_TYPE_0360
135 { Drive120Media120
, Drive120Media160
}, // DRIVE_TYPE_1200
136 { Drive720Media720
, Drive720Media720
}, // DRIVE_TYPE_0720
137 { Drive144Media144
, Drive144Media720
}, // DRIVE_TYPE_1440
138 { Drive288Media288
, Drive288Media720
}, // DRIVE_TYPE_2880
139 { Drive2080Media2080
, Drive2080Media720
}
142 DRIVE_MEDIA_LIMITS DriveMediaLimits
[NUMBER_OF_DRIVE_TYPES
] = {
144 { Drive720Media720
, Drive720Media720
}, // DRIVE_TYPE_0720
145 { Drive144Media144
, Drive144Media720
}, // DRIVE_TYPE_1440
146 { Drive288Media288
, Drive288Media720
}, // DRIVE_TYPE_2880
147 { Drive2080Media2080
, Drive2080Media720
},
148 { Drive32MMedia32M
, Drive32MMedia32M
}, // DRIVE_TYPE_32M
149 { Drive120MMedia120M
, Drive120MMedia720
}, // DRIVE_TYPE_120M
150 { Drive240MMedia240M
, Drive240MMedia144M
} // DRIVE_TYPE_240M
155 // For each drive/media combination, define important constants.
158 typedef struct _DRIVE_MEDIA_CONSTANTS
{
159 MEDIA_TYPE MediaType
;
160 USHORT BytesPerSector
;
161 UCHAR SectorsPerTrack
;
164 } DRIVE_MEDIA_CONSTANTS
, *PDRIVE_MEDIA_CONSTANTS
;
167 // Magic value to add to the SectorLengthCode to use it as a shift value
168 // to determine the sector size.
171 #define SECTORLENGTHCODE_TO_BYTESHIFT 7
174 // The following values were gleaned from many different sources, which
175 // often disagreed with each other. Where numbers were in conflict, I
176 // chose the more conservative or most-often-selected value.
179 DRIVE_MEDIA_CONSTANTS DriveMediaConstants
[] =
182 { F5_160_512
, 0x200, 0x08, 0x27, 0x1 },
183 { F5_180_512
, 0x200, 0x09, 0x27, 0x1 },
184 { F5_320_1024
, 0x400, 0x04, 0x27, 0x2 },
185 { F5_320_512
, 0x200, 0x08, 0x27, 0x2 },
186 { F5_360_512
, 0x200, 0x09, 0x27, 0x2 },
188 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
190 { F5_160_512
, 0x200, 0x08, 0x27, 0x1 },
191 { F5_180_512
, 0x200, 0x09, 0x27, 0x1 },
192 { F5_320_1024
, 0x400, 0x04, 0x27, 0x2 },
193 { F5_320_512
, 0x200, 0x08, 0x27, 0x2 },
194 { F5_360_512
, 0x200, 0x09, 0x27, 0x2 },
195 { F5_1Pt2_512
, 0x200, 0x0f, 0x4f, 0x2 },
197 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
198 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
200 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
201 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
202 { F3_2Pt88_512
, 0x200, 0x24, 0x4f, 0x2 },
204 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
205 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
206 { F3_20Pt8_512
, 0x200, 0x1b, 0xfa, 0x6 },
208 { F3_32M_512
, 0x200, 0x20, 0x3ff,0x2},
210 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
211 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
212 { F3_120M_512
, 0x200, 0x20, 0x3c2,0x8 },
214 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
215 { F3_120M_512
, 0x200, 0x20, 0x3c2,0x8 },
216 { F3_240M_512
, 0x200, 0x38, 0x105,0x20}
220 #define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS sizeof(DriveMediaConstants)/sizeof(DRIVE_MEDIA_CONSTANTS)
223 // floppy device data
226 typedef struct _DISK_DATA
{
229 // BOOLEAN EnableDMF;
230 UNICODE_STRING FloppyInterfaceString
;
231 } DISK_DATA
, *PDISK_DATA
;
234 // The FloppyCapacities and FloppyGeometries arrays are used by the
235 // USBFlopGetMediaTypes() and USBFlopFormatTracks() routines.
237 // The FloppyCapacities and FloppyGeometries arrays must be kept in 1:1 sync,
238 // i.e. each FloppyGeometries[i] must correspond to each FloppyCapacities[i].
240 // Also, the arrays must be kept in sorted ascending order so that they
241 // are returned in sorted ascending order by IOCTL_DISK_GET_MEDIA_TYPES.
244 typedef struct _FORMATTED_CAPACITY
246 ULONG NumberOfBlocks
;
250 BOOLEAN CanFormat
; // return for IOCTL_DISK_GET_MEDIA_TYPES ?
252 } FORMATTED_CAPACITY
, *PFORMATTED_CAPACITY
;
255 FORMATTED_CAPACITY FloppyCapacities
[] =
257 // Blocks BlockLen CanFormat H T B/S S/T
258 {0x000500, 0x0200, TRUE
}, // 2 80 512 8 640 KB F5_640_512
259 {0x0005A0, 0x0200, TRUE
}, // 2 80 512 9 720 KB F3_720_512
260 {0x000960, 0x0200, TRUE
}, // 2 80 512 15 1.20 MB F3_1Pt2_512 (Toshiba)
261 {0x0004D0, 0x0400, TRUE
}, // 2 77 1024 8 1.23 MB F3_1Pt23_1024 (NEC)
262 {0x000B40, 0x0200, TRUE
}, // 2 80 512 18 1.44 MB F3_1Pt44_512
263 {0x000D20, 0x0200, FALSE
}, // 2 80 512 21 1.70 MB DMF
264 {0x010000, 0x0200, TRUE
}, // 2 1024 512 32 32 MB F3_32M_512
265 {0x03C300, 0x0200, TRUE
}, // 8 963 512 32 120 MB F3_120M_512
266 {0x0600A4, 0x0200, TRUE
}, // 13 890 512 34 200 MB F3_200Mb_512 (HiFD)
267 {0x072A00, 0x0200, TRUE
} // 32 262 512 56 240 MB F3_240M_512
270 DISK_GEOMETRY FloppyGeometries
[] =
272 // Cyl MediaType Trk/Cyl Sec/Trk Bytes/Sec
274 {{80,0}, F3_640_512
, 2, 8, 512},
275 {{80,0}, F3_720_512
, 2, 9, 512},
276 {{80,0}, F3_1Pt2_512
, 2, 15, 512},
277 {{77,0}, F3_1Pt23_1024
, 2, 8, 1024},
278 {{80,0}, F3_1Pt44_512
, 2, 18, 512},
279 {{80,0}, F3_1Pt44_512
, 2, 21, 512}, // DMF -> F3_1Pt44_512
280 {{1024,0}, F3_32M_512
, 2, 32, 512},
281 {{963,0}, F3_120M_512
, 8, 32, 512},
282 {{890,0}, F3_200Mb_512
, 13, 34, 512},
283 {{262,0}, F3_240M_512
, 32, 56, 512}
285 {{{80,0}}, F3_640_512
, 2, 8, 512},
286 {{{80,0}}, F3_720_512
, 2, 9, 512},
287 {{{80,0}}, F3_1Pt2_512
, 2, 15, 512},
288 {{{77,0}}, F3_1Pt23_1024
, 2, 8, 1024},
289 {{{80,0}}, F3_1Pt44_512
, 2, 18, 512},
290 {{{80,0}}, F3_1Pt44_512
, 2, 21, 512}, // DMF -> F3_1Pt44_512
291 {{{1024,0}}, F3_32M_512
, 2, 32, 512},
292 {{{963,0}}, F3_120M_512
, 8, 32, 512},
293 {{{890,0}}, F3_200Mb_512
, 13, 34, 512},
294 {{{262,0}}, F3_240M_512
, 32, 56, 512}
298 #define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0]))
300 C_ASSERT((sizeof(FloppyGeometries
)/sizeof(FloppyGeometries
[0])) == FLOPPY_CAPACITIES
);
303 // The following structures are used by USBFlopFormatTracks()
306 #pragma pack (push, 1)
308 typedef struct _CDB12FORMAT
311 UCHAR DefectListFormat
: 3;
314 UCHAR LogicalUnitNumber
: 3;
319 UCHAR ParameterListLengthMsb
;
320 UCHAR ParameterListLengthLsb
;
322 } CDB12FORMAT
, *PCDB12FORMAT
;
325 typedef struct _DEFECT_LIST_HEADER
331 UCHAR SingleTrack
: 1;
332 UCHAR DisableCert
: 1;
334 UCHAR FormatOptionsValid
: 1;
335 UCHAR DefectListLengthMsb
;
336 UCHAR DefectListLengthLsb
;
337 } DEFECT_LIST_HEADER
, *PDEFECT_LIST_HEADER
;
339 typedef struct _FORMAT_UNIT_PARAMETER_LIST
341 DEFECT_LIST_HEADER DefectListHeader
;
342 FORMATTED_CAPACITY_DESCRIPTOR FormatDescriptor
;
343 } FORMAT_UNIT_PARAMETER_LIST
, *PFORMAT_UNIT_PARAMETER_LIST
;
347 DRIVER_INITIALIZE DriverEntry
;
349 DRIVER_UNLOAD ScsiFlopUnload
;
351 DRIVER_ADD_DEVICE ScsiFlopAddDevice
;
358 IN PDEVICE_OBJECT Fdo
366 IN PDEVICE_OBJECT Fdo
373 ScsiFlopRemoveDevice(
374 IN PDEVICE_OBJECT Fdo
,
383 IN PDEVICE_OBJECT Fdo
,
389 IN PDRIVER_OBJECT DriverObject
,
390 IN PUNICODE_STRING RegistryPath
,
391 IN PCLASS_INIT_DATA InitializationData
,
392 IN PDEVICE_OBJECT PortDeviceObject
,
400 ScsiFlopReadWriteVerification(
401 IN PDEVICE_OBJECT DeviceObject
,
409 ScsiFlopDeviceControl(
410 IN PDEVICE_OBJECT DeviceObject
,
416 PDEVICE_OBJECT DeviceObject
420 CreateFlopDeviceObject(
421 IN PDRIVER_OBJECT DriverObject
,
422 IN PDEVICE_OBJECT PortDeviceObject
,
428 PDEVICE_OBJECT DeviceObject
433 PDEVICE_OBJECT DeviceObject
437 FlCheckFormatParameters(
438 IN PDEVICE_OBJECT DeviceObject
,
439 IN PFORMAT_PARAMETERS FormatParameters
444 PDEVICE_OBJECT DeviceObject
,
449 FlopticalFormatMedia(
450 PDEVICE_OBJECT DeviceObject
,
451 PFORMAT_PARAMETERS Format
458 ScsiFlopProcessError(
459 PDEVICE_OBJECT DeviceObject
,
460 PSCSI_REQUEST_BLOCK Srb
,
466 USBFlopGetMediaTypes(
467 IN PDEVICE_OBJECT DeviceObject
,
473 IN PDEVICE_OBJECT DeviceObject
,
478 #pragma alloc_text(INIT, DriverEntry)
480 #pragma alloc_text(PAGE, ScsiFlopUnload)
481 #pragma alloc_text(PAGE, ScsiFlopAddDevice)
482 #pragma alloc_text(PAGE, CreateFlopDeviceObject)
483 #pragma alloc_text(PAGE, ScsiFlopStartDevice)
484 #pragma alloc_text(PAGE, ScsiFlopRemoveDevice)
485 #pragma alloc_text(PAGE, IsFloppyDevice)
486 #pragma alloc_text(PAGE, DetermineMediaType)
487 #pragma alloc_text(PAGE, DetermineDriveType)
488 #pragma alloc_text(PAGE, FlCheckFormatParameters)
489 #pragma alloc_text(PAGE, FormatMedia)
490 #pragma alloc_text(PAGE, FlopticalFormatMedia)
491 #pragma alloc_text(PAGE, USBFlopGetMediaTypes)
492 #pragma alloc_text(PAGE, USBFlopFormatTracks)
502 IN PDRIVER_OBJECT DriverObject
,
503 IN PUNICODE_STRING RegistryPath
509 This is the system initialization routine for installable drivers.
510 It calls the SCSI class driver initialization routine.
514 DriverObject - Pointer to driver object created by system.
523 CLASS_INIT_DATA InitializationData
;
529 RtlZeroMemory (&InitializationData
, sizeof(CLASS_INIT_DATA
));
535 InitializationData
.InitializationDataSize
= sizeof(CLASS_INIT_DATA
);
536 InitializationData
.FdoData
.DeviceExtensionSize
=
537 sizeof(FUNCTIONAL_DEVICE_EXTENSION
) + sizeof(DISK_DATA
);
539 InitializationData
.FdoData
.DeviceType
= FILE_DEVICE_DISK
;
540 InitializationData
.FdoData
.DeviceCharacteristics
= FILE_REMOVABLE_MEDIA
| FILE_FLOPPY_DISKETTE
;
546 InitializationData
.FdoData
.ClassInitDevice
= ScsiFlopInitDevice
;
547 InitializationData
.FdoData
.ClassStartDevice
= ScsiFlopStartDevice
;
548 InitializationData
.FdoData
.ClassStopDevice
= ScsiFlopStopDevice
;
549 InitializationData
.FdoData
.ClassRemoveDevice
= ScsiFlopRemoveDevice
;
551 InitializationData
.FdoData
.ClassReadWriteVerification
= ScsiFlopReadWriteVerification
;
552 InitializationData
.FdoData
.ClassDeviceControl
= ScsiFlopDeviceControl
;
554 InitializationData
.FdoData
.ClassShutdownFlush
= NULL
;
555 InitializationData
.FdoData
.ClassCreateClose
= NULL
;
556 InitializationData
.FdoData
.ClassError
= ScsiFlopProcessError
;
557 InitializationData
.ClassStartIo
= NULL
;
559 InitializationData
.ClassAddDevice
= ScsiFlopAddDevice
;
560 InitializationData
.ClassUnload
= ScsiFlopUnload
;
562 // Call the class init routine
565 return ClassInitialize( DriverObject
, RegistryPath
, &InitializationData
);
568 } // end DriverEntry()
575 IN PDRIVER_OBJECT DriverObject
579 UNREFERENCED_PARAMETER(DriverObject
);
584 // AddDevice operation is performed in CreateFlopDeviceObject function which
585 // is called by ScsiFlopAddDevice (The AddDevice routine for sfloppy.sys).
586 // DO_DEVICE_INITIALIZING flag is cleard upon successfully processing AddDevice
587 // operation in CreateFlopDeviceObject. But PREFAST is currently unable to
588 // detect that DO_DEVICE_INITIALIZING is indeed cleard in CreateFlopDeviceObject
589 // and it raises Warning 28152 (The return from an AddDevice-like function
590 // unexpectedly did not clear DO_DEVICE_INITIALIZING). Suppress that warning
594 #if !defined(__REACTOS__) || defined(_MSC_VER)
595 #pragma warning(push)
596 #pragma warning(disable:28152)
604 IN PDRIVER_OBJECT DriverObject
,
605 IN PDEVICE_OBJECT Pdo
611 This routine creates and initializes a new FDO for the corresponding
612 PDO. It may perform property queries on the FDO but cannot do any
613 media access operations.
617 DriverObject - Scsiscan class driver object.
619 Pdo - the physical device object we are being added to
628 ULONG floppyCount
= IoGetConfigurationInformation()->FloppyCount
;
633 // Get the number of disks already initialized.
636 status
= CreateFlopDeviceObject(DriverObject
, Pdo
, floppyCount
);
638 if (NT_SUCCESS(status
)) {
641 // Increment system floppy device count.
644 IoGetConfigurationInformation()->FloppyCount
++;
651 CreateFlopDeviceObject(
652 IN PDRIVER_OBJECT DriverObject
,
653 IN PDEVICE_OBJECT Pdo
,
661 This routine creates an object for the device and then calls the
662 SCSI port driver for media capacity and sector size.
666 DriverObject - Pointer to driver object created by system.
667 PortDeviceObject - to connect to SCSI port driver.
668 DeviceCount - Number of previously installed Floppys.
669 AdapterDescriptor - Pointer to structure returned by SCSI port
670 driver describing adapter capabilites (and limitations).
671 DeviceDescriptor - Pointer to configuration information for this device.
678 PDEVICE_OBJECT deviceObject
= NULL
;
679 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= NULL
;
684 DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n"));
687 // Try to claim the device.
690 status
= ClassClaimDevice(Pdo
,FALSE
);
692 if (!NT_SUCCESS(status
)) {
702 // Create device object for this device.
707 status
= RtlStringCbPrintfA((PCCHAR
) name
,
709 "\\Device\\Floppy%u",
711 if (NT_SUCCESS(status
)) {
713 status
= ClassCreateDeviceObject(DriverObject
,
719 } while ((status
== STATUS_OBJECT_NAME_COLLISION
) ||
720 (status
== STATUS_OBJECT_NAME_EXISTS
));
722 if (!NT_SUCCESS(status
)) {
723 DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n"));
724 goto CreateFlopDeviceObjectExit
;
728 // Indicate that IRPs should include MDLs.
731 deviceObject
->Flags
|= DO_DIRECT_IO
;
733 fdoExtension
= deviceObject
->DeviceExtension
;
736 // Back pointer to device object.
739 fdoExtension
->CommonExtension
.DeviceObject
= deviceObject
;
742 // This is the physical device.
745 fdoExtension
->CommonExtension
.PartitionZeroExtension
= fdoExtension
;
748 // Reset the drive type.
751 diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
752 diskData
->DriveType
= DRIVE_TYPE_NONE
;
753 diskData
->IsDMF
= FALSE
;
754 // diskData->EnableDMF = TRUE;
757 // Initialize lock count to zero. The lock count is used to
758 // disable the ejection mechanism when media is mounted.
761 fdoExtension
->LockCount
= 0;
764 // Save system floppy number
767 fdoExtension
->DeviceNumber
= DeviceCount
;
770 // Set the alignment requirements for the device based on the
771 // host adapter requirements
774 if (Pdo
->AlignmentRequirement
> deviceObject
->AlignmentRequirement
) {
775 deviceObject
->AlignmentRequirement
= Pdo
->AlignmentRequirement
;
779 // Clear the SrbFlags and disable synchronous transfers
782 fdoExtension
->SrbFlags
= SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
785 // Finally, attach to the PDO
788 fdoExtension
->LowerPdo
= Pdo
;
790 fdoExtension
->CommonExtension
.LowerDeviceObject
=
791 IoAttachDeviceToDeviceStack(deviceObject
, Pdo
);
793 if(fdoExtension
->CommonExtension
.LowerDeviceObject
== NULL
) {
795 status
= STATUS_UNSUCCESSFUL
;
796 goto CreateFlopDeviceObjectExit
;
799 deviceObject
->StackSize
++;
802 // The device is initialized properly - mark it as such.
805 deviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
807 return STATUS_SUCCESS
;
809 CreateFlopDeviceObjectExit
:
811 if (deviceObject
!= NULL
) {
812 IoDeleteDevice(deviceObject
);
817 } // end CreateFlopDeviceObject()
818 #if !defined(__REACTOS__) || defined(_MSC_VER)
827 IN PDEVICE_OBJECT Fdo
830 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
831 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
832 PDISK_DATA diskData
= commonExtension
->DriverData
;
834 PVOID senseData
= NULL
;
837 NTSTATUS status
= STATUS_SUCCESS
;
840 // Allocate request sense buffer.
843 senseData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, SENSE_BUFFER_SIZE
);
845 if (senseData
== NULL
) {
848 // The buffer cannot be allocated.
851 status
= STATUS_INSUFFICIENT_RESOURCES
;
856 // Set the sense data pointer in the device extension.
859 fdoExtension
->SenseData
= senseData
;
862 // Build the lookaside list for srb's for this device.
865 ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION
)fdoExtension
,
866 SFLOPPY_SRB_LIST_SIZE
);
869 // Register for media change notification
871 ClassInitializeMediaChangeDetection(fdoExtension
,
875 // Set timeout value in seconds.
878 timeOut
= ClassQueryTimeOutRegistryValue(Fdo
);
880 fdoExtension
->TimeOutValue
= timeOut
;
882 fdoExtension
->TimeOutValue
= SCSI_FLOPPY_TIMEOUT
;
886 // Floppies are not partitionable so starting offset is 0.
889 fdoExtension
->CommonExtension
.StartingOffset
.QuadPart
= (LONGLONG
)0;
892 if (!IsFloppyDevice(Fdo
) ||
893 !(Fdo
->Characteristics
& FILE_REMOVABLE_MEDIA
) ||
894 (fdoExtension
->DeviceDescriptor
->DeviceType
!= DIRECT_ACCESS_DEVICE
)) {
896 ExFreePool(senseData
);
897 status
= STATUS_NO_SUCH_DEVICE
;
902 RtlZeroMemory(&(fdoExtension
->DiskGeometry
),
903 sizeof(DISK_GEOMETRY
));
906 // Determine the media type if possible. Set the current media type to
907 // Unknown so that determine media type will check the media.
910 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
913 // Register interfaces for this device.
917 UNICODE_STRING interfaceName
;
919 RtlInitUnicodeString(&interfaceName
, NULL
);
921 status
= IoRegisterDeviceInterface(fdoExtension
->LowerPdo
,
922 (LPGUID
) &GUID_DEVINTERFACE_FLOPPY
,
926 if(NT_SUCCESS(status
)) {
927 diskData
->FloppyInterfaceString
= interfaceName
;
929 RtlInitUnicodeString(&(diskData
->FloppyInterfaceString
), NULL
);
930 DebugPrint((1, "ScsiFlopStartDevice: Unable to register device "
931 "interface for fdo %p [%08lx]\n",
936 return (STATUS_SUCCESS
);
939 #if !defined(__REACTOS__) || defined(_MSC_VER)
940 #pragma warning(suppress:6262) // This function uses 1096 bytes of stack which exceed default value of 1024 bytes used by Code Analysis for flagging as warning
943 NTSTATUS NTAPI
ScsiFlopStartDevice(
945 NTSTATUS
ScsiFlopStartDevice(
947 IN PDEVICE_OBJECT Fdo
950 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
951 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
954 IO_STATUS_BLOCK ioStatus
;
956 SCSI_ADDRESS scsiAddress
;
958 WCHAR ntNameBuffer
[256];
959 UNICODE_STRING ntUnicodeString
;
961 WCHAR arcNameBuffer
[256];
962 UNICODE_STRING arcUnicodeString
;
966 NTSTATUS status
= STATUS_SUCCESS
;
970 KeInitializeEvent(&event
,SynchronizationEvent
,FALSE
);
972 DetermineMediaType(Fdo
); // ignore unsuccessful here
975 // Create device object for this device.
978 RtlStringCbPrintfW(ntNameBuffer
,
979 sizeof(ntNameBuffer
),
980 L
"\\Device\\Floppy%u",
981 fdoExtension
->DeviceNumber
);
984 // Create local copy of unicode string
986 RtlInitUnicodeString(&ntUnicodeString
,ntNameBuffer
);
989 // Create a symbolic link from the disk name to the corresponding
990 // ARC name, to be used if we're booting off the disk. This will
991 // fail if it's not system initialization time; that's fine. The
992 // ARC name looks something like \ArcName\scsi(0)Flop(0)fdisk(0).
993 // In order to get the address, we need to send a IOCTL_SCSI_GET_ADDRESS...
996 irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS
,
1001 sizeof(scsiAddress
),
1007 return STATUS_INSUFFICIENT_RESOURCES
;
1010 status
= IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, irp
);
1012 if (status
== STATUS_PENDING
) {
1013 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
1014 status
= ioStatus
.Status
;
1018 // IOCTL_SCSI_GET_ADDRESS might not be supported by the port driver and
1019 // hence may fail. But it is not a fatal error. Do not fail PnP start
1020 // if this IOCTL fails.
1022 if (NT_SUCCESS(status
)) {
1024 RtlStringCbPrintfW(arcNameBuffer
,
1025 sizeof(arcNameBuffer
),
1026 L
"\\ArcName\\scsi(%u)disk(%u)fdisk(%u)",
1027 scsiAddress
.PortNumber
,
1028 scsiAddress
.TargetId
,
1031 RtlInitUnicodeString(&arcUnicodeString
, arcNameBuffer
);
1033 IoAssignArcName(&arcUnicodeString
, &ntUnicodeString
);
1036 status
= STATUS_SUCCESS
;
1039 // Create the multi() arc name -- Create the "fake"
1040 // name of multi(0)disk(0)fdisk(#) to handle the case where the
1041 // SCSI floppy is the only floppy in the system. If this fails
1042 // it doesn't matter because the previous scsi() based ArcName
1043 // will work. This name is necessary for installation.
1046 RtlStringCbPrintfW(arcNameBuffer
,
1047 sizeof(arcNameBuffer
),
1048 L
"\\ArcName\\multi(%u)disk(%u)fdisk(%u)",
1051 fdoExtension
->DeviceNumber
);
1053 RtlInitUnicodeString(&arcUnicodeString
, arcNameBuffer
);
1055 IoAssignArcName(&arcUnicodeString
, &ntUnicodeString
);
1058 // Set our interface state.
1062 PDISK_DATA diskData
= commonExtension
->DriverData
;
1064 if(diskData
->FloppyInterfaceString
.Buffer
!= NULL
) {
1066 status
= IoSetDeviceInterfaceState(
1067 &(diskData
->FloppyInterfaceString
),
1070 if(!NT_SUCCESS(status
)) {
1071 DebugPrint((1, "ScsiFlopStartDevice: Unable to set device "
1072 "interface state to TRUE for fdo %p "
1079 return STATUS_SUCCESS
;
1087 ScsiFlopReadWriteVerification(
1088 IN PDEVICE_OBJECT DeviceObject
,
1094 Routine Description:
1105 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1106 PIO_STACK_LOCATION irpSp
= IoGetCurrentIrpStackLocation(Irp
);
1107 NTSTATUS status
= STATUS_SUCCESS
;
1110 // Make sure that the number of bytes to transfer is a multiple of the sector size
1112 if ((irpSp
->Parameters
.Read
.Length
& (fdoExtension
->DiskGeometry
.BytesPerSector
- 1)) != 0)
1114 status
= STATUS_INVALID_PARAMETER
;
1117 Irp
->IoStatus
.Status
= status
;
1127 ScsiFlopDeviceControl(
1128 PDEVICE_OBJECT DeviceObject
,
1134 Routine Description:
1146 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
1147 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1148 PSCSI_REQUEST_BLOCK srb
;
1151 PDISK_GEOMETRY outputBuffer
;
1152 ULONG outputBufferLength
;
1154 DRIVE_MEDIA_TYPE lowestDriveMediaType
;
1155 DRIVE_MEDIA_TYPE highestDriveMediaType
;
1156 PFORMAT_PARAMETERS formatParameters
;
1157 PMODE_PARAMETER_HEADER modeData
;
1161 // Initialize the information field
1163 Irp
->IoStatus
.Information
= 0;
1165 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
1169 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1170 if (IoIsErrorUserInduced(Irp
->IoStatus
.Status
)) {
1172 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1175 KeRaiseIrql(DISPATCH_LEVEL
, ¤tIrql
);
1176 ClassReleaseRemoveLock(DeviceObject
, Irp
);
1177 ClassCompleteRequest(DeviceObject
, Irp
, 0);
1178 KeLowerIrql(currentIrql
);
1180 return(STATUS_INSUFFICIENT_RESOURCES
);
1184 // Write zeros to Srb.
1187 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
1189 cdb
= (PCDB
)srb
->Cdb
;
1191 switch (irpStack
->Parameters
.DeviceIoControl
.IoControlCode
) {
1194 case IOCTL_DISK_VERIFY
: {
1196 PVERIFY_INFORMATION verifyInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
1197 LARGE_INTEGER byteOffset
;
1202 // Validate buffer length.
1205 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
1206 sizeof(VERIFY_INFORMATION
)) {
1208 status
= STATUS_INFO_LENGTH_MISMATCH
;
1213 // Perform a bounds check on the sector range
1215 if ((verifyInfo
->StartingOffset
.QuadPart
> fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
) ||
1216 (verifyInfo
->StartingOffset
.QuadPart
< 0))
1218 status
= STATUS_NONEXISTENT_SECTOR
;
1223 ULONGLONG bytesRemaining
= fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
- verifyInfo
->StartingOffset
.QuadPart
;
1225 if ((ULONGLONG
)verifyInfo
->Length
> bytesRemaining
)
1227 status
= STATUS_NONEXISTENT_SECTOR
;
1236 srb
->CdbLength
= 10;
1238 cdb
->CDB10
.OperationCode
= SCSIOP_VERIFY
;
1241 // Add disk offset to starting sector.
1244 byteOffset
.QuadPart
= fdoExtension
->CommonExtension
.StartingOffset
.QuadPart
+
1245 verifyInfo
->StartingOffset
.QuadPart
;
1248 // Convert byte offset to sector offset.
1251 sectorOffset
= (ULONG
)(byteOffset
.QuadPart
>> fdoExtension
->SectorShift
);
1254 // Convert ULONG byte count to USHORT sector count.
1257 sectorCount
= (USHORT
)(verifyInfo
->Length
>> fdoExtension
->SectorShift
);
1260 // Move little endian values into CDB in big endian format.
1263 cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)§orOffset
)->Byte3
;
1264 cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)§orOffset
)->Byte2
;
1265 cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)§orOffset
)->Byte1
;
1266 cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)§orOffset
)->Byte0
;
1268 cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)§orCount
)->Byte1
;
1269 cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)§orCount
)->Byte0
;
1272 // The verify command is used by the NT FORMAT utility and
1273 // requests are sent down for 5% of the volume size. The
1274 // request timeout value is calculated based on the number of
1275 // sectors verified.
1278 srb
->TimeOutValue
= ((sectorCount
+ 0x7F) >> 7) *
1279 fdoExtension
->TimeOutValue
;
1281 status
= ClassSendSrbAsynchronous(DeviceObject
,
1291 case IOCTL_DISK_GET_PARTITION_INFO
: {
1293 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
) {
1295 USBFlopGetMediaTypes(DeviceObject
, NULL
);
1297 // Don't need to propagate any error if one occurs
1299 status
= STATUS_SUCCESS
;
1303 status
= DetermineMediaType(DeviceObject
);
1306 if (!NT_SUCCESS(status
)) {
1307 // so will propogate error
1309 } else if (fdoExtension
->DiskGeometry
.MediaType
== F3_120M_512
) {
1310 //so that the format code will not try to partition it.
1311 status
= STATUS_INVALID_DEVICE_REQUEST
;
1314 // Free the Srb, since it is not needed.
1320 // Pass the request to the common device control routine.
1323 return(ClassDeviceControl(DeviceObject
, Irp
));
1328 case IOCTL_DISK_GET_DRIVE_GEOMETRY
: {
1330 DebugPrint((3,"ScsiDeviceIoControl: Get drive geometry\n"));
1332 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
)
1334 status
= USBFlopGetMediaTypes(DeviceObject
,
1340 // If there's not enough room to write the
1341 // data, then fail the request.
1344 if ( irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1345 sizeof( DISK_GEOMETRY
) ) {
1347 status
= STATUS_INVALID_PARAMETER
;
1351 status
= DetermineMediaType(DeviceObject
);
1353 if (!NT_SUCCESS(status
)) {
1355 Irp
->IoStatus
.Information
= 0;
1356 Irp
->IoStatus
.Status
= status
;
1361 // Copy drive geometry information from device extension.
1364 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
,
1365 &(fdoExtension
->DiskGeometry
),
1366 sizeof(DISK_GEOMETRY
));
1368 Irp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
1369 status
= STATUS_SUCCESS
;
1376 case IOCTL_DISK_GET_MEDIA_TYPES
: {
1378 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
)
1380 status
= USBFlopGetMediaTypes(DeviceObject
,
1385 i
= DetermineDriveType(DeviceObject
);
1387 if (i
== DRIVE_TYPE_NONE
) {
1388 status
= STATUS_UNRECOGNIZED_MEDIA
;
1392 lowestDriveMediaType
= DriveMediaLimits
[i
].LowestDriveMediaType
;
1393 highestDriveMediaType
= DriveMediaLimits
[i
].HighestDriveMediaType
;
1395 outputBufferLength
=
1396 irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1399 // Make sure that the input buffer has enough room to return
1400 // at least one descriptions of a supported media type.
1403 if ( outputBufferLength
< ( sizeof( DISK_GEOMETRY
) ) ) {
1405 status
= STATUS_BUFFER_TOO_SMALL
;
1410 // Assume success, although we might modify it to a buffer
1411 // overflow warning below (if the buffer isn't big enough
1412 // to hold ALL of the media descriptions).
1415 status
= STATUS_SUCCESS
;
1417 if (outputBufferLength
< ( sizeof( DISK_GEOMETRY
) *
1418 ( highestDriveMediaType
- lowestDriveMediaType
+ 1 ) ) ) {
1421 // The buffer is too small for all of the descriptions;
1422 // calculate what CAN fit in the buffer.
1425 status
= STATUS_BUFFER_OVERFLOW
;
1427 highestDriveMediaType
= (DRIVE_MEDIA_TYPE
)( ( lowestDriveMediaType
- 1 ) +
1428 ( outputBufferLength
/
1429 sizeof( DISK_GEOMETRY
) ) );
1432 outputBuffer
= (PDISK_GEOMETRY
) Irp
->AssociatedIrp
.SystemBuffer
;
1434 for (i
= (UCHAR
)lowestDriveMediaType
;i
<= (UCHAR
)highestDriveMediaType
;i
++ ) {
1436 outputBuffer
->MediaType
= DriveMediaConstants
[i
].MediaType
;
1437 outputBuffer
->Cylinders
.LowPart
=
1438 DriveMediaConstants
[i
].MaximumTrack
+ 1;
1439 outputBuffer
->Cylinders
.HighPart
= 0;
1440 outputBuffer
->TracksPerCylinder
=
1441 DriveMediaConstants
[i
].NumberOfHeads
;
1442 outputBuffer
->SectorsPerTrack
=
1443 DriveMediaConstants
[i
].SectorsPerTrack
;
1444 outputBuffer
->BytesPerSector
=
1445 DriveMediaConstants
[i
].BytesPerSector
;
1448 Irp
->IoStatus
.Information
+= sizeof( DISK_GEOMETRY
);
1454 case IOCTL_DISK_FORMAT_TRACKS
: {
1456 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
)
1458 status
= USBFlopFormatTracks(DeviceObject
,
1464 // Make sure that we got all the necessary format parameters.
1467 if ( irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<sizeof( FORMAT_PARAMETERS
) ) {
1469 status
= STATUS_INVALID_PARAMETER
;
1473 formatParameters
= (PFORMAT_PARAMETERS
) Irp
->AssociatedIrp
.SystemBuffer
;
1476 // Make sure the parameters we got are reasonable.
1479 if ( !FlCheckFormatParameters(DeviceObject
, formatParameters
)) {
1481 status
= STATUS_INVALID_PARAMETER
;
1486 // If this request is for a 20.8 MB floppy then call a special
1487 // floppy format routine.
1490 if (formatParameters
->MediaType
== F3_20Pt8_512
) {
1491 status
= FlopticalFormatMedia(DeviceObject
,
1499 // All the work is done in the pass. If this is not the first pass,
1500 // then complete the request and return;
1503 if (formatParameters
->StartCylinderNumber
!= 0 || formatParameters
->StartHeadNumber
!= 0) {
1505 status
= STATUS_SUCCESS
;
1509 status
= FormatMedia( DeviceObject
, formatParameters
->MediaType
);
1513 case IOCTL_DISK_IS_WRITABLE
: {
1515 if ((fdoExtension
->DiskGeometry
.MediaType
) == F3_32M_512
) {
1518 // 32MB media is READ ONLY. Just return
1519 // STATUS_MEDIA_WRITE_PROTECTED
1522 status
= STATUS_MEDIA_WRITE_PROTECTED
;
1528 // Determine if the device is writable.
1531 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
1533 if (modeData
== NULL
) {
1534 status
= STATUS_INSUFFICIENT_RESOURCES
;
1538 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
1540 length
= ClassModeSense(DeviceObject
,
1543 MODE_SENSE_RETURN_ALL
);
1545 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1548 // Retry the request in case of a check condition.
1551 length
= ClassModeSense(DeviceObject
,
1554 MODE_SENSE_RETURN_ALL
);
1556 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1557 status
= STATUS_IO_DEVICE_ERROR
;
1558 ExFreePool(modeData
);
1563 if (modeData
->DeviceSpecificParameter
& MODE_DSP_WRITE_PROTECT
) {
1564 status
= STATUS_MEDIA_WRITE_PROTECTED
;
1566 status
= STATUS_SUCCESS
;
1569 DebugPrint((2,"IOCTL_DISK_IS_WRITABLE returns %08X\n", status
));
1571 ExFreePool(modeData
);
1577 DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n"));
1580 // Free the Srb, since it is not needed.
1586 // Pass the request to the common device control routine.
1589 return(ClassDeviceControl(DeviceObject
, Irp
));
1594 } // end switch( ...
1597 // Check if SL_OVERRIDE_VERIFY_VOLUME flag is set in the IRP.
1598 // If so, do not return STATUS_VERIFY_REQUIRED
1600 if ((status
== STATUS_VERIFY_REQUIRED
) &&
1601 (TEST_FLAG(irpStack
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
))) {
1603 status
= STATUS_IO_DEVICE_ERROR
;
1607 Irp
->IoStatus
.Status
= status
;
1609 if (!NT_SUCCESS(status
) && IoIsErrorUserInduced(status
)) {
1611 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1614 KeRaiseIrql(DISPATCH_LEVEL
, ¤tIrql
);
1615 ClassReleaseRemoveLock(DeviceObject
, Irp
);
1616 ClassCompleteRequest(DeviceObject
, Irp
, 0);
1617 KeLowerIrql(currentIrql
);
1623 } // end ScsiFlopDeviceControl()
1629 PDEVICE_OBJECT DeviceObject
1633 Routine Description:
1635 The routine performs the necessary funcitons to deterime if the device is
1636 really a floppy rather than a harddisk. This is done by a mode sense
1637 command. First a check is made to see if the medimum type is set. Second
1638 a check is made for the flexible parameters mode page.
1642 DeviceObject - Supplies the device object to be tested.
1646 Return TRUE if the indicated device is a floppy.
1655 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
1657 if (modeData
== NULL
) {
1661 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
1663 length
= ClassModeSense(DeviceObject
, modeData
, MODE_DATA_SIZE
, MODE_SENSE_RETURN_ALL
);
1665 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1668 // Retry the request in case of a check condition.
1671 length
= ClassModeSense(DeviceObject
,
1674 MODE_SENSE_RETURN_ALL
);
1676 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1678 ExFreePool(modeData
);
1686 // Some drives incorrectly report this. In particular the SONY RMO-S350
1687 // when in disk mode.
1690 if (((PMODE_PARAMETER_HEADER
) modeData
)->MediumType
>= MODE_FD_SINGLE_SIDE
1691 && ((PMODE_PARAMETER_HEADER
) modeData
)->MediumType
<= MODE_FD_MAXIMUM_TYPE
) {
1693 DebugPrint((1, "ScsiFlop: MediumType value %2x, This is a floppy.\n", ((PMODE_PARAMETER_HEADER
) modeData
)->MediumType
));
1694 ExFreePool(modeData
);
1701 // If the length is greater than length indiated by the mode data reset
1702 // the data to the mode data.
1704 if (length
> (ULONG
)((PMODE_PARAMETER_HEADER
) modeData
)->ModeDataLength
+ 1) {
1705 length
= (ULONG
)((PMODE_PARAMETER_HEADER
) modeData
)->ModeDataLength
+ 1;
1710 // Look for the flexible disk mode page.
1713 pageData
= ClassFindModePage( modeData
, length
, MODE_PAGE_FLEXIBILE
, TRUE
);
1715 if (pageData
!= NULL
) {
1717 DebugPrint((1, "ScsiFlop: Flexible disk page found, This is a floppy.\n"));
1720 // As a special case for the floptical driver do a magic mode sense to
1721 // enable the drive.
1724 ClassModeSense(DeviceObject
, modeData
, 0x2a, 0x2e);
1726 ExFreePool(modeData
);
1731 ExFreePool(modeData
);
1740 PDEVICE_OBJECT DeviceObject
1744 Routine Description:
1746 This routine determines the floppy media type based on the size of the
1747 device. The geometry information is set for the device object.
1751 DeviceObject - Supplies the device object to be tested.
1759 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1760 PDISK_GEOMETRY geometry
;
1766 geometry
= &(fdoExtension
->DiskGeometry
);
1769 // Issue ReadCapacity to update device extension
1770 // with information for current media.
1773 status
= ClassReadDriveCapacity(DeviceObject
);
1775 if (!NT_SUCCESS(status
)) {
1778 // Set the media type to unknow and zero the geometry information.
1781 geometry
->MediaType
= Unknown
;
1788 // Look at the capcity of disk to determine its type.
1791 for (index
= NUMBER_OF_DRIVE_MEDIA_COMBINATIONS
- 1; index
>= 0; index
--) {
1794 // Walk the table backward untill the drive capacity holds all of the
1795 // data and the bytes per setor are equal
1798 if ((ULONG
) (DriveMediaConstants
[index
].NumberOfHeads
*
1799 (DriveMediaConstants
[index
].MaximumTrack
+ 1) *
1800 DriveMediaConstants
[index
].SectorsPerTrack
*
1801 DriveMediaConstants
[index
].BytesPerSector
) <=
1802 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
&&
1803 DriveMediaConstants
[index
].BytesPerSector
==
1804 geometry
->BytesPerSector
) {
1806 geometry
->MediaType
= DriveMediaConstants
[index
].MediaType
;
1807 geometry
->TracksPerCylinder
= DriveMediaConstants
[index
].NumberOfHeads
;
1808 geometry
->SectorsPerTrack
= DriveMediaConstants
[index
].SectorsPerTrack
;
1809 geometry
->Cylinders
.LowPart
= DriveMediaConstants
[index
].MaximumTrack
+1;
1817 // Set the media type to unknow and zero the geometry information.
1820 geometry
->MediaType
= Unknown
;
1825 // DMF check breaks the insight SCSI floppy, so its disabled for that case
1827 PDISK_DATA diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
1829 // if (diskData->EnableDMF == TRUE) {
1832 //check to see if DMF
1835 PSCSI_REQUEST_BLOCK srb
;
1839 // Allocate a Srb for the read command.
1842 readData
= ExAllocatePool(NonPagedPoolNx
, geometry
->BytesPerSector
);
1843 if (readData
== NULL
) {
1844 return STATUS_NO_MEMORY
;
1847 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
1851 ExFreePool(readData
);
1852 return STATUS_NO_MEMORY
;
1855 RtlZeroMemory(readData
, geometry
->BytesPerSector
);
1856 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
1858 srb
->CdbLength
= 10;
1859 srb
->Cdb
[0] = SCSIOP_READ
;
1861 srb
->Cdb
[8] = (UCHAR
) 1;
1864 // Set timeout value.
1867 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
1870 // Send the mode select data.
1873 status
= ClassSendSrbSynchronous(DeviceObject
,
1876 geometry
->BytesPerSector
,
1880 if (NT_SUCCESS(status
)) {
1881 char *pchar
= (char *)readData
;
1883 pchar
+= 3; //skip 3 bytes jump code
1885 // If the MSDMF3. signature is there then mark it as DMF diskette
1886 if (RtlCompareMemory(pchar
, "MSDMF3.", 7) == 7) {
1887 diskData
->IsDMF
= TRUE
;
1891 ExFreePool(readData
);
1900 PDEVICE_OBJECT DeviceObject
1904 Routine Description:
1906 The routine determines the device type so that the supported medias can be
1907 determined. It does a mode sense for the default parameters. This code
1908 assumes that the returned values are for the maximum device size.
1912 DeviceObject - Supplies the device object to be tested.
1920 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1922 PDISK_DATA diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
1923 PMODE_FLEXIBLE_DISK_PAGE pageData
;
1926 UCHAR numberOfHeads
;
1927 UCHAR sectorsPerTrack
;
1928 USHORT maximumTrack
;
1929 BOOLEAN applyFix
= FALSE
;
1933 if (diskData
->DriveType
!= DRIVE_TYPE_NONE
) {
1934 return(diskData
->DriveType
);
1937 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
1939 if (modeData
== NULL
) {
1940 return(DRIVE_TYPE_NONE
);
1943 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
1945 length
= ClassModeSense(DeviceObject
,
1948 MODE_PAGE_FLEXIBILE
);
1950 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1953 // Retry the request one more time
1954 // in case of a check condition.
1956 length
= ClassModeSense(DeviceObject
,
1959 MODE_PAGE_FLEXIBILE
);
1961 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1963 ExFreePool(modeData
);
1964 return(DRIVE_TYPE_NONE
);
1969 // Look for the flexible disk mode page.
1972 pageData
= ClassFindModePage( modeData
,
1974 MODE_PAGE_FLEXIBILE
,
1978 // Make sure the page is returned and is large enough.
1981 if ((pageData
!= NULL
) &&
1982 (pageData
->PageLength
+ 2 >=
1983 (UCHAR
)offsetof(MODE_FLEXIBLE_DISK_PAGE
, StartWritePrecom
))) {
1986 // Pull out the heads, cylinders, and sectors.
1989 numberOfHeads
= pageData
->NumberOfHeads
;
1990 maximumTrack
= pageData
->NumberOfCylinders
[1];
1991 maximumTrack
|= pageData
->NumberOfCylinders
[0] << 8;
1992 sectorsPerTrack
= pageData
->SectorsPerTrack
;
1996 // Convert from number of cylinders to maximum track.
2002 // Search for the maximum supported media. Based on the number of heads,
2003 // sectors per track and number of cylinders
2005 for (index
= 0; index
< NUMBER_OF_DRIVE_MEDIA_COMBINATIONS
; index
++) {
2008 // Walk the table forward until the drive capacity holds all of the
2009 // data and the bytes per setor are equal
2012 if (DriveMediaConstants
[index
].NumberOfHeads
== numberOfHeads
&&
2013 DriveMediaConstants
[index
].MaximumTrack
== maximumTrack
&&
2014 DriveMediaConstants
[index
].SectorsPerTrack
==sectorsPerTrack
) {
2016 ExFreePool(modeData
);
2019 // index is now a drive media combination. Compare this to
2020 // the maximum drive media type in the drive media table.
2023 for (length
= 0; length
< NUMBER_OF_DRIVE_TYPES
; length
++) {
2025 if (DriveMediaLimits
[length
].HighestDriveMediaType
== index
) {
2029 return(DRIVE_TYPE_NONE
);
2033 // If the maximum track is greater than 8 bits then divide the
2034 // number of tracks by 3 and multiply the number of heads by 3.
2035 // This is a special case for the 20.8 MB floppy.
2038 if (!applyFix
&& maximumTrack
>= 0x0100) {
2044 ExFreePool(modeData
);
2045 return(DRIVE_TYPE_NONE
);
2050 ExFreePool(modeData
);
2051 return(DRIVE_TYPE_NONE
);
2056 FlCheckFormatParameters(
2057 IN PDEVICE_OBJECT DeviceObject
,
2058 IN PFORMAT_PARAMETERS FormatParameters
2063 Routine Description:
2065 This routine checks the supplied format parameters to make sure that
2066 they'll work on the drive to be formatted.
2070 DeviceObject - Pointer to the device object to be formated.
2072 FormatParameters - a pointer to the caller's parameters for the FORMAT.
2076 TRUE if parameters are OK.
2077 FALSE if the parameters are bad.
2082 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2083 DRIVE_MEDIA_TYPE driveMediaType
;
2089 // Get the device type.
2092 index
= DetermineDriveType(DeviceObject
);
2094 if (index
== DRIVE_TYPE_NONE
) {
2097 // If the determine device type failed then just use the media type
2098 // and try the parameters.
2101 driveMediaType
= Drive360Media160
;
2103 while (( DriveMediaConstants
[driveMediaType
].MediaType
!=
2104 FormatParameters
->MediaType
) &&
2105 ( driveMediaType
< Drive288Media288
) ) {
2113 // Figure out which entry in the DriveMediaConstants table to use.
2117 DriveMediaLimits
[index
].HighestDriveMediaType
;
2119 while ( ( DriveMediaConstants
[driveMediaType
].MediaType
!=
2120 FormatParameters
->MediaType
) &&
2121 ( driveMediaType
> DriveMediaLimits
[index
].
2122 LowestDriveMediaType
) ) {
2130 // driveMediaType is bounded below by DriveMediaLimits[].LowestDriveMediaType
2131 #if !defined(__REACTOS__) || defined(_MSC_VER)
2132 #pragma warning(push)
2133 #pragma warning(disable:33010) // 33010: Enum used as array index may be negative
2135 if ( DriveMediaConstants
[driveMediaType
].MediaType
!=
2136 FormatParameters
->MediaType
) {
2141 driveMediaConstants
= &DriveMediaConstants
[driveMediaType
];
2143 if ( ( FormatParameters
->StartHeadNumber
>
2144 (ULONG
)( driveMediaConstants
->NumberOfHeads
- 1 ) ) ||
2145 ( FormatParameters
->EndHeadNumber
>
2146 (ULONG
)( driveMediaConstants
->NumberOfHeads
- 1 ) ) ||
2147 ( FormatParameters
->StartCylinderNumber
>
2148 driveMediaConstants
->MaximumTrack
) ||
2149 ( FormatParameters
->EndCylinderNumber
>
2150 driveMediaConstants
->MaximumTrack
) ||
2151 ( FormatParameters
->EndCylinderNumber
<
2152 FormatParameters
->StartCylinderNumber
) ) {
2161 #if !defined(__REACTOS__) || defined(_MSC_VER)
2162 #pragma warning(pop)
2168 PDEVICE_OBJECT DeviceObject
,
2169 MEDIA_TYPE MediaType
2173 Routine Description:
2175 This routine formats the floppy disk. The entire floppy is formated in
2180 DeviceObject - Supplies the device object to be tested.
2182 Irp - Supplies a pointer to the requesting Irp.
2184 MediaType - Supplies the media type format the device for.
2188 Returns a status for the operation.
2193 PSCSI_REQUEST_BLOCK srb
;
2194 PMODE_FLEXIBLE_DISK_PAGE pageData
;
2195 DRIVE_MEDIA_TYPE driveMediaType
;
2196 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2202 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
2204 if (modeData
== NULL
) {
2205 return(STATUS_INSUFFICIENT_RESOURCES
);
2208 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
2210 length
= ClassModeSense(DeviceObject
,
2213 MODE_PAGE_FLEXIBILE
);
2215 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
2216 ExFreePool(modeData
);
2217 return(STATUS_INVALID_DEVICE_REQUEST
);
2221 // Look for the flexible disk mode page.
2224 pageData
= ClassFindModePage( modeData
, length
, MODE_PAGE_FLEXIBILE
, TRUE
);
2227 // Make sure the page is returned and is large enough.
2230 if ((pageData
== NULL
) ||
2231 (pageData
->PageLength
+ 2 <
2232 (UCHAR
)offsetof(MODE_FLEXIBLE_DISK_PAGE
, StartWritePrecom
))) {
2234 ExFreePool(modeData
);
2235 return(STATUS_INVALID_DEVICE_REQUEST
);
2240 // Look for a drive media type which matches the requested media type.
2243 //start from Drive120MMedia120M instead of Drive2080Media2080
2245 for (driveMediaType
= Drive120MMedia120M
;
2246 DriveMediaConstants
[driveMediaType
].MediaType
!= MediaType
;
2248 if (driveMediaType
== Drive360Media160
) {
2250 ExFreePool(modeData
);
2251 return(STATUS_INVALID_PARAMETER
);
2256 driveMediaConstants
= &DriveMediaConstants
[driveMediaType
];
2258 if ((pageData
->NumberOfHeads
!= driveMediaConstants
->NumberOfHeads
) ||
2259 (pageData
->SectorsPerTrack
!= driveMediaConstants
->SectorsPerTrack
) ||
2260 ((pageData
->NumberOfCylinders
[0] != (UCHAR
)((driveMediaConstants
->MaximumTrack
+1) >> 8)) &&
2261 (pageData
->NumberOfCylinders
[1] != (UCHAR
)driveMediaConstants
->MaximumTrack
+1)) ||
2262 (pageData
->BytesPerSector
[0] != driveMediaConstants
->BytesPerSector
>> 8 )) {
2265 // Update the flexible parameters page with the new parameters.
2268 pageData
->NumberOfHeads
= driveMediaConstants
->NumberOfHeads
;
2269 pageData
->SectorsPerTrack
= driveMediaConstants
->SectorsPerTrack
;
2270 pageData
->NumberOfCylinders
[0] = (UCHAR
)((driveMediaConstants
->MaximumTrack
+1) >> 8);
2271 pageData
->NumberOfCylinders
[1] = (UCHAR
)driveMediaConstants
->MaximumTrack
+1;
2272 pageData
->BytesPerSector
[0] = driveMediaConstants
->BytesPerSector
>> 8;
2275 // Clear the mode parameter header.
2278 RtlZeroMemory(modeData
, sizeof(MODE_PARAMETER_HEADER
));
2281 // Set the length equal to the length returned for the flexible page.
2284 length
= pageData
->PageLength
+ 2;
2287 // Copy the page after the mode parameter header.
2290 RtlMoveMemory((PCHAR
) modeData
+ sizeof(MODE_PARAMETER_HEADER
),
2294 length
+= sizeof(MODE_PARAMETER_HEADER
);
2298 // Allocate a Srb for the format command.
2301 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
2305 ExFreePool(modeData
);
2306 return(STATUS_INSUFFICIENT_RESOURCES
);
2309 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2312 srb
->Cdb
[0] = SCSIOP_MODE_SELECT
;
2313 srb
->Cdb
[4] = (UCHAR
) length
;
2319 srb
->Cdb
[1] |= 0x10;
2322 // Set timeout value.
2325 srb
->TimeOutValue
= 2;
2328 // Send the mode select data.
2331 status
= ClassSendSrbSynchronous(DeviceObject
,
2339 // The mode data not needed any more so free it.
2342 ExFreePool(modeData
);
2344 if (!NT_SUCCESS(status
)) {
2352 // The mode data not needed any more so free it.
2355 ExFreePool(modeData
);
2358 // Allocate a Srb for the format command.
2361 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
2364 return(STATUS_INSUFFICIENT_RESOURCES
);
2369 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2373 srb
->Cdb
[0] = SCSIOP_FORMAT_UNIT
;
2376 // Set timeout value.
2379 srb
->TimeOutValue
= 10 * 60;
2381 status
= ClassSendSrbSynchronous(DeviceObject
,
2397 ScsiFlopProcessError(
2398 PDEVICE_OBJECT DeviceObject
,
2399 PSCSI_REQUEST_BLOCK Srb
,
2405 Routine Description:
2407 This routine checks the type of error. If the error indicate the floppy
2408 controller needs to be reinitialize a command is made to do it.
2412 DeviceObject - Supplies a pointer to the device object.
2414 Srb - Supplies a pointer to the failing Srb.
2416 Status - Status with which the IRP will be completed.
2418 Retry - Indication of whether the request will be retried.
2427 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
2428 PDISK_DATA diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
2429 PSENSE_DATA senseBuffer
= Srb
->SenseInfoBuffer
;
2430 PIO_STACK_LOCATION irpStack
;
2432 PSCSI_REQUEST_BLOCK srb
;
2433 LARGE_INTEGER largeInt
;
2434 PCOMPLETION_CONTEXT context
;
2436 ULONG_PTR alignment
;
2437 ULONG majorFunction
;
2439 UNREFERENCED_PARAMETER(Status
);
2440 UNREFERENCED_PARAMETER(Retry
);
2442 largeInt
.QuadPart
= 1;
2445 // Check the status. The initialization command only needs to be sent
2446 // if UNIT ATTENTION or LUN NOT READY is returned.
2449 if (!(Srb
->SrbStatus
& SRB_STATUS_AUTOSENSE_VALID
)) {
2452 // The drive does not require reinitialization.
2459 // Reset the drive type.
2462 diskData
->DriveType
= DRIVE_TYPE_NONE
;
2463 diskData
->IsDMF
= FALSE
;
2465 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
2467 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
) {
2469 // FLPYDISK.SYS never returns a non-zero value for the ChangeCount
2470 // on an IOCTL_DISK_CHECK_VERIFY. Some things seem to work better
2471 // if we do the same. In particular, FatVerifyVolume() can exit between
2472 // the IOCTL_DISK_CHECK_VERIFY and the IOCTL_DISK_GET_DRIVE_GEOMETRY
2473 // if a non-zero ChangeCount is returned, and this appears to cause
2474 // issues formatting unformatted media in some situations.
2476 // This is something that should probably be revisited at some point.
2478 fdoExtension
->MediaChangeCount
= 0;
2480 if (((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) &&
2481 (senseBuffer
->AdditionalSenseCode
== SCSI_ADSENSE_MEDIUM_CHANGED
)) {
2483 struct _START_STOP
*startStopCdb
;
2485 DebugPrint((2,"Sending SCSIOP_START_STOP_UNIT\n"));
2487 context
= ExAllocatePool(NonPagedPoolNx
,
2488 sizeof(COMPLETION_CONTEXT
));
2490 if (context
== NULL
) {
2494 #if (NTDDI_VERSION >= NTDDI_WIN8)
2495 srb
= &context
->Srb
.Srb
;
2497 srb
= &context
->Srb
;
2500 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2502 srb
->SrbFlags
= SRB_FLAGS_DISABLE_AUTOSENSE
;
2506 startStopCdb
= (struct _START_STOP
*)srb
->Cdb
;
2508 startStopCdb
->OperationCode
= SCSIOP_START_STOP_UNIT
;
2509 startStopCdb
->Start
= 1;
2511 // A Start Stop Unit request has no transfer buffer.
2512 // Set the request to IRP_MJ_FLUSH_BUFFERS when calling
2513 // IoBuildAsynchronousFsdRequest() so that it ignores
2514 // the buffer pointer and buffer length parameters.
2516 majorFunction
= IRP_MJ_FLUSH_BUFFERS
;
2518 } else if ((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_MEDIUM_ERROR
) {
2520 // Return ERROR_UNRECOGNIZED_MEDIA instead of
2521 // STATUS_DEVICE_DATA_ERROR to make shell happy.
2523 *Status
= STATUS_UNRECOGNIZED_MEDIA
;
2532 } else if (((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_NOT_READY
) &&
2533 senseBuffer
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_INIT_COMMAND_REQUIRED
||
2534 (senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) {
2536 } else if ((((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_NOT_READY
) &&
2537 senseBuffer
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_INIT_COMMAND_REQUIRED
) ||
2538 (senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) {
2545 DebugPrint((1, "ScsiFlopProcessError: Reinitializing the floppy.\n"));
2548 // Send the special mode sense command to enable writes on the
2552 alignment
= DeviceObject
->AlignmentRequirement
?
2553 DeviceObject
->AlignmentRequirement
: 1;
2557 if (SUCCEEDED(ULongAdd(sizeof(COMPLETION_CONTEXT
), 0x2a, &tmpSize
))) {
2559 if (SUCCEEDED(ULongAdd(tmpSize
, (ULONG
) alignment
, &sizeNeeded
))) {
2567 context
= ExAllocatePool(NonPagedPoolNx
, sizeNeeded
);
2570 if (context
== NULL
) {
2573 // If there is not enough memory to fulfill this request,
2574 // simply return. A subsequent retry will fail and another
2575 // chance to start the unit.
2581 #if (NTDDI_VERSION >= NTDDI_WIN8)
2582 srb
= &context
->Srb
.Srb
;
2584 srb
= &context
->Srb
;
2587 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2590 // Set the transfer length.
2593 srb
->DataTransferLength
= 0x2a;
2594 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_AUTOSENSE
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2597 // The data buffer must be aligned.
2600 srb
->DataBuffer
= (PVOID
) (((ULONG_PTR
) (context
+ 1) + (alignment
- 1)) &
2605 // Build the start unit CDB.
2609 cdb
= (PCDB
)srb
->Cdb
;
2610 cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
2611 cdb
->MODE_SENSE
.PageCode
= 0x2e;
2612 cdb
->MODE_SENSE
.AllocationLength
= 0x2a;
2614 majorFunction
= IRP_MJ_READ
;
2621 context
->DeviceObject
= DeviceObject
;
2624 // Write length to SRB.
2627 srb
->Length
= SCSI_REQUEST_BLOCK_SIZE
;
2629 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2630 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
2633 // Build the asynchronous request
2634 // to be sent to the port driver.
2637 irp
= IoBuildAsynchronousFsdRequest(majorFunction
,
2640 srb
->DataTransferLength
,
2645 ExFreePool(context
);
2650 IoSetCompletionRoutine(irp
,
2651 (PIO_COMPLETION_ROUTINE
)ClassAsynchronousCompletion
,
2657 ClassAcquireRemoveLock(DeviceObject
, irp
);
2659 irpStack
= IoGetNextIrpStackLocation(irp
);
2661 irpStack
->MajorFunction
= IRP_MJ_SCSI
;
2663 srb
->OriginalRequest
= irp
;
2666 // Save SRB address in next stack for port driver.
2669 irpStack
->Parameters
.Others
.Argument1
= (PVOID
)srb
;
2672 // Can't release the remove lock yet - let ClassAsynchronousCompletion
2673 // take care of that for us.
2676 (VOID
)IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, irp
);
2682 FlopticalFormatMedia(
2683 PDEVICE_OBJECT DeviceObject
,
2684 PFORMAT_PARAMETERS Format
2688 Routine Description:
2690 This routine is used to do perform a format tracks for the 20.8 MB
2691 floppy. Because the device does not support format tracks and the full
2692 format takes a long time a write of zeros is done instead.
2696 DeviceObject - Supplies the device object to be tested.
2698 Format - Supplies the format parameters.
2702 Returns a status for the operation.
2706 IO_STATUS_BLOCK ioStatus
;
2709 LARGE_INTEGER offset
;
2712 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2717 driveMediaConstants
= &DriveMediaConstants
[Drive2080Media2080
];
2720 // Calculate the length of the buffer.
2723 length
= ((Format
->EndCylinderNumber
- Format
->StartCylinderNumber
) *
2724 driveMediaConstants
->NumberOfHeads
+
2725 Format
->EndHeadNumber
- Format
->StartHeadNumber
+ 1) *
2726 driveMediaConstants
->SectorsPerTrack
*
2727 driveMediaConstants
->BytesPerSector
;
2729 buffer
= ExAllocatePool(NonPagedPoolNxCacheAligned
, length
);
2731 if (buffer
== NULL
) {
2732 return(STATUS_INSUFFICIENT_RESOURCES
);
2735 RtlZeroMemory(buffer
, length
);
2738 (Format
->StartCylinderNumber
* driveMediaConstants
->NumberOfHeads
+
2739 Format
->StartHeadNumber
) * driveMediaConstants
->SectorsPerTrack
*
2740 driveMediaConstants
->BytesPerSector
;
2743 // Set the event object to the unsignaled state.
2744 // It will be used to signal request completion.
2747 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
2750 // Build the synchronous request with data transfer.
2753 irp
= IoBuildSynchronousFsdRequest(
2763 status
= IoCallDriver(DeviceObject
, irp
);
2765 if (status
== STATUS_PENDING
) {
2768 // Wait for the request to complete if necessary.
2771 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
2775 // If the call driver suceeded then set the status to the status block.
2778 if (NT_SUCCESS(status
)) {
2779 status
= ioStatus
.Status
;
2782 status
= STATUS_INSUFFICIENT_RESOURCES
;
2796 ScsiFlopRemoveDevice(
2797 IN PDEVICE_OBJECT DeviceObject
,
2802 Routine Description:
2804 This routine is responsible for releasing any resources in use by the
2805 sfloppy driver. This routine is called
2806 when all outstanding requests have been completed and the driver has
2807 disappeared - no requests may be issued to the lower drivers.
2811 DeviceObject - the device object being removed
2813 Type - the type of remove operation (QUERY, REMOVE or CANCEL)
2817 for a query - success if the device can be removed or a failure code
2818 indiciating why not.
2820 for a remove or cancel - STATUS_SUCCESS
2825 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension
=
2826 DeviceObject
->DeviceExtension
;
2827 PDISK_DATA diskData
= deviceExtension
->CommonExtension
.DriverData
;
2832 if((Type
== IRP_MN_QUERY_REMOVE_DEVICE
) ||
2833 (Type
== IRP_MN_CANCEL_REMOVE_DEVICE
)) {
2834 return STATUS_SUCCESS
;
2837 if (Type
== IRP_MN_REMOVE_DEVICE
){
2838 if(deviceExtension
->DeviceDescriptor
) {
2839 ExFreePool(deviceExtension
->DeviceDescriptor
);
2840 deviceExtension
->DeviceDescriptor
= NULL
;
2843 if(deviceExtension
->AdapterDescriptor
) {
2844 ExFreePool(deviceExtension
->AdapterDescriptor
);
2845 deviceExtension
->AdapterDescriptor
= NULL
;
2848 if(deviceExtension
->SenseData
) {
2849 ExFreePool(deviceExtension
->SenseData
);
2850 deviceExtension
->SenseData
= NULL
;
2853 ClassDeleteSrbLookasideList(&deviceExtension
->CommonExtension
);
2856 if(diskData
->FloppyInterfaceString
.Buffer
!= NULL
) {
2858 status
= IoSetDeviceInterfaceState(
2859 &(diskData
->FloppyInterfaceString
),
2862 if (!NT_SUCCESS(status
)) {
2863 // Failed to disable device interface during removal. Not a fatal error.
2864 DebugPrint((1, "ScsiFlopRemoveDevice: Unable to set device "
2865 "interface state to FALSE for fdo %p "
2867 DeviceObject
, status
));
2870 RtlFreeUnicodeString(&(diskData
->FloppyInterfaceString
));
2871 RtlInitUnicodeString(&(diskData
->FloppyInterfaceString
), NULL
);
2874 if(Type
== IRP_MN_REMOVE_DEVICE
) {
2875 IoGetConfigurationInformation()->FloppyCount
--;
2878 return STATUS_SUCCESS
;
2887 IN PDEVICE_OBJECT DeviceObject
,
2891 UNREFERENCED_PARAMETER(DeviceObject
);
2892 UNREFERENCED_PARAMETER(Type
);
2894 return STATUS_SUCCESS
;
2899 USBFlopGetMediaTypes(
2900 IN PDEVICE_OBJECT DeviceObject
,
2906 Routine Description:
2908 This routines determines the current or default geometry of the drive
2909 for IOCTL_DISK_GET_DRIVE_GEOMETRY, or all currently supported geometries
2910 of the drive (which is determined by its currently inserted media) for
2911 IOCTL_DISK_GET_MEDIA_TYPES.
2913 The returned geometries are determined by issuing a Read Format Capacities
2914 request and then matching the returned {Number of Blocks, Block Length}
2915 pairs in a table of known floppy geometries.
2919 DeviceObject - Supplies the device object.
2921 Irp - A IOCTL_DISK_GET_DRIVE_GEOMETRY or a IOCTL_DISK_GET_MEDIA_TYPES Irp.
2922 If NULL, the device geometry is updated with the current device
2930 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
2931 PIO_STACK_LOCATION irpStack
;
2932 ULONG ioControlCode
;
2933 PDISK_GEOMETRY outputBuffer
;
2934 PDISK_GEOMETRY outputBufferEnd
;
2935 ULONG outputBufferLength
;
2936 PSCSI_REQUEST_BLOCK srb
;
2938 ULONG dataTransferLength
;
2939 struct _READ_FORMATTED_CAPACITIES
*cdb
;
2940 PFORMATTED_CAPACITY_LIST capList
;
2945 fdoExtension
= DeviceObject
->DeviceExtension
;
2949 // Get the Irp parameters
2951 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
2953 ioControlCode
= irpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
2955 Irp
->IoStatus
.Information
= 0;
2957 outputBuffer
= (PDISK_GEOMETRY
) Irp
->AssociatedIrp
.SystemBuffer
;
2959 outputBufferLength
= irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2961 if (outputBufferLength
< sizeof(DISK_GEOMETRY
))
2963 return STATUS_BUFFER_TOO_SMALL
;
2966 // Pointer arithmetic to allow multiple DISK_GEOMETRY's to be returned.
2967 // Rounds BufferEnd down to integral multiple of DISK_GEOMETRY structs.
2969 outputBufferEnd
= outputBuffer
+
2970 outputBufferLength
/ sizeof(DISK_GEOMETRY
);
2974 // No Irp to return the result in, just update the current geometry
2975 // in the device extension.
2977 ioControlCode
= IOCTL_DISK_GET_DRIVE_GEOMETRY
;
2979 outputBuffer
= NULL
;
2981 outputBufferEnd
= NULL
;
2983 outputBufferLength
= 0;
2986 if (ioControlCode
== IOCTL_DISK_GET_DRIVE_GEOMETRY
) {
2988 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
2990 status
= ClassReadDriveCapacity(DeviceObject
);
2992 if (!NT_SUCCESS(status
))
2994 // If the media is not recongized, we want to return the default
2995 // geometry so that the media can be formatted. Unrecognized media
2996 // causes SCSI_SENSE_MEDIUM_ERROR, which gets reported as
2997 // STATUS_DEVICE_DATA_ERROR. Ignore these errors, but return other
2998 // errors, such as STATUS_NO_MEDIA_IN_DEVICE.
3000 if (status
!= STATUS_UNRECOGNIZED_MEDIA
)
3002 DebugPrint((2,"IOCTL_DISK_GET_DRIVE_GEOMETRY returns %08X\n", status
));
3009 // Allocate an SRB for the SCSIOP_READ_FORMATTED_CAPACITY request
3011 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
3015 return STATUS_INSUFFICIENT_RESOURCES
;
3018 // Allocate a transfer buffer for the SCSIOP_READ_FORMATTED_CAPACITY request
3019 // The length of the returned descriptor array is limited to a byte field
3020 // in the capacity list header.
3022 dataTransferLength
= sizeof(FORMATTED_CAPACITY_LIST
) +
3023 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3025 ASSERT(dataTransferLength
< 0x100);
3027 dataBuffer
= ExAllocatePool(NonPagedPoolNx
, dataTransferLength
);
3029 if (dataBuffer
== NULL
)
3032 return STATUS_INSUFFICIENT_RESOURCES
;
3035 // Initialize the SRB and CDB
3037 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
3039 RtlZeroMemory(dataBuffer
, dataTransferLength
);
3041 srb
->CdbLength
= sizeof(struct _READ_FORMATTED_CAPACITIES
);
3043 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3045 cdb
= (struct _READ_FORMATTED_CAPACITIES
*)srb
->Cdb
;
3047 cdb
->OperationCode
= SCSIOP_READ_FORMATTED_CAPACITY
;
3048 cdb
->AllocationLength
[1] = (UCHAR
)dataTransferLength
;
3051 // Send down the SCSIOP_READ_FORMATTED_CAPACITY request
3053 status
= ClassSendSrbSynchronous(DeviceObject
,
3059 capList
= (PFORMATTED_CAPACITY_LIST
)dataBuffer
;
3061 // If we don't get as much data as requested, it is not an error.
3063 if (SRB_STATUS(srb
->SrbStatus
) == SRB_STATUS_DATA_OVERRUN
)
3065 status
= STATUS_SUCCESS
;
3068 if (NT_SUCCESS(status
) &&
3069 srb
->DataTransferLength
>= sizeof(FORMATTED_CAPACITY_LIST
) &&
3070 capList
->CapacityListLength
&&
3071 capList
->CapacityListLength
% sizeof(FORMATTED_CAPACITY_DESCRIPTOR
) == 0)
3073 ULONG NumberOfBlocks
;
3077 LONG currentGeometry
;
3078 BOOLEAN capacityMatches
[FLOPPY_CAPACITIES
];
3080 // Subtract the size of the Capacity List Header to get
3081 // just the size of the Capacity List Descriptor array.
3083 srb
->DataTransferLength
-= sizeof(FORMATTED_CAPACITY_LIST
);
3085 // Only look at the Capacity List Descriptors that were actually
3088 if (srb
->DataTransferLength
< capList
->CapacityListLength
)
3090 count
= srb
->DataTransferLength
/
3091 sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3095 count
= capList
->CapacityListLength
/
3096 sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3099 // Updated only if a match is found for the first Capacity List
3100 // Descriptor returned by the device.
3102 currentGeometry
= -1;
3104 // Initialize the array of capacities that hit a match.
3106 RtlZeroMemory(capacityMatches
, sizeof(capacityMatches
));
3108 // Iterate over each Capacity List Descriptor returned from the device
3109 // and record matching capacities in the capacity match array.
3111 for (i
= 0; i
< count
; i
++)
3113 NumberOfBlocks
= (capList
->Descriptors
[i
].NumberOfBlocks
[0] << 24) +
3114 (capList
->Descriptors
[i
].NumberOfBlocks
[1] << 16) +
3115 (capList
->Descriptors
[i
].NumberOfBlocks
[2] << 8) +
3116 (capList
->Descriptors
[i
].NumberOfBlocks
[3]);
3118 BlockLength
= (capList
->Descriptors
[i
].BlockLength
[0] << 16) +
3119 (capList
->Descriptors
[i
].BlockLength
[1] << 8) +
3120 (capList
->Descriptors
[i
].BlockLength
[2]);
3122 // Given the {NumberOfBlocks, BlockLength} from this Capacity List
3123 // Descriptor, find a matching entry in FloppyCapacities[].
3125 for (j
= 0; j
< FLOPPY_CAPACITIES
; j
++)
3127 if (NumberOfBlocks
== FloppyCapacities
[j
].NumberOfBlocks
&&
3128 BlockLength
== FloppyCapacities
[j
].BlockLength
)
3130 // A matching capacity was found, record it.
3132 capacityMatches
[j
] = TRUE
;
3134 // A match was found for the first Capacity List
3135 // Descriptor returned by the device.
3139 currentGeometry
= j
;
3141 } else if ((capList
->Descriptors
[i
].Valid
) &&
3142 (BlockLength
== FloppyCapacities
[j
].BlockLength
)) {
3148 // Check if this is 32MB media type. 32MB media
3149 // reports variable NumberOfBlocks. So we cannot
3150 // use that to determine the drive type
3152 inx
= DetermineDriveType(DeviceObject
);
3153 if (inx
!= DRIVE_TYPE_NONE
) {
3154 mediaInx
= DriveMediaLimits
[inx
].HighestDriveMediaType
;
3155 if ((DriveMediaConstants
[mediaInx
].MediaType
)
3157 capacityMatches
[j
] = TRUE
;
3160 currentGeometry
= j
;
3168 // Default status is STATUS_UNRECOGNIZED_MEDIA, unless we return
3169 // either STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW.
3171 status
= STATUS_UNRECOGNIZED_MEDIA
;
3173 if (ioControlCode
== IOCTL_DISK_GET_DRIVE_GEOMETRY
) {
3175 if (currentGeometry
!= -1)
3177 // Update the current device geometry
3179 fdoExtension
->DiskGeometry
= FloppyGeometries
[currentGeometry
];
3182 // Calculate sector to byte shift.
3185 WHICH_BIT(fdoExtension
->DiskGeometry
.BytesPerSector
,
3186 fdoExtension
->SectorShift
);
3188 fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
=
3189 (LONGLONG
)FloppyCapacities
[currentGeometry
].NumberOfBlocks
*
3190 FloppyCapacities
[currentGeometry
].BlockLength
;
3192 DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n",
3193 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3194 fdoExtension
->DiskGeometry
.MediaType
,
3195 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3196 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3197 fdoExtension
->DiskGeometry
.BytesPerSector
,
3198 fdoExtension
->SectorShift
,
3199 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3201 // Return the current device geometry
3205 *outputBuffer
= FloppyGeometries
[currentGeometry
];
3207 Irp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
3210 status
= STATUS_SUCCESS
;
3215 // Iterate over the capacities and return the geometry
3216 // corresponding to each matching Capacity List Descriptor
3217 // returned from the device.
3219 // The resulting list should be in sorted ascending order,
3220 // assuming that the FloppyGeometries[] array is in sorted
3223 for (i
= 0; i
< FLOPPY_CAPACITIES
; i
++)
3225 if (capacityMatches
[i
] && FloppyCapacities
[i
].CanFormat
)
3227 if (outputBuffer
< outputBufferEnd
)
3229 *outputBuffer
++ = FloppyGeometries
[i
];
3231 Irp
->IoStatus
.Information
+= sizeof(DISK_GEOMETRY
);
3233 DebugPrint((2,"geometry : %3d %2d %d %2d %4d\n",
3234 FloppyGeometries
[i
].Cylinders
.LowPart
,
3235 FloppyGeometries
[i
].MediaType
,
3236 FloppyGeometries
[i
].TracksPerCylinder
,
3237 FloppyGeometries
[i
].SectorsPerTrack
,
3238 FloppyGeometries
[i
].BytesPerSector
));
3240 status
= STATUS_SUCCESS
;
3244 // We ran out of output buffer room before we ran out
3245 // geometries to return.
3247 status
= STATUS_BUFFER_OVERFLOW
;
3253 else if (NT_SUCCESS(status
))
3255 // The SCSIOP_READ_FORMATTED_CAPACITY request was successful, but
3256 // returned data does not appear valid.
3258 status
= STATUS_UNSUCCESSFUL
;
3261 ExFreePool(dataBuffer
);
3269 USBFlopFormatTracks(
3270 IN PDEVICE_OBJECT DeviceObject
,
3276 Routine Description:
3278 This routines formats the specified tracks. If multiple tracks are
3279 specified, each is formatted with a separate Format Unit request.
3283 DeviceObject - Supplies the device object.
3285 Irp - A IOCTL_DISK_FORMAT_TRACKS Irp.
3292 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
3293 PIO_STACK_LOCATION irpStack
;
3294 PFORMAT_PARAMETERS formatParameters
;
3295 PDISK_GEOMETRY geometry
;
3296 PFORMATTED_CAPACITY capacity
;
3297 PSCSI_REQUEST_BLOCK srb
;
3298 PFORMAT_UNIT_PARAMETER_LIST parameterList
;
3301 ULONG cylinder
, head
;
3302 NTSTATUS status
= STATUS_SUCCESS
;
3306 fdoExtension
= DeviceObject
->DeviceExtension
;
3308 // Get the Irp parameters
3310 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
3312 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
3313 sizeof(FORMAT_PARAMETERS
))
3315 return STATUS_INVALID_PARAMETER
;
3318 formatParameters
= (PFORMAT_PARAMETERS
)Irp
->AssociatedIrp
.SystemBuffer
;
3320 // Find the geometry / capacity entries corresponding to the format
3321 // parameters MediaType
3326 for (i
=0; i
<FLOPPY_CAPACITIES
; i
++)
3328 if (FloppyGeometries
[i
].MediaType
== formatParameters
->MediaType
)
3330 geometry
= &FloppyGeometries
[i
];
3331 capacity
= &FloppyCapacities
[i
];
3337 if (geometry
== NULL
)
3339 return STATUS_INVALID_PARAMETER
;
3342 // Check if the format parameters are valid
3344 if ((formatParameters
->StartCylinderNumber
>
3345 geometry
->Cylinders
.LowPart
- 1) ||
3347 (formatParameters
->EndCylinderNumber
>
3348 geometry
->Cylinders
.LowPart
- 1) ||
3350 (formatParameters
->StartHeadNumber
>
3351 geometry
->TracksPerCylinder
- 1) ||
3353 (formatParameters
->EndHeadNumber
>
3354 geometry
->TracksPerCylinder
- 1) ||
3356 (formatParameters
->StartCylinderNumber
>
3357 formatParameters
->EndCylinderNumber
) ||
3359 (formatParameters
->StartHeadNumber
>
3360 formatParameters
->EndHeadNumber
))
3362 return STATUS_INVALID_PARAMETER
;
3365 // Don't low level format LS-120 media, Imation says it's best to not
3368 if ((formatParameters
->MediaType
== F3_120M_512
) ||
3369 (formatParameters
->MediaType
== F3_240M_512
) ||
3370 (formatParameters
->MediaType
== F3_32M_512
))
3372 return STATUS_SUCCESS
;
3375 // Allocate an SRB for the SCSIOP_FORMAT_UNIT request
3377 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
3381 return STATUS_INSUFFICIENT_RESOURCES
;
3384 // Allocate a transfer buffer for the SCSIOP_FORMAT_UNIT parameter list
3386 parameterList
= ExAllocatePool(NonPagedPoolNx
,
3387 sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3389 if (parameterList
== NULL
)
3392 return STATUS_INSUFFICIENT_RESOURCES
;
3395 // Initialize the parameter list
3397 RtlZeroMemory(parameterList
, sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3399 parameterList
->DefectListHeader
.SingleTrack
= 1;
3400 parameterList
->DefectListHeader
.DisableCert
= 1; // TEAC requires this set
3401 parameterList
->DefectListHeader
.FormatOptionsValid
= 1;
3402 parameterList
->DefectListHeader
.DefectListLengthLsb
= 8;
3404 parameterList
->FormatDescriptor
.NumberOfBlocks
[0] =
3405 (UCHAR
)((capacity
->NumberOfBlocks
>> 24) & 0xFF);
3407 parameterList
->FormatDescriptor
.NumberOfBlocks
[1] =
3408 (UCHAR
)((capacity
->NumberOfBlocks
>> 16) & 0xFF);
3410 parameterList
->FormatDescriptor
.NumberOfBlocks
[2] =
3411 (UCHAR
)((capacity
->NumberOfBlocks
>> 8) & 0xFF);
3413 parameterList
->FormatDescriptor
.NumberOfBlocks
[3] =
3414 (UCHAR
)(capacity
->NumberOfBlocks
& 0xFF);
3416 parameterList
->FormatDescriptor
.BlockLength
[0] =
3417 (UCHAR
)((capacity
->BlockLength
>> 16) & 0xFF);
3419 parameterList
->FormatDescriptor
.BlockLength
[1] =
3420 (UCHAR
)((capacity
->BlockLength
>> 8) & 0xFF);
3422 parameterList
->FormatDescriptor
.BlockLength
[2] =
3423 (UCHAR
)(capacity
->BlockLength
& 0xFF);
3426 for (cylinder
= formatParameters
->StartCylinderNumber
;
3427 cylinder
<= formatParameters
->EndCylinderNumber
;
3430 for (head
= formatParameters
->StartHeadNumber
;
3431 head
<= formatParameters
->EndHeadNumber
;
3434 // Initialize the SRB and CDB
3436 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
3438 srb
->CdbLength
= sizeof(CDB12FORMAT
);
3440 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3442 cdb
= (PCDB12FORMAT
)srb
->Cdb
;
3444 cdb
->OperationCode
= SCSIOP_FORMAT_UNIT
;
3445 cdb
->DefectListFormat
= 7;
3447 cdb
->TrackNumber
= (UCHAR
)cylinder
;
3448 cdb
->ParameterListLengthLsb
= sizeof(FORMAT_UNIT_PARAMETER_LIST
);
3450 parameterList
->DefectListHeader
.Side
= (UCHAR
)head
;
3453 // Send down the SCSIOP_FORMAT_UNIT request
3455 status
= ClassSendSrbSynchronous(DeviceObject
,
3458 sizeof(FORMAT_UNIT_PARAMETER_LIST
),
3461 if (!NT_SUCCESS(status
))
3466 if (!NT_SUCCESS(status
))
3472 if (NT_SUCCESS(status
) && formatParameters
->StartCylinderNumber
== 0)
3474 // Update the device geometry
3477 DebugPrint((2,"geometry was: %3d %2d %d %2d %4d %2d %08X\n",
3478 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3479 fdoExtension
->DiskGeometry
.MediaType
,
3480 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3481 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3482 fdoExtension
->DiskGeometry
.BytesPerSector
,
3483 fdoExtension
->SectorShift
,
3484 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3486 fdoExtension
->DiskGeometry
= *geometry
;
3489 // Calculate sector to byte shift.
3492 WHICH_BIT(fdoExtension
->DiskGeometry
.BytesPerSector
,
3493 fdoExtension
->SectorShift
);
3495 fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
=
3496 (LONGLONG
)capacity
->NumberOfBlocks
*
3497 capacity
->BlockLength
;
3499 DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n",
3500 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3501 fdoExtension
->DiskGeometry
.MediaType
,
3502 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3503 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3504 fdoExtension
->DiskGeometry
.BytesPerSector
,
3505 fdoExtension
->SectorShift
,
3506 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3509 // Free everything we allocated
3511 ExFreePool(parameterList
);