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>
49 #define MODE_DATA_SIZE 192
50 #define SCSI_FLOPPY_TIMEOUT 20
51 #define SFLOPPY_SRB_LIST_SIZE 4
53 // Define all possible drive/media combinations, given drives listed above
54 // and media types in ntdddisk.h.
56 // These values are used to index the DriveMediaConstants table.
59 #define NUMBER_OF_DRIVE_TYPES 7
60 #define DRIVE_TYPE_120M 4 //120MB Floptical
61 #define DRIVE_TYPE_NONE NUMBER_OF_DRIVE_TYPES
64 // This array describes all media types we support.
65 // It should be arranged in the increasing order of density
67 // For a given drive, we list all the mediatypes that will
68 // work with that drive. For instance, a 120MB drive will
69 // take 720KB media, 1.44MB media, and 120MB media.
71 // Note that, DriveMediaConstants given below is grouped
72 // as drive and media combination
74 typedef enum _DRIVE_MEDIA_TYPE
{
75 Drive360Media160
, // 5.25" 360k drive; 160k media
76 Drive360Media180
, // 5.25" 360k drive; 180k media
77 Drive360Media320
, // 5.25" 360k drive; 320k media
78 Drive360Media32X
, // 5.25" 360k drive; 320k 1k secs
79 Drive360Media360
, // 5.25" 360k drive; 360k media
80 Drive720Media720
, // 3.5" 720k drive; 720k media
81 Drive120Media160
, // 5.25" 1.2Mb drive; 160k media
82 Drive120Media180
, // 5.25" 1.2Mb drive; 180k media
83 Drive120Media320
, // 5.25" 1.2Mb drive; 320k media
84 Drive120Media32X
, // 5.25" 1.2Mb drive; 320k 1k secs
85 Drive120Media360
, // 5.25" 1.2Mb drive; 360k media
86 Drive120Media120
, // 5.25" 1.2Mb drive; 1.2Mb media
87 Drive144Media720
, // 3.5" 1.44Mb drive; 720k media
88 Drive144Media144
, // 3.5" 1.44Mb drive; 1.44Mb media
89 Drive288Media720
, // 3.5" 2.88Mb drive; 720k media
90 Drive288Media144
, // 3.5" 2.88Mb drive; 1.44Mb media
91 Drive288Media288
, // 3.5" 2.88Mb drive; 2.88Mb media
92 Drive2080Media720
, // 3.5" 20.8Mb drive; 720k media
93 Drive2080Media144
, // 3.5" 20.8Mb drive; 1.44Mb media
94 Drive2080Media2080
, // 3.5" 20.8Mb drive; 20.8Mb media
95 Drive32MMedia32M
, // 3.5" 32Mb drive; 32MB media
96 Drive120MMedia720
, // 3.5" 120Mb drive; 720k media
97 Drive120MMedia144
, // 3.5" 120Mb drive; 1.44Mb media
98 Drive120MMedia120M
, // 3.5" 120Mb drive; 120Mb media
99 Drive240MMedia144M
, // 3.5" 240Mb drive; 1.44Mb media
100 Drive240MMedia120M
, // 3.5" 240Mb drive; 120Mb media
101 Drive240MMedia240M
// 3.5" 240Mb drive; 240Mb media
105 // When we want to determine the media type in a drive, we will first
106 // guess that the media with highest possible density is in the drive,
107 // and keep trying lower densities until we can successfully read from
110 // These values are used to select a DRIVE_MEDIA_TYPE value.
112 // The following table defines ranges that apply to the DRIVE_MEDIA_TYPE
113 // enumerated values when trying media types for a particular drive type.
114 // Note that for this to work, the DRIVE_MEDIA_TYPE values must be sorted
115 // by ascending densities within drive types. Also, for maximum track
116 // size to be determined properly, the drive types must be in ascending
120 typedef struct _DRIVE_MEDIA_LIMITS
{
121 DRIVE_MEDIA_TYPE HighestDriveMediaType
;
122 DRIVE_MEDIA_TYPE LowestDriveMediaType
;
123 } DRIVE_MEDIA_LIMITS
, *PDRIVE_MEDIA_LIMITS
;
126 DRIVE_MEDIA_LIMITS DriveMediaLimits
[NUMBER_OF_DRIVE_TYPES
] = {
128 { Drive360Media360
, Drive360Media160
}, // DRIVE_TYPE_0360
129 { Drive120Media120
, Drive120Media160
}, // DRIVE_TYPE_1200
130 { Drive720Media720
, Drive720Media720
}, // DRIVE_TYPE_0720
131 { Drive144Media144
, Drive144Media720
}, // DRIVE_TYPE_1440
132 { Drive288Media288
, Drive288Media720
}, // DRIVE_TYPE_2880
133 { Drive2080Media2080
, Drive2080Media720
}
136 DRIVE_MEDIA_LIMITS DriveMediaLimits
[NUMBER_OF_DRIVE_TYPES
] = {
138 { Drive720Media720
, Drive720Media720
}, // DRIVE_TYPE_0720
139 { Drive144Media144
, Drive144Media720
}, // DRIVE_TYPE_1440
140 { Drive288Media288
, Drive288Media720
}, // DRIVE_TYPE_2880
141 { Drive2080Media2080
, Drive2080Media720
},
142 { Drive32MMedia32M
, Drive32MMedia32M
}, // DRIVE_TYPE_32M
143 { Drive120MMedia120M
, Drive120MMedia720
}, // DRIVE_TYPE_120M
144 { Drive240MMedia240M
, Drive240MMedia144M
} // DRIVE_TYPE_240M
149 // For each drive/media combination, define important constants.
152 typedef struct _DRIVE_MEDIA_CONSTANTS
{
153 MEDIA_TYPE MediaType
;
154 USHORT BytesPerSector
;
155 UCHAR SectorsPerTrack
;
158 } DRIVE_MEDIA_CONSTANTS
, *PDRIVE_MEDIA_CONSTANTS
;
161 // Magic value to add to the SectorLengthCode to use it as a shift value
162 // to determine the sector size.
165 #define SECTORLENGTHCODE_TO_BYTESHIFT 7
168 // The following values were gleaned from many different sources, which
169 // often disagreed with each other. Where numbers were in conflict, I
170 // chose the more conservative or most-often-selected value.
173 DRIVE_MEDIA_CONSTANTS DriveMediaConstants
[] =
176 { F5_160_512
, 0x200, 0x08, 0x27, 0x1 },
177 { F5_180_512
, 0x200, 0x09, 0x27, 0x1 },
178 { F5_320_1024
, 0x400, 0x04, 0x27, 0x2 },
179 { F5_320_512
, 0x200, 0x08, 0x27, 0x2 },
180 { F5_360_512
, 0x200, 0x09, 0x27, 0x2 },
182 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
184 { F5_160_512
, 0x200, 0x08, 0x27, 0x1 },
185 { F5_180_512
, 0x200, 0x09, 0x27, 0x1 },
186 { F5_320_1024
, 0x400, 0x04, 0x27, 0x2 },
187 { F5_320_512
, 0x200, 0x08, 0x27, 0x2 },
188 { F5_360_512
, 0x200, 0x09, 0x27, 0x2 },
189 { F5_1Pt2_512
, 0x200, 0x0f, 0x4f, 0x2 },
191 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
192 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
194 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
195 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
196 { F3_2Pt88_512
, 0x200, 0x24, 0x4f, 0x2 },
198 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
199 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
200 { F3_20Pt8_512
, 0x200, 0x1b, 0xfa, 0x6 },
202 { F3_32M_512
, 0x200, 0x20, 0x3ff,0x2},
204 { F3_720_512
, 0x200, 0x09, 0x4f, 0x2 },
205 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
206 { F3_120M_512
, 0x200, 0x20, 0x3c2,0x8 },
208 { F3_1Pt44_512
, 0x200, 0x12, 0x4f, 0x2 },
209 { F3_120M_512
, 0x200, 0x20, 0x3c2,0x8 },
210 { F3_240M_512
, 0x200, 0x38, 0x105,0x20}
214 #define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS sizeof(DriveMediaConstants)/sizeof(DRIVE_MEDIA_CONSTANTS)
217 // floppy device data
220 typedef struct _DISK_DATA
{
223 // BOOLEAN EnableDMF;
224 UNICODE_STRING FloppyInterfaceString
;
225 } DISK_DATA
, *PDISK_DATA
;
228 // The FloppyCapacities and FloppyGeometries arrays are used by the
229 // USBFlopGetMediaTypes() and USBFlopFormatTracks() routines.
231 // The FloppyCapacities and FloppyGeometries arrays must be kept in 1:1 sync,
232 // i.e. each FloppyGeometries[i] must correspond to each FloppyCapacities[i].
234 // Also, the arrays must be kept in sorted ascending order so that they
235 // are returned in sorted ascending order by IOCTL_DISK_GET_MEDIA_TYPES.
238 typedef struct _FORMATTED_CAPACITY
240 ULONG NumberOfBlocks
;
244 BOOLEAN CanFormat
; // return for IOCTL_DISK_GET_MEDIA_TYPES ?
246 } FORMATTED_CAPACITY
, *PFORMATTED_CAPACITY
;
249 FORMATTED_CAPACITY FloppyCapacities
[] =
251 // Blocks BlockLen CanFormat H T B/S S/T
252 {0x000500, 0x0200, TRUE
}, // 2 80 512 8 640 KB F5_640_512
253 {0x0005A0, 0x0200, TRUE
}, // 2 80 512 9 720 KB F3_720_512
254 {0x000960, 0x0200, TRUE
}, // 2 80 512 15 1.20 MB F3_1Pt2_512 (Toshiba)
255 {0x0004D0, 0x0400, TRUE
}, // 2 77 1024 8 1.23 MB F3_1Pt23_1024 (NEC)
256 {0x000B40, 0x0200, TRUE
}, // 2 80 512 18 1.44 MB F3_1Pt44_512
257 {0x000D20, 0x0200, FALSE
}, // 2 80 512 21 1.70 MB DMF
258 {0x010000, 0x0200, TRUE
}, // 2 1024 512 32 32 MB F3_32M_512
259 {0x03C300, 0x0200, TRUE
}, // 8 963 512 32 120 MB F3_120M_512
260 {0x0600A4, 0x0200, TRUE
}, // 13 890 512 34 200 MB F3_200Mb_512 (HiFD)
261 {0x072A00, 0x0200, TRUE
} // 32 262 512 56 240 MB F3_240M_512
264 DISK_GEOMETRY FloppyGeometries
[] =
266 // Cyl MediaType Trk/Cyl Sec/Trk Bytes/Sec
268 {{80,0}, F3_640_512
, 2, 8, 512},
269 {{80,0}, F3_720_512
, 2, 9, 512},
270 {{80,0}, F3_1Pt2_512
, 2, 15, 512},
271 {{77,0}, F3_1Pt23_1024
, 2, 8, 1024},
272 {{80,0}, F3_1Pt44_512
, 2, 18, 512},
273 {{80,0}, F3_1Pt44_512
, 2, 21, 512}, // DMF -> F3_1Pt44_512
274 {{1024,0}, F3_32M_512
, 2, 32, 512},
275 {{963,0}, F3_120M_512
, 8, 32, 512},
276 {{890,0}, F3_200Mb_512
, 13, 34, 512},
277 {{262,0}, F3_240M_512
, 32, 56, 512}
279 {{{80,0}}, F3_640_512
, 2, 8, 512},
280 {{{80,0}}, F3_720_512
, 2, 9, 512},
281 {{{80,0}}, F3_1Pt2_512
, 2, 15, 512},
282 {{{77,0}}, F3_1Pt23_1024
, 2, 8, 1024},
283 {{{80,0}}, F3_1Pt44_512
, 2, 18, 512},
284 {{{80,0}}, F3_1Pt44_512
, 2, 21, 512}, // DMF -> F3_1Pt44_512
285 {{{1024,0}}, F3_32M_512
, 2, 32, 512},
286 {{{963,0}}, F3_120M_512
, 8, 32, 512},
287 {{{890,0}}, F3_200Mb_512
, 13, 34, 512},
288 {{{262,0}}, F3_240M_512
, 32, 56, 512}
292 #define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0]))
294 C_ASSERT((sizeof(FloppyGeometries
)/sizeof(FloppyGeometries
[0])) == FLOPPY_CAPACITIES
);
297 // The following structures are used by USBFlopFormatTracks()
300 #pragma pack (push, 1)
302 typedef struct _CDB12FORMAT
305 UCHAR DefectListFormat
: 3;
308 UCHAR LogicalUnitNumber
: 3;
313 UCHAR ParameterListLengthMsb
;
314 UCHAR ParameterListLengthLsb
;
316 } CDB12FORMAT
, *PCDB12FORMAT
;
319 typedef struct _DEFECT_LIST_HEADER
325 UCHAR SingleTrack
: 1;
326 UCHAR DisableCert
: 1;
328 UCHAR FormatOptionsValid
: 1;
329 UCHAR DefectListLengthMsb
;
330 UCHAR DefectListLengthLsb
;
331 } DEFECT_LIST_HEADER
, *PDEFECT_LIST_HEADER
;
333 typedef struct _FORMAT_UNIT_PARAMETER_LIST
335 DEFECT_LIST_HEADER DefectListHeader
;
336 FORMATTED_CAPACITY_DESCRIPTOR FormatDescriptor
;
337 } FORMAT_UNIT_PARAMETER_LIST
, *PFORMAT_UNIT_PARAMETER_LIST
;
341 DRIVER_INITIALIZE DriverEntry
;
343 DRIVER_UNLOAD ScsiFlopUnload
;
345 DRIVER_ADD_DEVICE ScsiFlopAddDevice
;
352 IN PDEVICE_OBJECT Fdo
360 IN PDEVICE_OBJECT Fdo
367 ScsiFlopRemoveDevice(
368 IN PDEVICE_OBJECT Fdo
,
377 IN PDEVICE_OBJECT Fdo
,
383 IN PDRIVER_OBJECT DriverObject
,
384 IN PUNICODE_STRING RegistryPath
,
385 IN PCLASS_INIT_DATA InitializationData
,
386 IN PDEVICE_OBJECT PortDeviceObject
,
394 ScsiFlopReadWriteVerification(
395 IN PDEVICE_OBJECT DeviceObject
,
403 ScsiFlopDeviceControl(
404 IN PDEVICE_OBJECT DeviceObject
,
410 PDEVICE_OBJECT DeviceObject
414 CreateFlopDeviceObject(
415 IN PDRIVER_OBJECT DriverObject
,
416 IN PDEVICE_OBJECT PortDeviceObject
,
422 PDEVICE_OBJECT DeviceObject
427 PDEVICE_OBJECT DeviceObject
431 FlCheckFormatParameters(
432 IN PDEVICE_OBJECT DeviceObject
,
433 IN PFORMAT_PARAMETERS FormatParameters
438 PDEVICE_OBJECT DeviceObject
,
443 FlopticalFormatMedia(
444 PDEVICE_OBJECT DeviceObject
,
445 PFORMAT_PARAMETERS Format
452 ScsiFlopProcessError(
453 PDEVICE_OBJECT DeviceObject
,
454 PSCSI_REQUEST_BLOCK Srb
,
460 USBFlopGetMediaTypes(
461 IN PDEVICE_OBJECT DeviceObject
,
467 IN PDEVICE_OBJECT DeviceObject
,
472 #pragma alloc_text(INIT, DriverEntry)
474 #pragma alloc_text(PAGE, ScsiFlopUnload)
475 #pragma alloc_text(PAGE, ScsiFlopAddDevice)
476 #pragma alloc_text(PAGE, CreateFlopDeviceObject)
477 #pragma alloc_text(PAGE, ScsiFlopStartDevice)
478 #pragma alloc_text(PAGE, ScsiFlopRemoveDevice)
479 #pragma alloc_text(PAGE, IsFloppyDevice)
480 #pragma alloc_text(PAGE, DetermineMediaType)
481 #pragma alloc_text(PAGE, DetermineDriveType)
482 #pragma alloc_text(PAGE, FlCheckFormatParameters)
483 #pragma alloc_text(PAGE, FormatMedia)
484 #pragma alloc_text(PAGE, FlopticalFormatMedia)
485 #pragma alloc_text(PAGE, USBFlopGetMediaTypes)
486 #pragma alloc_text(PAGE, USBFlopFormatTracks)
496 IN PDRIVER_OBJECT DriverObject
,
497 IN PUNICODE_STRING RegistryPath
503 This is the system initialization routine for installable drivers.
504 It calls the SCSI class driver initialization routine.
508 DriverObject - Pointer to driver object created by system.
517 CLASS_INIT_DATA InitializationData
;
523 RtlZeroMemory (&InitializationData
, sizeof(CLASS_INIT_DATA
));
529 InitializationData
.InitializationDataSize
= sizeof(CLASS_INIT_DATA
);
530 InitializationData
.FdoData
.DeviceExtensionSize
=
531 sizeof(FUNCTIONAL_DEVICE_EXTENSION
) + sizeof(DISK_DATA
);
533 InitializationData
.FdoData
.DeviceType
= FILE_DEVICE_DISK
;
534 InitializationData
.FdoData
.DeviceCharacteristics
= FILE_REMOVABLE_MEDIA
| FILE_FLOPPY_DISKETTE
;
540 InitializationData
.FdoData
.ClassInitDevice
= ScsiFlopInitDevice
;
541 InitializationData
.FdoData
.ClassStartDevice
= ScsiFlopStartDevice
;
542 InitializationData
.FdoData
.ClassStopDevice
= ScsiFlopStopDevice
;
543 InitializationData
.FdoData
.ClassRemoveDevice
= ScsiFlopRemoveDevice
;
545 InitializationData
.FdoData
.ClassReadWriteVerification
= ScsiFlopReadWriteVerification
;
546 InitializationData
.FdoData
.ClassDeviceControl
= ScsiFlopDeviceControl
;
548 InitializationData
.FdoData
.ClassShutdownFlush
= NULL
;
549 InitializationData
.FdoData
.ClassCreateClose
= NULL
;
550 InitializationData
.FdoData
.ClassError
= ScsiFlopProcessError
;
551 InitializationData
.ClassStartIo
= NULL
;
553 InitializationData
.ClassAddDevice
= ScsiFlopAddDevice
;
554 InitializationData
.ClassUnload
= ScsiFlopUnload
;
556 // Call the class init routine
559 return ClassInitialize( DriverObject
, RegistryPath
, &InitializationData
);
562 } // end DriverEntry()
569 IN PDRIVER_OBJECT DriverObject
573 UNREFERENCED_PARAMETER(DriverObject
);
578 // AddDevice operation is performed in CreateFlopDeviceObject function which
579 // is called by ScsiFlopAddDevice (The AddDevice routine for sfloppy.sys).
580 // DO_DEVICE_INITIALIZING flag is cleard upon successfully processing AddDevice
581 // operation in CreateFlopDeviceObject. But PREFAST is currently unable to
582 // detect that DO_DEVICE_INITIALIZING is indeed cleard in CreateFlopDeviceObject
583 // and it raises Warning 28152 (The return from an AddDevice-like function
584 // unexpectedly did not clear DO_DEVICE_INITIALIZING). Suppress that warning
588 #if !defined(__REACTOS__) || defined(_MSC_VER)
589 #pragma warning(push)
590 #pragma warning(disable:28152)
598 IN PDRIVER_OBJECT DriverObject
,
599 IN PDEVICE_OBJECT Pdo
605 This routine creates and initializes a new FDO for the corresponding
606 PDO. It may perform property queries on the FDO but cannot do any
607 media access operations.
611 DriverObject - Scsiscan class driver object.
613 Pdo - the physical device object we are being added to
622 ULONG floppyCount
= IoGetConfigurationInformation()->FloppyCount
;
627 // Get the number of disks already initialized.
630 status
= CreateFlopDeviceObject(DriverObject
, Pdo
, floppyCount
);
632 if (NT_SUCCESS(status
)) {
635 // Increment system floppy device count.
638 IoGetConfigurationInformation()->FloppyCount
++;
645 CreateFlopDeviceObject(
646 IN PDRIVER_OBJECT DriverObject
,
647 IN PDEVICE_OBJECT Pdo
,
655 This routine creates an object for the device and then calls the
656 SCSI port driver for media capacity and sector size.
660 DriverObject - Pointer to driver object created by system.
661 PortDeviceObject - to connect to SCSI port driver.
662 DeviceCount - Number of previously installed Floppys.
663 AdapterDescriptor - Pointer to structure returned by SCSI port
664 driver describing adapter capabilites (and limitations).
665 DeviceDescriptor - Pointer to configuration information for this device.
672 PDEVICE_OBJECT deviceObject
= NULL
;
673 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= NULL
;
678 DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n"));
681 // Try to claim the device.
684 status
= ClassClaimDevice(Pdo
,FALSE
);
686 if (!NT_SUCCESS(status
)) {
696 // Create device object for this device.
701 status
= RtlStringCbPrintfA((PCCHAR
) name
,
703 "\\Device\\Floppy%u",
705 if (NT_SUCCESS(status
)) {
707 status
= ClassCreateDeviceObject(DriverObject
,
713 } while ((status
== STATUS_OBJECT_NAME_COLLISION
) ||
714 (status
== STATUS_OBJECT_NAME_EXISTS
));
716 if (!NT_SUCCESS(status
)) {
717 DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n"));
718 goto CreateFlopDeviceObjectExit
;
722 // Indicate that IRPs should include MDLs.
725 deviceObject
->Flags
|= DO_DIRECT_IO
;
727 fdoExtension
= deviceObject
->DeviceExtension
;
730 // Back pointer to device object.
733 fdoExtension
->CommonExtension
.DeviceObject
= deviceObject
;
736 // This is the physical device.
739 fdoExtension
->CommonExtension
.PartitionZeroExtension
= fdoExtension
;
742 // Reset the drive type.
745 diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
746 diskData
->DriveType
= DRIVE_TYPE_NONE
;
747 diskData
->IsDMF
= FALSE
;
748 // diskData->EnableDMF = TRUE;
751 // Initialize lock count to zero. The lock count is used to
752 // disable the ejection mechanism when media is mounted.
755 fdoExtension
->LockCount
= 0;
758 // Save system floppy number
761 fdoExtension
->DeviceNumber
= DeviceCount
;
764 // Set the alignment requirements for the device based on the
765 // host adapter requirements
768 if (Pdo
->AlignmentRequirement
> deviceObject
->AlignmentRequirement
) {
769 deviceObject
->AlignmentRequirement
= Pdo
->AlignmentRequirement
;
773 // Clear the SrbFlags and disable synchronous transfers
776 fdoExtension
->SrbFlags
= SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
779 // Finally, attach to the PDO
782 fdoExtension
->LowerPdo
= Pdo
;
784 fdoExtension
->CommonExtension
.LowerDeviceObject
=
785 IoAttachDeviceToDeviceStack(deviceObject
, Pdo
);
787 if(fdoExtension
->CommonExtension
.LowerDeviceObject
== NULL
) {
789 status
= STATUS_UNSUCCESSFUL
;
790 goto CreateFlopDeviceObjectExit
;
793 deviceObject
->StackSize
++;
796 // The device is initialized properly - mark it as such.
799 deviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
801 return STATUS_SUCCESS
;
803 CreateFlopDeviceObjectExit
:
805 if (deviceObject
!= NULL
) {
806 IoDeleteDevice(deviceObject
);
811 } // end CreateFlopDeviceObject()
812 #if !defined(__REACTOS__) || defined(_MSC_VER)
821 IN PDEVICE_OBJECT Fdo
824 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
825 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
826 PDISK_DATA diskData
= commonExtension
->DriverData
;
828 PVOID senseData
= NULL
;
831 NTSTATUS status
= STATUS_SUCCESS
;
834 // Allocate request sense buffer.
838 senseData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, SENSE_BUFFER_SIZE
);
840 senseData
= ExAllocatePool(NonPagedPoolCacheAligned
, SENSE_BUFFER_SIZE
);
843 if (senseData
== NULL
) {
846 // The buffer cannot be allocated.
849 status
= STATUS_INSUFFICIENT_RESOURCES
;
854 // Set the sense data pointer in the device extension.
857 fdoExtension
->SenseData
= senseData
;
860 // Build the lookaside list for srb's for this device.
863 ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION
)fdoExtension
,
864 SFLOPPY_SRB_LIST_SIZE
);
867 // Register for media change notification
869 ClassInitializeMediaChangeDetection(fdoExtension
,
873 // Set timeout value in seconds.
876 timeOut
= ClassQueryTimeOutRegistryValue(Fdo
);
878 fdoExtension
->TimeOutValue
= timeOut
;
880 fdoExtension
->TimeOutValue
= SCSI_FLOPPY_TIMEOUT
;
884 // Floppies are not partitionable so starting offset is 0.
887 fdoExtension
->CommonExtension
.StartingOffset
.QuadPart
= (LONGLONG
)0;
890 if (!IsFloppyDevice(Fdo
) ||
891 !(Fdo
->Characteristics
& FILE_REMOVABLE_MEDIA
) ||
892 (fdoExtension
->DeviceDescriptor
->DeviceType
!= DIRECT_ACCESS_DEVICE
)) {
894 ExFreePool(senseData
);
895 status
= STATUS_NO_SUCH_DEVICE
;
900 RtlZeroMemory(&(fdoExtension
->DiskGeometry
),
901 sizeof(DISK_GEOMETRY
));
904 // Determine the media type if possible. Set the current media type to
905 // Unknown so that determine media type will check the media.
908 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
911 // Register interfaces for this device.
915 UNICODE_STRING interfaceName
;
917 RtlInitUnicodeString(&interfaceName
, NULL
);
919 status
= IoRegisterDeviceInterface(fdoExtension
->LowerPdo
,
920 (LPGUID
) &GUID_DEVINTERFACE_FLOPPY
,
924 if(NT_SUCCESS(status
)) {
925 diskData
->FloppyInterfaceString
= interfaceName
;
927 RtlInitUnicodeString(&(diskData
->FloppyInterfaceString
), NULL
);
928 DebugPrint((1, "ScsiFlopStartDevice: Unable to register device "
929 "interface for fdo %p [%08lx]\n",
934 return (STATUS_SUCCESS
);
937 #if !defined(__REACTOS__) || defined(_MSC_VER)
938 #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
941 NTSTATUS NTAPI
ScsiFlopStartDevice(
943 NTSTATUS
ScsiFlopStartDevice(
945 IN PDEVICE_OBJECT Fdo
948 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
949 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
952 IO_STATUS_BLOCK ioStatus
;
954 SCSI_ADDRESS scsiAddress
;
956 WCHAR ntNameBuffer
[256];
957 UNICODE_STRING ntUnicodeString
;
959 WCHAR arcNameBuffer
[256];
960 UNICODE_STRING arcUnicodeString
;
964 NTSTATUS status
= STATUS_SUCCESS
;
968 KeInitializeEvent(&event
,SynchronizationEvent
,FALSE
);
970 DetermineMediaType(Fdo
); // ignore unsuccessful here
973 // Create device object for this device.
976 RtlStringCbPrintfW(ntNameBuffer
,
977 sizeof(ntNameBuffer
),
978 L
"\\Device\\Floppy%u",
979 fdoExtension
->DeviceNumber
);
982 // Create local copy of unicode string
984 RtlInitUnicodeString(&ntUnicodeString
,ntNameBuffer
);
987 // Create a symbolic link from the disk name to the corresponding
988 // ARC name, to be used if we're booting off the disk. This will
989 // fail if it's not system initialization time; that's fine. The
990 // ARC name looks something like \ArcName\scsi(0)Flop(0)fdisk(0).
991 // In order to get the address, we need to send a IOCTL_SCSI_GET_ADDRESS...
994 irp
= IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS
,
1005 return STATUS_INSUFFICIENT_RESOURCES
;
1008 status
= IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, irp
);
1010 if (status
== STATUS_PENDING
) {
1011 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
1012 status
= ioStatus
.Status
;
1016 // IOCTL_SCSI_GET_ADDRESS might not be supported by the port driver and
1017 // hence may fail. But it is not a fatal error. Do not fail PnP start
1018 // if this IOCTL fails.
1020 if (NT_SUCCESS(status
)) {
1022 RtlStringCbPrintfW(arcNameBuffer
,
1023 sizeof(arcNameBuffer
),
1024 L
"\\ArcName\\scsi(%u)disk(%u)fdisk(%u)",
1025 scsiAddress
.PortNumber
,
1026 scsiAddress
.TargetId
,
1029 RtlInitUnicodeString(&arcUnicodeString
, arcNameBuffer
);
1031 IoAssignArcName(&arcUnicodeString
, &ntUnicodeString
);
1034 status
= STATUS_SUCCESS
;
1037 // Create the multi() arc name -- Create the "fake"
1038 // name of multi(0)disk(0)fdisk(#) to handle the case where the
1039 // SCSI floppy is the only floppy in the system. If this fails
1040 // it doesn't matter because the previous scsi() based ArcName
1041 // will work. This name is necessary for installation.
1044 RtlStringCbPrintfW(arcNameBuffer
,
1045 sizeof(arcNameBuffer
),
1046 L
"\\ArcName\\multi(%u)disk(%u)fdisk(%u)",
1049 fdoExtension
->DeviceNumber
);
1051 RtlInitUnicodeString(&arcUnicodeString
, arcNameBuffer
);
1053 IoAssignArcName(&arcUnicodeString
, &ntUnicodeString
);
1056 // Set our interface state.
1060 PDISK_DATA diskData
= commonExtension
->DriverData
;
1062 if(diskData
->FloppyInterfaceString
.Buffer
!= NULL
) {
1064 status
= IoSetDeviceInterfaceState(
1065 &(diskData
->FloppyInterfaceString
),
1068 if(!NT_SUCCESS(status
)) {
1069 DebugPrint((1, "ScsiFlopStartDevice: Unable to set device "
1070 "interface state to TRUE for fdo %p "
1077 return STATUS_SUCCESS
;
1085 ScsiFlopReadWriteVerification(
1086 IN PDEVICE_OBJECT DeviceObject
,
1092 Routine Description:
1103 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1104 PIO_STACK_LOCATION irpSp
= IoGetCurrentIrpStackLocation(Irp
);
1105 NTSTATUS status
= STATUS_SUCCESS
;
1108 // Make sure that the number of bytes to transfer is a multiple of the sector size
1110 if ((irpSp
->Parameters
.Read
.Length
& (fdoExtension
->DiskGeometry
.BytesPerSector
- 1)) != 0)
1112 status
= STATUS_INVALID_PARAMETER
;
1115 Irp
->IoStatus
.Status
= status
;
1125 ScsiFlopDeviceControl(
1126 PDEVICE_OBJECT DeviceObject
,
1132 Routine Description:
1144 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
1145 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1146 PSCSI_REQUEST_BLOCK srb
;
1149 PDISK_GEOMETRY outputBuffer
;
1150 ULONG outputBufferLength
;
1152 DRIVE_MEDIA_TYPE lowestDriveMediaType
;
1153 DRIVE_MEDIA_TYPE highestDriveMediaType
;
1154 PFORMAT_PARAMETERS formatParameters
;
1155 PMODE_PARAMETER_HEADER modeData
;
1159 // Initialize the information field
1161 Irp
->IoStatus
.Information
= 0;
1164 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
1166 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
1171 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1172 if (IoIsErrorUserInduced(Irp
->IoStatus
.Status
)) {
1174 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1177 KeRaiseIrql(DISPATCH_LEVEL
, ¤tIrql
);
1178 ClassReleaseRemoveLock(DeviceObject
, Irp
);
1179 ClassCompleteRequest(DeviceObject
, Irp
, 0);
1180 KeLowerIrql(currentIrql
);
1182 return(STATUS_INSUFFICIENT_RESOURCES
);
1186 // Write zeros to Srb.
1189 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
1191 cdb
= (PCDB
)srb
->Cdb
;
1193 switch (irpStack
->Parameters
.DeviceIoControl
.IoControlCode
) {
1196 case IOCTL_DISK_VERIFY
: {
1198 PVERIFY_INFORMATION verifyInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
1199 LARGE_INTEGER byteOffset
;
1204 // Validate buffer length.
1207 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
1208 sizeof(VERIFY_INFORMATION
)) {
1210 status
= STATUS_INFO_LENGTH_MISMATCH
;
1215 // Perform a bounds check on the sector range
1217 if ((verifyInfo
->StartingOffset
.QuadPart
> fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
) ||
1218 (verifyInfo
->StartingOffset
.QuadPart
< 0))
1220 status
= STATUS_NONEXISTENT_SECTOR
;
1225 ULONGLONG bytesRemaining
= fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
- verifyInfo
->StartingOffset
.QuadPart
;
1227 if ((ULONGLONG
)verifyInfo
->Length
> bytesRemaining
)
1229 status
= STATUS_NONEXISTENT_SECTOR
;
1238 srb
->CdbLength
= 10;
1240 cdb
->CDB10
.OperationCode
= SCSIOP_VERIFY
;
1243 // Add disk offset to starting sector.
1246 byteOffset
.QuadPart
= fdoExtension
->CommonExtension
.StartingOffset
.QuadPart
+
1247 verifyInfo
->StartingOffset
.QuadPart
;
1250 // Convert byte offset to sector offset.
1253 sectorOffset
= (ULONG
)(byteOffset
.QuadPart
>> fdoExtension
->SectorShift
);
1256 // Convert ULONG byte count to USHORT sector count.
1259 sectorCount
= (USHORT
)(verifyInfo
->Length
>> fdoExtension
->SectorShift
);
1262 // Move little endian values into CDB in big endian format.
1265 cdb
->CDB10
.LogicalBlockByte0
= ((PFOUR_BYTE
)§orOffset
)->Byte3
;
1266 cdb
->CDB10
.LogicalBlockByte1
= ((PFOUR_BYTE
)§orOffset
)->Byte2
;
1267 cdb
->CDB10
.LogicalBlockByte2
= ((PFOUR_BYTE
)§orOffset
)->Byte1
;
1268 cdb
->CDB10
.LogicalBlockByte3
= ((PFOUR_BYTE
)§orOffset
)->Byte0
;
1270 cdb
->CDB10
.TransferBlocksMsb
= ((PFOUR_BYTE
)§orCount
)->Byte1
;
1271 cdb
->CDB10
.TransferBlocksLsb
= ((PFOUR_BYTE
)§orCount
)->Byte0
;
1274 // The verify command is used by the NT FORMAT utility and
1275 // requests are sent down for 5% of the volume size. The
1276 // request timeout value is calculated based on the number of
1277 // sectors verified.
1280 srb
->TimeOutValue
= ((sectorCount
+ 0x7F) >> 7) *
1281 fdoExtension
->TimeOutValue
;
1283 status
= ClassSendSrbAsynchronous(DeviceObject
,
1293 case IOCTL_DISK_GET_PARTITION_INFO
: {
1295 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
) {
1297 USBFlopGetMediaTypes(DeviceObject
, NULL
);
1299 // Don't need to propagate any error if one occurs
1301 status
= STATUS_SUCCESS
;
1305 status
= DetermineMediaType(DeviceObject
);
1308 if (!NT_SUCCESS(status
)) {
1309 // so will propogate error
1311 } else if (fdoExtension
->DiskGeometry
.MediaType
== F3_120M_512
) {
1312 //so that the format code will not try to partition it.
1313 status
= STATUS_INVALID_DEVICE_REQUEST
;
1316 // Free the Srb, since it is not needed.
1322 // Pass the request to the common device control routine.
1325 return(ClassDeviceControl(DeviceObject
, Irp
));
1330 case IOCTL_DISK_GET_DRIVE_GEOMETRY
: {
1332 DebugPrint((3,"ScsiDeviceIoControl: Get drive geometry\n"));
1334 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
)
1336 status
= USBFlopGetMediaTypes(DeviceObject
,
1342 // If there's not enough room to write the
1343 // data, then fail the request.
1346 if ( irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1347 sizeof( DISK_GEOMETRY
) ) {
1349 status
= STATUS_INVALID_PARAMETER
;
1353 status
= DetermineMediaType(DeviceObject
);
1355 if (!NT_SUCCESS(status
)) {
1357 Irp
->IoStatus
.Information
= 0;
1358 Irp
->IoStatus
.Status
= status
;
1363 // Copy drive geometry information from device extension.
1366 RtlMoveMemory(Irp
->AssociatedIrp
.SystemBuffer
,
1367 &(fdoExtension
->DiskGeometry
),
1368 sizeof(DISK_GEOMETRY
));
1370 Irp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
1371 status
= STATUS_SUCCESS
;
1378 case IOCTL_DISK_GET_MEDIA_TYPES
: {
1380 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
)
1382 status
= USBFlopGetMediaTypes(DeviceObject
,
1387 i
= DetermineDriveType(DeviceObject
);
1389 if (i
== DRIVE_TYPE_NONE
) {
1390 status
= STATUS_UNRECOGNIZED_MEDIA
;
1394 lowestDriveMediaType
= DriveMediaLimits
[i
].LowestDriveMediaType
;
1395 highestDriveMediaType
= DriveMediaLimits
[i
].HighestDriveMediaType
;
1397 outputBufferLength
=
1398 irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1401 // Make sure that the input buffer has enough room to return
1402 // at least one descriptions of a supported media type.
1405 if ( outputBufferLength
< ( sizeof( DISK_GEOMETRY
) ) ) {
1407 status
= STATUS_BUFFER_TOO_SMALL
;
1412 // Assume success, although we might modify it to a buffer
1413 // overflow warning below (if the buffer isn't big enough
1414 // to hold ALL of the media descriptions).
1417 status
= STATUS_SUCCESS
;
1419 if (outputBufferLength
< ( sizeof( DISK_GEOMETRY
) *
1420 ( highestDriveMediaType
- lowestDriveMediaType
+ 1 ) ) ) {
1423 // The buffer is too small for all of the descriptions;
1424 // calculate what CAN fit in the buffer.
1427 status
= STATUS_BUFFER_OVERFLOW
;
1429 highestDriveMediaType
= (DRIVE_MEDIA_TYPE
)( ( lowestDriveMediaType
- 1 ) +
1430 ( outputBufferLength
/
1431 sizeof( DISK_GEOMETRY
) ) );
1434 outputBuffer
= (PDISK_GEOMETRY
) Irp
->AssociatedIrp
.SystemBuffer
;
1436 for (i
= (UCHAR
)lowestDriveMediaType
;i
<= (UCHAR
)highestDriveMediaType
;i
++ ) {
1438 outputBuffer
->MediaType
= DriveMediaConstants
[i
].MediaType
;
1439 outputBuffer
->Cylinders
.LowPart
=
1440 DriveMediaConstants
[i
].MaximumTrack
+ 1;
1441 outputBuffer
->Cylinders
.HighPart
= 0;
1442 outputBuffer
->TracksPerCylinder
=
1443 DriveMediaConstants
[i
].NumberOfHeads
;
1444 outputBuffer
->SectorsPerTrack
=
1445 DriveMediaConstants
[i
].SectorsPerTrack
;
1446 outputBuffer
->BytesPerSector
=
1447 DriveMediaConstants
[i
].BytesPerSector
;
1450 Irp
->IoStatus
.Information
+= sizeof( DISK_GEOMETRY
);
1456 case IOCTL_DISK_FORMAT_TRACKS
: {
1458 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
)
1460 status
= USBFlopFormatTracks(DeviceObject
,
1466 // Make sure that we got all the necessary format parameters.
1469 if ( irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<sizeof( FORMAT_PARAMETERS
) ) {
1471 status
= STATUS_INVALID_PARAMETER
;
1475 formatParameters
= (PFORMAT_PARAMETERS
) Irp
->AssociatedIrp
.SystemBuffer
;
1478 // Make sure the parameters we got are reasonable.
1481 if ( !FlCheckFormatParameters(DeviceObject
, formatParameters
)) {
1483 status
= STATUS_INVALID_PARAMETER
;
1488 // If this request is for a 20.8 MB floppy then call a special
1489 // floppy format routine.
1492 if (formatParameters
->MediaType
== F3_20Pt8_512
) {
1493 status
= FlopticalFormatMedia(DeviceObject
,
1501 // All the work is done in the pass. If this is not the first pass,
1502 // then complete the request and return;
1505 if (formatParameters
->StartCylinderNumber
!= 0 || formatParameters
->StartHeadNumber
!= 0) {
1507 status
= STATUS_SUCCESS
;
1511 status
= FormatMedia( DeviceObject
, formatParameters
->MediaType
);
1515 case IOCTL_DISK_IS_WRITABLE
: {
1517 if ((fdoExtension
->DiskGeometry
.MediaType
) == F3_32M_512
) {
1520 // 32MB media is READ ONLY. Just return
1521 // STATUS_MEDIA_WRITE_PROTECTED
1524 status
= STATUS_MEDIA_WRITE_PROTECTED
;
1530 // Determine if the device is writable.
1534 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
1536 modeData
= ExAllocatePool(NonPagedPoolCacheAligned
, MODE_DATA_SIZE
);
1539 if (modeData
== NULL
) {
1540 status
= STATUS_INSUFFICIENT_RESOURCES
;
1544 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
1546 length
= ClassModeSense(DeviceObject
,
1549 MODE_SENSE_RETURN_ALL
);
1551 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1554 // Retry the request in case of a check condition.
1557 length
= ClassModeSense(DeviceObject
,
1560 MODE_SENSE_RETURN_ALL
);
1562 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1563 status
= STATUS_IO_DEVICE_ERROR
;
1564 ExFreePool(modeData
);
1569 if (modeData
->DeviceSpecificParameter
& MODE_DSP_WRITE_PROTECT
) {
1570 status
= STATUS_MEDIA_WRITE_PROTECTED
;
1572 status
= STATUS_SUCCESS
;
1575 DebugPrint((2,"IOCTL_DISK_IS_WRITABLE returns %08X\n", status
));
1577 ExFreePool(modeData
);
1583 DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n"));
1586 // Free the Srb, since it is not needed.
1592 // Pass the request to the common device control routine.
1595 return(ClassDeviceControl(DeviceObject
, Irp
));
1600 } // end switch( ...
1603 // Check if SL_OVERRIDE_VERIFY_VOLUME flag is set in the IRP.
1604 // If so, do not return STATUS_VERIFY_REQUIRED
1606 if ((status
== STATUS_VERIFY_REQUIRED
) &&
1607 (TEST_FLAG(irpStack
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
))) {
1609 status
= STATUS_IO_DEVICE_ERROR
;
1613 Irp
->IoStatus
.Status
= status
;
1615 if (!NT_SUCCESS(status
) && IoIsErrorUserInduced(status
)) {
1617 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
1620 KeRaiseIrql(DISPATCH_LEVEL
, ¤tIrql
);
1621 ClassReleaseRemoveLock(DeviceObject
, Irp
);
1622 ClassCompleteRequest(DeviceObject
, Irp
, 0);
1623 KeLowerIrql(currentIrql
);
1629 } // end ScsiFlopDeviceControl()
1635 PDEVICE_OBJECT DeviceObject
1639 Routine Description:
1641 The routine performs the necessary funcitons to deterime if the device is
1642 really a floppy rather than a harddisk. This is done by a mode sense
1643 command. First a check is made to see if the medimum type is set. Second
1644 a check is made for the flexible parameters mode page.
1648 DeviceObject - Supplies the device object to be tested.
1652 Return TRUE if the indicated device is a floppy.
1661 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
1663 if (modeData
== NULL
) {
1667 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
1669 length
= ClassModeSense(DeviceObject
, modeData
, MODE_DATA_SIZE
, MODE_SENSE_RETURN_ALL
);
1671 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1674 // Retry the request in case of a check condition.
1677 length
= ClassModeSense(DeviceObject
,
1680 MODE_SENSE_RETURN_ALL
);
1682 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1684 ExFreePool(modeData
);
1692 // Some drives incorrectly report this. In particular the SONY RMO-S350
1693 // when in disk mode.
1696 if (((PMODE_PARAMETER_HEADER
) modeData
)->MediumType
>= MODE_FD_SINGLE_SIDE
1697 && ((PMODE_PARAMETER_HEADER
) modeData
)->MediumType
<= MODE_FD_MAXIMUM_TYPE
) {
1699 DebugPrint((1, "ScsiFlop: MediumType value %2x, This is a floppy.\n", ((PMODE_PARAMETER_HEADER
) modeData
)->MediumType
));
1700 ExFreePool(modeData
);
1707 // If the length is greater than length indiated by the mode data reset
1708 // the data to the mode data.
1710 if (length
> (ULONG
)((PMODE_PARAMETER_HEADER
) modeData
)->ModeDataLength
+ 1) {
1711 length
= (ULONG
)((PMODE_PARAMETER_HEADER
) modeData
)->ModeDataLength
+ 1;
1716 // Look for the flexible disk mode page.
1719 pageData
= ClassFindModePage( modeData
, length
, MODE_PAGE_FLEXIBILE
, TRUE
);
1721 if (pageData
!= NULL
) {
1723 DebugPrint((1, "ScsiFlop: Flexible disk page found, This is a floppy.\n"));
1726 // As a special case for the floptical driver do a magic mode sense to
1727 // enable the drive.
1730 ClassModeSense(DeviceObject
, modeData
, 0x2a, 0x2e);
1732 ExFreePool(modeData
);
1737 ExFreePool(modeData
);
1746 PDEVICE_OBJECT DeviceObject
1750 Routine Description:
1752 This routine determines the floppy media type based on the size of the
1753 device. The geometry information is set for the device object.
1757 DeviceObject - Supplies the device object to be tested.
1765 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1766 PDISK_GEOMETRY geometry
;
1772 geometry
= &(fdoExtension
->DiskGeometry
);
1775 // Issue ReadCapacity to update device extension
1776 // with information for current media.
1779 status
= ClassReadDriveCapacity(DeviceObject
);
1781 if (!NT_SUCCESS(status
)) {
1784 // Set the media type to unknow and zero the geometry information.
1787 geometry
->MediaType
= Unknown
;
1794 // Look at the capcity of disk to determine its type.
1797 for (index
= NUMBER_OF_DRIVE_MEDIA_COMBINATIONS
- 1; index
>= 0; index
--) {
1800 // Walk the table backward untill the drive capacity holds all of the
1801 // data and the bytes per setor are equal
1804 if ((ULONG
) (DriveMediaConstants
[index
].NumberOfHeads
*
1805 (DriveMediaConstants
[index
].MaximumTrack
+ 1) *
1806 DriveMediaConstants
[index
].SectorsPerTrack
*
1807 DriveMediaConstants
[index
].BytesPerSector
) <=
1808 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
&&
1809 DriveMediaConstants
[index
].BytesPerSector
==
1810 geometry
->BytesPerSector
) {
1812 geometry
->MediaType
= DriveMediaConstants
[index
].MediaType
;
1813 geometry
->TracksPerCylinder
= DriveMediaConstants
[index
].NumberOfHeads
;
1814 geometry
->SectorsPerTrack
= DriveMediaConstants
[index
].SectorsPerTrack
;
1815 geometry
->Cylinders
.LowPart
= DriveMediaConstants
[index
].MaximumTrack
+1;
1823 // Set the media type to unknow and zero the geometry information.
1826 geometry
->MediaType
= Unknown
;
1831 // DMF check breaks the insight SCSI floppy, so its disabled for that case
1833 PDISK_DATA diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
1835 // if (diskData->EnableDMF == TRUE) {
1838 //check to see if DMF
1841 PSCSI_REQUEST_BLOCK srb
;
1845 // Allocate a Srb for the read command.
1849 readData
= ExAllocatePool(NonPagedPoolNx
, geometry
->BytesPerSector
);
1851 readData
= ExAllocatePool(NonPagedPool
, geometry
->BytesPerSector
);
1853 if (readData
== NULL
) {
1854 return STATUS_NO_MEMORY
;
1858 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
1860 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
1865 ExFreePool(readData
);
1866 return STATUS_NO_MEMORY
;
1869 RtlZeroMemory(readData
, geometry
->BytesPerSector
);
1870 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
1872 srb
->CdbLength
= 10;
1873 srb
->Cdb
[0] = SCSIOP_READ
;
1875 srb
->Cdb
[8] = (UCHAR
) 1;
1878 // Set timeout value.
1881 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
1884 // Send the mode select data.
1887 status
= ClassSendSrbSynchronous(DeviceObject
,
1890 geometry
->BytesPerSector
,
1894 if (NT_SUCCESS(status
)) {
1895 char *pchar
= (char *)readData
;
1897 pchar
+= 3; //skip 3 bytes jump code
1899 // If the MSDMF3. signature is there then mark it as DMF diskette
1900 if (RtlCompareMemory(pchar
, "MSDMF3.", 7) == 7) {
1901 diskData
->IsDMF
= TRUE
;
1905 ExFreePool(readData
);
1914 PDEVICE_OBJECT DeviceObject
1918 Routine Description:
1920 The routine determines the device type so that the supported medias can be
1921 determined. It does a mode sense for the default parameters. This code
1922 assumes that the returned values are for the maximum device size.
1926 DeviceObject - Supplies the device object to be tested.
1934 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
1936 PDISK_DATA diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
1937 PMODE_FLEXIBLE_DISK_PAGE pageData
;
1940 UCHAR numberOfHeads
;
1941 UCHAR sectorsPerTrack
;
1942 USHORT maximumTrack
;
1943 BOOLEAN applyFix
= FALSE
;
1947 if (diskData
->DriveType
!= DRIVE_TYPE_NONE
) {
1948 return(diskData
->DriveType
);
1952 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
1954 modeData
= ExAllocatePool(NonPagedPoolCacheAligned
, MODE_DATA_SIZE
);
1957 if (modeData
== NULL
) {
1958 return(DRIVE_TYPE_NONE
);
1961 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
1963 length
= ClassModeSense(DeviceObject
,
1966 MODE_PAGE_FLEXIBILE
);
1968 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1971 // Retry the request one more time
1972 // in case of a check condition.
1974 length
= ClassModeSense(DeviceObject
,
1977 MODE_PAGE_FLEXIBILE
);
1979 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
1981 ExFreePool(modeData
);
1982 return(DRIVE_TYPE_NONE
);
1987 // Look for the flexible disk mode page.
1990 pageData
= ClassFindModePage( modeData
,
1992 MODE_PAGE_FLEXIBILE
,
1996 // Make sure the page is returned and is large enough.
1999 if ((pageData
!= NULL
) &&
2000 (pageData
->PageLength
+ 2 >=
2001 (UCHAR
)offsetof(MODE_FLEXIBLE_DISK_PAGE
, StartWritePrecom
))) {
2004 // Pull out the heads, cylinders, and sectors.
2007 numberOfHeads
= pageData
->NumberOfHeads
;
2008 maximumTrack
= pageData
->NumberOfCylinders
[1];
2009 maximumTrack
|= pageData
->NumberOfCylinders
[0] << 8;
2010 sectorsPerTrack
= pageData
->SectorsPerTrack
;
2014 // Convert from number of cylinders to maximum track.
2020 // Search for the maximum supported media. Based on the number of heads,
2021 // sectors per track and number of cylinders
2023 for (index
= 0; index
< NUMBER_OF_DRIVE_MEDIA_COMBINATIONS
; index
++) {
2026 // Walk the table forward until the drive capacity holds all of the
2027 // data and the bytes per setor are equal
2030 if (DriveMediaConstants
[index
].NumberOfHeads
== numberOfHeads
&&
2031 DriveMediaConstants
[index
].MaximumTrack
== maximumTrack
&&
2032 DriveMediaConstants
[index
].SectorsPerTrack
==sectorsPerTrack
) {
2034 ExFreePool(modeData
);
2037 // index is now a drive media combination. Compare this to
2038 // the maximum drive media type in the drive media table.
2041 for (length
= 0; length
< NUMBER_OF_DRIVE_TYPES
; length
++) {
2043 if (DriveMediaLimits
[length
].HighestDriveMediaType
== index
) {
2047 return(DRIVE_TYPE_NONE
);
2051 // If the maximum track is greater than 8 bits then divide the
2052 // number of tracks by 3 and multiply the number of heads by 3.
2053 // This is a special case for the 20.8 MB floppy.
2056 if (!applyFix
&& maximumTrack
>= 0x0100) {
2062 ExFreePool(modeData
);
2063 return(DRIVE_TYPE_NONE
);
2068 ExFreePool(modeData
);
2069 return(DRIVE_TYPE_NONE
);
2074 FlCheckFormatParameters(
2075 IN PDEVICE_OBJECT DeviceObject
,
2076 IN PFORMAT_PARAMETERS FormatParameters
2081 Routine Description:
2083 This routine checks the supplied format parameters to make sure that
2084 they'll work on the drive to be formatted.
2088 DeviceObject - Pointer to the device object to be formated.
2090 FormatParameters - a pointer to the caller's parameters for the FORMAT.
2094 TRUE if parameters are OK.
2095 FALSE if the parameters are bad.
2100 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2101 DRIVE_MEDIA_TYPE driveMediaType
;
2107 // Get the device type.
2110 index
= DetermineDriveType(DeviceObject
);
2112 if (index
== DRIVE_TYPE_NONE
) {
2115 // If the determine device type failed then just use the media type
2116 // and try the parameters.
2119 driveMediaType
= Drive360Media160
;
2121 while (( DriveMediaConstants
[driveMediaType
].MediaType
!=
2122 FormatParameters
->MediaType
) &&
2123 ( driveMediaType
< Drive288Media288
) ) {
2131 // Figure out which entry in the DriveMediaConstants table to use.
2135 DriveMediaLimits
[index
].HighestDriveMediaType
;
2137 while ( ( DriveMediaConstants
[driveMediaType
].MediaType
!=
2138 FormatParameters
->MediaType
) &&
2139 ( driveMediaType
> DriveMediaLimits
[index
].
2140 LowestDriveMediaType
) ) {
2148 // driveMediaType is bounded below by DriveMediaLimits[].LowestDriveMediaType
2149 #if !defined(__REACTOS__) || defined(_MSC_VER)
2150 #pragma warning(push)
2151 #pragma warning(disable:33010) // 33010: Enum used as array index may be negative
2153 if ( DriveMediaConstants
[driveMediaType
].MediaType
!=
2154 FormatParameters
->MediaType
) {
2159 driveMediaConstants
= &DriveMediaConstants
[driveMediaType
];
2161 if ( ( FormatParameters
->StartHeadNumber
>
2162 (ULONG
)( driveMediaConstants
->NumberOfHeads
- 1 ) ) ||
2163 ( FormatParameters
->EndHeadNumber
>
2164 (ULONG
)( driveMediaConstants
->NumberOfHeads
- 1 ) ) ||
2165 ( FormatParameters
->StartCylinderNumber
>
2166 driveMediaConstants
->MaximumTrack
) ||
2167 ( FormatParameters
->EndCylinderNumber
>
2168 driveMediaConstants
->MaximumTrack
) ||
2169 ( FormatParameters
->EndCylinderNumber
<
2170 FormatParameters
->StartCylinderNumber
) ) {
2179 #if !defined(__REACTOS__) || defined(_MSC_VER)
2180 #pragma warning(pop)
2186 PDEVICE_OBJECT DeviceObject
,
2187 MEDIA_TYPE MediaType
2191 Routine Description:
2193 This routine formats the floppy disk. The entire floppy is formated in
2198 DeviceObject - Supplies the device object to be tested.
2200 Irp - Supplies a pointer to the requesting Irp.
2202 MediaType - Supplies the media type format the device for.
2206 Returns a status for the operation.
2211 PSCSI_REQUEST_BLOCK srb
;
2212 PMODE_FLEXIBLE_DISK_PAGE pageData
;
2213 DRIVE_MEDIA_TYPE driveMediaType
;
2214 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2221 modeData
= ExAllocatePool(NonPagedPoolNxCacheAligned
, MODE_DATA_SIZE
);
2223 modeData
= ExAllocatePool(NonPagedPoolCacheAligned
, MODE_DATA_SIZE
);
2226 if (modeData
== NULL
) {
2227 return(STATUS_INSUFFICIENT_RESOURCES
);
2230 RtlZeroMemory(modeData
, MODE_DATA_SIZE
);
2232 length
= ClassModeSense(DeviceObject
,
2235 MODE_PAGE_FLEXIBILE
);
2237 if (length
< sizeof(MODE_PARAMETER_HEADER
)) {
2238 ExFreePool(modeData
);
2239 return(STATUS_INVALID_DEVICE_REQUEST
);
2243 // Look for the flexible disk mode page.
2246 pageData
= ClassFindModePage( modeData
, length
, MODE_PAGE_FLEXIBILE
, TRUE
);
2249 // Make sure the page is returned and is large enough.
2252 if ((pageData
== NULL
) ||
2253 (pageData
->PageLength
+ 2 <
2254 (UCHAR
)offsetof(MODE_FLEXIBLE_DISK_PAGE
, StartWritePrecom
))) {
2256 ExFreePool(modeData
);
2257 return(STATUS_INVALID_DEVICE_REQUEST
);
2262 // Look for a drive media type which matches the requested media type.
2265 //start from Drive120MMedia120M instead of Drive2080Media2080
2267 for (driveMediaType
= Drive120MMedia120M
;
2268 DriveMediaConstants
[driveMediaType
].MediaType
!= MediaType
;
2270 if (driveMediaType
== Drive360Media160
) {
2272 ExFreePool(modeData
);
2273 return(STATUS_INVALID_PARAMETER
);
2278 driveMediaConstants
= &DriveMediaConstants
[driveMediaType
];
2280 if ((pageData
->NumberOfHeads
!= driveMediaConstants
->NumberOfHeads
) ||
2281 (pageData
->SectorsPerTrack
!= driveMediaConstants
->SectorsPerTrack
) ||
2282 ((pageData
->NumberOfCylinders
[0] != (UCHAR
)((driveMediaConstants
->MaximumTrack
+1) >> 8)) &&
2283 (pageData
->NumberOfCylinders
[1] != (UCHAR
)driveMediaConstants
->MaximumTrack
+1)) ||
2284 (pageData
->BytesPerSector
[0] != driveMediaConstants
->BytesPerSector
>> 8 )) {
2287 // Update the flexible parameters page with the new parameters.
2290 pageData
->NumberOfHeads
= driveMediaConstants
->NumberOfHeads
;
2291 pageData
->SectorsPerTrack
= driveMediaConstants
->SectorsPerTrack
;
2292 pageData
->NumberOfCylinders
[0] = (UCHAR
)((driveMediaConstants
->MaximumTrack
+1) >> 8);
2293 pageData
->NumberOfCylinders
[1] = (UCHAR
)driveMediaConstants
->MaximumTrack
+1;
2294 pageData
->BytesPerSector
[0] = driveMediaConstants
->BytesPerSector
>> 8;
2297 // Clear the mode parameter header.
2300 RtlZeroMemory(modeData
, sizeof(MODE_PARAMETER_HEADER
));
2303 // Set the length equal to the length returned for the flexible page.
2306 length
= pageData
->PageLength
+ 2;
2309 // Copy the page after the mode parameter header.
2312 RtlMoveMemory((PCHAR
) modeData
+ sizeof(MODE_PARAMETER_HEADER
),
2316 length
+= sizeof(MODE_PARAMETER_HEADER
);
2320 // Allocate a Srb for the format command.
2324 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
2326 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
2331 ExFreePool(modeData
);
2332 return(STATUS_INSUFFICIENT_RESOURCES
);
2335 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2338 srb
->Cdb
[0] = SCSIOP_MODE_SELECT
;
2339 srb
->Cdb
[4] = (UCHAR
) length
;
2345 srb
->Cdb
[1] |= 0x10;
2348 // Set timeout value.
2351 srb
->TimeOutValue
= 2;
2354 // Send the mode select data.
2357 status
= ClassSendSrbSynchronous(DeviceObject
,
2365 // The mode data not needed any more so free it.
2368 ExFreePool(modeData
);
2370 if (!NT_SUCCESS(status
)) {
2378 // The mode data not needed any more so free it.
2381 ExFreePool(modeData
);
2384 // Allocate a Srb for the format command.
2388 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
2390 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
2394 return(STATUS_INSUFFICIENT_RESOURCES
);
2399 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2403 srb
->Cdb
[0] = SCSIOP_FORMAT_UNIT
;
2406 // Set timeout value.
2409 srb
->TimeOutValue
= 10 * 60;
2411 status
= ClassSendSrbSynchronous(DeviceObject
,
2427 ScsiFlopProcessError(
2428 PDEVICE_OBJECT DeviceObject
,
2429 PSCSI_REQUEST_BLOCK Srb
,
2435 Routine Description:
2437 This routine checks the type of error. If the error indicate the floppy
2438 controller needs to be reinitialize a command is made to do it.
2442 DeviceObject - Supplies a pointer to the device object.
2444 Srb - Supplies a pointer to the failing Srb.
2446 Status - Status with which the IRP will be completed.
2448 Retry - Indication of whether the request will be retried.
2457 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
2458 PDISK_DATA diskData
= (PDISK_DATA
) fdoExtension
->CommonExtension
.DriverData
;
2459 PSENSE_DATA senseBuffer
= Srb
->SenseInfoBuffer
;
2460 PIO_STACK_LOCATION irpStack
;
2462 PSCSI_REQUEST_BLOCK srb
;
2463 LARGE_INTEGER largeInt
;
2464 PCOMPLETION_CONTEXT context
;
2466 ULONG_PTR alignment
;
2467 ULONG majorFunction
;
2469 UNREFERENCED_PARAMETER(Status
);
2470 UNREFERENCED_PARAMETER(Retry
);
2472 largeInt
.QuadPart
= 1;
2475 // Check the status. The initialization command only needs to be sent
2476 // if UNIT ATTENTION or LUN NOT READY is returned.
2479 if (!(Srb
->SrbStatus
& SRB_STATUS_AUTOSENSE_VALID
)) {
2482 // The drive does not require reinitialization.
2489 // Reset the drive type.
2492 diskData
->DriveType
= DRIVE_TYPE_NONE
;
2493 diskData
->IsDMF
= FALSE
;
2495 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
2497 if (fdoExtension
->AdapterDescriptor
->BusType
== BusTypeUsb
) {
2499 // FLPYDISK.SYS never returns a non-zero value for the ChangeCount
2500 // on an IOCTL_DISK_CHECK_VERIFY. Some things seem to work better
2501 // if we do the same. In particular, FatVerifyVolume() can exit between
2502 // the IOCTL_DISK_CHECK_VERIFY and the IOCTL_DISK_GET_DRIVE_GEOMETRY
2503 // if a non-zero ChangeCount is returned, and this appears to cause
2504 // issues formatting unformatted media in some situations.
2506 // This is something that should probably be revisited at some point.
2508 fdoExtension
->MediaChangeCount
= 0;
2510 if (((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) &&
2511 (senseBuffer
->AdditionalSenseCode
== SCSI_ADSENSE_MEDIUM_CHANGED
)) {
2513 struct _START_STOP
*startStopCdb
;
2515 DebugPrint((2,"Sending SCSIOP_START_STOP_UNIT\n"));
2518 context
= ExAllocatePool(NonPagedPoolNx
,
2519 sizeof(COMPLETION_CONTEXT
));
2521 context
= ExAllocatePool(NonPagedPool
,
2522 sizeof(COMPLETION_CONTEXT
));
2525 if (context
== NULL
) {
2529 #if (NTDDI_VERSION >= NTDDI_WIN8)
2530 srb
= &context
->Srb
.Srb
;
2532 srb
= &context
->Srb
;
2535 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2537 srb
->SrbFlags
= SRB_FLAGS_DISABLE_AUTOSENSE
;
2541 startStopCdb
= (struct _START_STOP
*)srb
->Cdb
;
2543 startStopCdb
->OperationCode
= SCSIOP_START_STOP_UNIT
;
2544 startStopCdb
->Start
= 1;
2546 // A Start Stop Unit request has no transfer buffer.
2547 // Set the request to IRP_MJ_FLUSH_BUFFERS when calling
2548 // IoBuildAsynchronousFsdRequest() so that it ignores
2549 // the buffer pointer and buffer length parameters.
2551 majorFunction
= IRP_MJ_FLUSH_BUFFERS
;
2553 } else if ((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_MEDIUM_ERROR
) {
2555 // Return ERROR_UNRECOGNIZED_MEDIA instead of
2556 // STATUS_DEVICE_DATA_ERROR to make shell happy.
2558 *Status
= STATUS_UNRECOGNIZED_MEDIA
;
2567 } else if (((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_NOT_READY
) &&
2568 senseBuffer
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_INIT_COMMAND_REQUIRED
||
2569 (senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) {
2571 } else if ((((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_NOT_READY
) &&
2572 senseBuffer
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_INIT_COMMAND_REQUIRED
) ||
2573 (senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) {
2580 DebugPrint((1, "ScsiFlopProcessError: Reinitializing the floppy.\n"));
2583 // Send the special mode sense command to enable writes on the
2587 alignment
= DeviceObject
->AlignmentRequirement
?
2588 DeviceObject
->AlignmentRequirement
: 1;
2592 if (SUCCEEDED(ULongAdd(sizeof(COMPLETION_CONTEXT
), 0x2a, &tmpSize
))) {
2594 if (SUCCEEDED(ULongAdd(tmpSize
, (ULONG
) alignment
, &sizeNeeded
))) {
2603 context
= ExAllocatePool(NonPagedPoolNx
, sizeNeeded
);
2605 context
= ExAllocatePool(NonPagedPool
, sizeNeeded
);
2609 if (context
== NULL
) {
2612 // If there is not enough memory to fulfill this request,
2613 // simply return. A subsequent retry will fail and another
2614 // chance to start the unit.
2620 #if (NTDDI_VERSION >= NTDDI_WIN8)
2621 srb
= &context
->Srb
.Srb
;
2623 srb
= &context
->Srb
;
2626 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2629 // Set the transfer length.
2632 srb
->DataTransferLength
= 0x2a;
2633 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_AUTOSENSE
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2636 // The data buffer must be aligned.
2639 srb
->DataBuffer
= (PVOID
) (((ULONG_PTR
) (context
+ 1) + (alignment
- 1)) &
2644 // Build the start unit CDB.
2648 cdb
= (PCDB
)srb
->Cdb
;
2649 cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
2650 cdb
->MODE_SENSE
.PageCode
= 0x2e;
2651 cdb
->MODE_SENSE
.AllocationLength
= 0x2a;
2653 majorFunction
= IRP_MJ_READ
;
2660 context
->DeviceObject
= DeviceObject
;
2663 // Write length to SRB.
2666 srb
->Length
= SCSI_REQUEST_BLOCK_SIZE
;
2668 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2669 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
2672 // Build the asynchronous request
2673 // to be sent to the port driver.
2676 irp
= IoBuildAsynchronousFsdRequest(majorFunction
,
2679 srb
->DataTransferLength
,
2684 ExFreePool(context
);
2689 IoSetCompletionRoutine(irp
,
2690 (PIO_COMPLETION_ROUTINE
)ClassAsynchronousCompletion
,
2696 ClassAcquireRemoveLock(DeviceObject
, irp
);
2698 irpStack
= IoGetNextIrpStackLocation(irp
);
2700 irpStack
->MajorFunction
= IRP_MJ_SCSI
;
2702 srb
->OriginalRequest
= irp
;
2705 // Save SRB address in next stack for port driver.
2708 irpStack
->Parameters
.Others
.Argument1
= (PVOID
)srb
;
2711 // Can't release the remove lock yet - let ClassAsynchronousCompletion
2712 // take care of that for us.
2715 (VOID
)IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, irp
);
2721 FlopticalFormatMedia(
2722 PDEVICE_OBJECT DeviceObject
,
2723 PFORMAT_PARAMETERS Format
2727 Routine Description:
2729 This routine is used to do perform a format tracks for the 20.8 MB
2730 floppy. Because the device does not support format tracks and the full
2731 format takes a long time a write of zeros is done instead.
2735 DeviceObject - Supplies the device object to be tested.
2737 Format - Supplies the format parameters.
2741 Returns a status for the operation.
2745 IO_STATUS_BLOCK ioStatus
;
2748 LARGE_INTEGER offset
;
2751 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2756 driveMediaConstants
= &DriveMediaConstants
[Drive2080Media2080
];
2759 // Calculate the length of the buffer.
2762 length
= ((Format
->EndCylinderNumber
- Format
->StartCylinderNumber
) *
2763 driveMediaConstants
->NumberOfHeads
+
2764 Format
->EndHeadNumber
- Format
->StartHeadNumber
+ 1) *
2765 driveMediaConstants
->SectorsPerTrack
*
2766 driveMediaConstants
->BytesPerSector
;
2769 buffer
= ExAllocatePool(NonPagedPoolNxCacheAligned
, length
);
2771 buffer
= ExAllocatePool(NonPagedPoolCacheAligned
, length
);
2774 if (buffer
== NULL
) {
2775 return(STATUS_INSUFFICIENT_RESOURCES
);
2778 RtlZeroMemory(buffer
, length
);
2781 (Format
->StartCylinderNumber
* driveMediaConstants
->NumberOfHeads
+
2782 Format
->StartHeadNumber
) * driveMediaConstants
->SectorsPerTrack
*
2783 driveMediaConstants
->BytesPerSector
;
2786 // Set the event object to the unsignaled state.
2787 // It will be used to signal request completion.
2790 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
2793 // Build the synchronous request with data transfer.
2796 irp
= IoBuildSynchronousFsdRequest(
2806 status
= IoCallDriver(DeviceObject
, irp
);
2808 if (status
== STATUS_PENDING
) {
2811 // Wait for the request to complete if necessary.
2814 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
2818 // If the call driver suceeded then set the status to the status block.
2821 if (NT_SUCCESS(status
)) {
2822 status
= ioStatus
.Status
;
2825 status
= STATUS_INSUFFICIENT_RESOURCES
;
2839 ScsiFlopRemoveDevice(
2840 IN PDEVICE_OBJECT DeviceObject
,
2845 Routine Description:
2847 This routine is responsible for releasing any resources in use by the
2848 sfloppy driver. This routine is called
2849 when all outstanding requests have been completed and the driver has
2850 disappeared - no requests may be issued to the lower drivers.
2854 DeviceObject - the device object being removed
2856 Type - the type of remove operation (QUERY, REMOVE or CANCEL)
2860 for a query - success if the device can be removed or a failure code
2861 indiciating why not.
2863 for a remove or cancel - STATUS_SUCCESS
2868 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension
=
2869 DeviceObject
->DeviceExtension
;
2870 PDISK_DATA diskData
= deviceExtension
->CommonExtension
.DriverData
;
2875 if((Type
== IRP_MN_QUERY_REMOVE_DEVICE
) ||
2876 (Type
== IRP_MN_CANCEL_REMOVE_DEVICE
)) {
2877 return STATUS_SUCCESS
;
2880 if (Type
== IRP_MN_REMOVE_DEVICE
){
2881 if(deviceExtension
->DeviceDescriptor
) {
2882 ExFreePool(deviceExtension
->DeviceDescriptor
);
2883 deviceExtension
->DeviceDescriptor
= NULL
;
2886 if(deviceExtension
->AdapterDescriptor
) {
2887 ExFreePool(deviceExtension
->AdapterDescriptor
);
2888 deviceExtension
->AdapterDescriptor
= NULL
;
2891 if(deviceExtension
->SenseData
) {
2892 ExFreePool(deviceExtension
->SenseData
);
2893 deviceExtension
->SenseData
= NULL
;
2896 ClassDeleteSrbLookasideList(&deviceExtension
->CommonExtension
);
2899 if(diskData
->FloppyInterfaceString
.Buffer
!= NULL
) {
2901 status
= IoSetDeviceInterfaceState(
2902 &(diskData
->FloppyInterfaceString
),
2905 if (!NT_SUCCESS(status
)) {
2906 // Failed to disable device interface during removal. Not a fatal error.
2907 DebugPrint((1, "ScsiFlopRemoveDevice: Unable to set device "
2908 "interface state to FALSE for fdo %p "
2910 DeviceObject
, status
));
2913 RtlFreeUnicodeString(&(diskData
->FloppyInterfaceString
));
2914 RtlInitUnicodeString(&(diskData
->FloppyInterfaceString
), NULL
);
2917 if(Type
== IRP_MN_REMOVE_DEVICE
) {
2918 IoGetConfigurationInformation()->FloppyCount
--;
2921 return STATUS_SUCCESS
;
2930 IN PDEVICE_OBJECT DeviceObject
,
2934 UNREFERENCED_PARAMETER(DeviceObject
);
2935 UNREFERENCED_PARAMETER(Type
);
2937 return STATUS_SUCCESS
;
2942 USBFlopGetMediaTypes(
2943 IN PDEVICE_OBJECT DeviceObject
,
2949 Routine Description:
2951 This routines determines the current or default geometry of the drive
2952 for IOCTL_DISK_GET_DRIVE_GEOMETRY, or all currently supported geometries
2953 of the drive (which is determined by its currently inserted media) for
2954 IOCTL_DISK_GET_MEDIA_TYPES.
2956 The returned geometries are determined by issuing a Read Format Capacities
2957 request and then matching the returned {Number of Blocks, Block Length}
2958 pairs in a table of known floppy geometries.
2962 DeviceObject - Supplies the device object.
2964 Irp - A IOCTL_DISK_GET_DRIVE_GEOMETRY or a IOCTL_DISK_GET_MEDIA_TYPES Irp.
2965 If NULL, the device geometry is updated with the current device
2973 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
2974 PIO_STACK_LOCATION irpStack
;
2975 ULONG ioControlCode
;
2976 PDISK_GEOMETRY outputBuffer
;
2977 PDISK_GEOMETRY outputBufferEnd
;
2978 ULONG outputBufferLength
;
2979 PSCSI_REQUEST_BLOCK srb
;
2981 ULONG dataTransferLength
;
2982 struct _READ_FORMATTED_CAPACITIES
*cdb
;
2983 PFORMATTED_CAPACITY_LIST capList
;
2988 fdoExtension
= DeviceObject
->DeviceExtension
;
2992 // Get the Irp parameters
2994 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
2996 ioControlCode
= irpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
2998 Irp
->IoStatus
.Information
= 0;
3000 outputBuffer
= (PDISK_GEOMETRY
) Irp
->AssociatedIrp
.SystemBuffer
;
3002 outputBufferLength
= irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
3004 if (outputBufferLength
< sizeof(DISK_GEOMETRY
))
3006 return STATUS_BUFFER_TOO_SMALL
;
3009 // Pointer arithmetic to allow multiple DISK_GEOMETRY's to be returned.
3010 // Rounds BufferEnd down to integral multiple of DISK_GEOMETRY structs.
3012 outputBufferEnd
= outputBuffer
+
3013 outputBufferLength
/ sizeof(DISK_GEOMETRY
);
3017 // No Irp to return the result in, just update the current geometry
3018 // in the device extension.
3020 ioControlCode
= IOCTL_DISK_GET_DRIVE_GEOMETRY
;
3022 outputBuffer
= NULL
;
3024 outputBufferEnd
= NULL
;
3026 outputBufferLength
= 0;
3029 if (ioControlCode
== IOCTL_DISK_GET_DRIVE_GEOMETRY
) {
3031 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
3033 status
= ClassReadDriveCapacity(DeviceObject
);
3035 if (!NT_SUCCESS(status
))
3037 // If the media is not recongized, we want to return the default
3038 // geometry so that the media can be formatted. Unrecognized media
3039 // causes SCSI_SENSE_MEDIUM_ERROR, which gets reported as
3040 // STATUS_DEVICE_DATA_ERROR. Ignore these errors, but return other
3041 // errors, such as STATUS_NO_MEDIA_IN_DEVICE.
3043 if (status
!= STATUS_UNRECOGNIZED_MEDIA
)
3045 DebugPrint((2,"IOCTL_DISK_GET_DRIVE_GEOMETRY returns %08X\n", status
));
3052 // Allocate an SRB for the SCSIOP_READ_FORMATTED_CAPACITY request
3055 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
3057 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
3062 return STATUS_INSUFFICIENT_RESOURCES
;
3065 // Allocate a transfer buffer for the SCSIOP_READ_FORMATTED_CAPACITY request
3066 // The length of the returned descriptor array is limited to a byte field
3067 // in the capacity list header.
3069 dataTransferLength
= sizeof(FORMATTED_CAPACITY_LIST
) +
3070 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3072 ASSERT(dataTransferLength
< 0x100);
3075 dataBuffer
= ExAllocatePool(NonPagedPoolNx
, dataTransferLength
);
3077 dataBuffer
= ExAllocatePool(NonPagedPool
, dataTransferLength
);
3080 if (dataBuffer
== NULL
)
3083 return STATUS_INSUFFICIENT_RESOURCES
;
3086 // Initialize the SRB and CDB
3088 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
3090 RtlZeroMemory(dataBuffer
, dataTransferLength
);
3092 srb
->CdbLength
= sizeof(struct _READ_FORMATTED_CAPACITIES
);
3094 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3096 cdb
= (struct _READ_FORMATTED_CAPACITIES
*)srb
->Cdb
;
3098 cdb
->OperationCode
= SCSIOP_READ_FORMATTED_CAPACITY
;
3099 cdb
->AllocationLength
[1] = (UCHAR
)dataTransferLength
;
3102 // Send down the SCSIOP_READ_FORMATTED_CAPACITY request
3104 status
= ClassSendSrbSynchronous(DeviceObject
,
3110 capList
= (PFORMATTED_CAPACITY_LIST
)dataBuffer
;
3112 // If we don't get as much data as requested, it is not an error.
3114 if (SRB_STATUS(srb
->SrbStatus
) == SRB_STATUS_DATA_OVERRUN
)
3116 status
= STATUS_SUCCESS
;
3119 if (NT_SUCCESS(status
) &&
3120 srb
->DataTransferLength
>= sizeof(FORMATTED_CAPACITY_LIST
) &&
3121 capList
->CapacityListLength
&&
3122 capList
->CapacityListLength
% sizeof(FORMATTED_CAPACITY_DESCRIPTOR
) == 0)
3124 ULONG NumberOfBlocks
;
3128 LONG currentGeometry
;
3129 BOOLEAN capacityMatches
[FLOPPY_CAPACITIES
];
3131 // Subtract the size of the Capacity List Header to get
3132 // just the size of the Capacity List Descriptor array.
3134 srb
->DataTransferLength
-= sizeof(FORMATTED_CAPACITY_LIST
);
3136 // Only look at the Capacity List Descriptors that were actually
3139 if (srb
->DataTransferLength
< capList
->CapacityListLength
)
3141 count
= srb
->DataTransferLength
/
3142 sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3146 count
= capList
->CapacityListLength
/
3147 sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3150 // Updated only if a match is found for the first Capacity List
3151 // Descriptor returned by the device.
3153 currentGeometry
= -1;
3155 // Initialize the array of capacities that hit a match.
3157 RtlZeroMemory(capacityMatches
, sizeof(capacityMatches
));
3159 // Iterate over each Capacity List Descriptor returned from the device
3160 // and record matching capacities in the capacity match array.
3162 for (i
= 0; i
< count
; i
++)
3164 NumberOfBlocks
= (capList
->Descriptors
[i
].NumberOfBlocks
[0] << 24) +
3165 (capList
->Descriptors
[i
].NumberOfBlocks
[1] << 16) +
3166 (capList
->Descriptors
[i
].NumberOfBlocks
[2] << 8) +
3167 (capList
->Descriptors
[i
].NumberOfBlocks
[3]);
3169 BlockLength
= (capList
->Descriptors
[i
].BlockLength
[0] << 16) +
3170 (capList
->Descriptors
[i
].BlockLength
[1] << 8) +
3171 (capList
->Descriptors
[i
].BlockLength
[2]);
3173 // Given the {NumberOfBlocks, BlockLength} from this Capacity List
3174 // Descriptor, find a matching entry in FloppyCapacities[].
3176 for (j
= 0; j
< FLOPPY_CAPACITIES
; j
++)
3178 if (NumberOfBlocks
== FloppyCapacities
[j
].NumberOfBlocks
&&
3179 BlockLength
== FloppyCapacities
[j
].BlockLength
)
3181 // A matching capacity was found, record it.
3183 capacityMatches
[j
] = TRUE
;
3185 // A match was found for the first Capacity List
3186 // Descriptor returned by the device.
3190 currentGeometry
= j
;
3192 } else if ((capList
->Descriptors
[i
].Valid
) &&
3193 (BlockLength
== FloppyCapacities
[j
].BlockLength
)) {
3199 // Check if this is 32MB media type. 32MB media
3200 // reports variable NumberOfBlocks. So we cannot
3201 // use that to determine the drive type
3203 inx
= DetermineDriveType(DeviceObject
);
3204 if (inx
!= DRIVE_TYPE_NONE
) {
3205 mediaInx
= DriveMediaLimits
[inx
].HighestDriveMediaType
;
3206 if ((DriveMediaConstants
[mediaInx
].MediaType
)
3208 capacityMatches
[j
] = TRUE
;
3211 currentGeometry
= j
;
3219 // Default status is STATUS_UNRECOGNIZED_MEDIA, unless we return
3220 // either STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW.
3222 status
= STATUS_UNRECOGNIZED_MEDIA
;
3224 if (ioControlCode
== IOCTL_DISK_GET_DRIVE_GEOMETRY
) {
3226 if (currentGeometry
!= -1)
3228 // Update the current device geometry
3230 fdoExtension
->DiskGeometry
= FloppyGeometries
[currentGeometry
];
3233 // Calculate sector to byte shift.
3236 WHICH_BIT(fdoExtension
->DiskGeometry
.BytesPerSector
,
3237 fdoExtension
->SectorShift
);
3239 fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
=
3240 (LONGLONG
)FloppyCapacities
[currentGeometry
].NumberOfBlocks
*
3241 FloppyCapacities
[currentGeometry
].BlockLength
;
3243 DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n",
3244 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3245 fdoExtension
->DiskGeometry
.MediaType
,
3246 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3247 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3248 fdoExtension
->DiskGeometry
.BytesPerSector
,
3249 fdoExtension
->SectorShift
,
3250 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3252 // Return the current device geometry
3256 *outputBuffer
= FloppyGeometries
[currentGeometry
];
3258 Irp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
3261 status
= STATUS_SUCCESS
;
3266 // Iterate over the capacities and return the geometry
3267 // corresponding to each matching Capacity List Descriptor
3268 // returned from the device.
3270 // The resulting list should be in sorted ascending order,
3271 // assuming that the FloppyGeometries[] array is in sorted
3274 for (i
= 0; i
< FLOPPY_CAPACITIES
; i
++)
3276 if (capacityMatches
[i
] && FloppyCapacities
[i
].CanFormat
)
3278 if (outputBuffer
< outputBufferEnd
)
3280 *outputBuffer
++ = FloppyGeometries
[i
];
3282 Irp
->IoStatus
.Information
+= sizeof(DISK_GEOMETRY
);
3284 DebugPrint((2,"geometry : %3d %2d %d %2d %4d\n",
3285 FloppyGeometries
[i
].Cylinders
.LowPart
,
3286 FloppyGeometries
[i
].MediaType
,
3287 FloppyGeometries
[i
].TracksPerCylinder
,
3288 FloppyGeometries
[i
].SectorsPerTrack
,
3289 FloppyGeometries
[i
].BytesPerSector
));
3291 status
= STATUS_SUCCESS
;
3295 // We ran out of output buffer room before we ran out
3296 // geometries to return.
3298 status
= STATUS_BUFFER_OVERFLOW
;
3304 else if (NT_SUCCESS(status
))
3306 // The SCSIOP_READ_FORMATTED_CAPACITY request was successful, but
3307 // returned data does not appear valid.
3309 status
= STATUS_UNSUCCESSFUL
;
3312 ExFreePool(dataBuffer
);
3320 USBFlopFormatTracks(
3321 IN PDEVICE_OBJECT DeviceObject
,
3327 Routine Description:
3329 This routines formats the specified tracks. If multiple tracks are
3330 specified, each is formatted with a separate Format Unit request.
3334 DeviceObject - Supplies the device object.
3336 Irp - A IOCTL_DISK_FORMAT_TRACKS Irp.
3343 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
3344 PIO_STACK_LOCATION irpStack
;
3345 PFORMAT_PARAMETERS formatParameters
;
3346 PDISK_GEOMETRY geometry
;
3347 PFORMATTED_CAPACITY capacity
;
3348 PSCSI_REQUEST_BLOCK srb
;
3349 PFORMAT_UNIT_PARAMETER_LIST parameterList
;
3352 ULONG cylinder
, head
;
3353 NTSTATUS status
= STATUS_SUCCESS
;
3357 fdoExtension
= DeviceObject
->DeviceExtension
;
3359 // Get the Irp parameters
3361 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
3363 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
3364 sizeof(FORMAT_PARAMETERS
))
3366 return STATUS_INVALID_PARAMETER
;
3369 formatParameters
= (PFORMAT_PARAMETERS
)Irp
->AssociatedIrp
.SystemBuffer
;
3371 // Find the geometry / capacity entries corresponding to the format
3372 // parameters MediaType
3377 for (i
=0; i
<FLOPPY_CAPACITIES
; i
++)
3379 if (FloppyGeometries
[i
].MediaType
== formatParameters
->MediaType
)
3381 geometry
= &FloppyGeometries
[i
];
3382 capacity
= &FloppyCapacities
[i
];
3388 if (geometry
== NULL
)
3390 return STATUS_INVALID_PARAMETER
;
3393 // Check if the format parameters are valid
3395 if ((formatParameters
->StartCylinderNumber
>
3396 geometry
->Cylinders
.LowPart
- 1) ||
3398 (formatParameters
->EndCylinderNumber
>
3399 geometry
->Cylinders
.LowPart
- 1) ||
3401 (formatParameters
->StartHeadNumber
>
3402 geometry
->TracksPerCylinder
- 1) ||
3404 (formatParameters
->EndHeadNumber
>
3405 geometry
->TracksPerCylinder
- 1) ||
3407 (formatParameters
->StartCylinderNumber
>
3408 formatParameters
->EndCylinderNumber
) ||
3410 (formatParameters
->StartHeadNumber
>
3411 formatParameters
->EndHeadNumber
))
3413 return STATUS_INVALID_PARAMETER
;
3416 // Don't low level format LS-120 media, Imation says it's best to not
3419 if ((formatParameters
->MediaType
== F3_120M_512
) ||
3420 (formatParameters
->MediaType
== F3_240M_512
) ||
3421 (formatParameters
->MediaType
== F3_32M_512
))
3423 return STATUS_SUCCESS
;
3426 // Allocate an SRB for the SCSIOP_FORMAT_UNIT request
3429 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
3431 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
3436 return STATUS_INSUFFICIENT_RESOURCES
;
3439 // Allocate a transfer buffer for the SCSIOP_FORMAT_UNIT parameter list
3442 parameterList
= ExAllocatePool(NonPagedPoolNx
,
3443 sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3445 parameterList
= ExAllocatePool(NonPagedPool
,
3446 sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3449 if (parameterList
== NULL
)
3452 return STATUS_INSUFFICIENT_RESOURCES
;
3455 // Initialize the parameter list
3457 RtlZeroMemory(parameterList
, sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3459 parameterList
->DefectListHeader
.SingleTrack
= 1;
3460 parameterList
->DefectListHeader
.DisableCert
= 1; // TEAC requires this set
3461 parameterList
->DefectListHeader
.FormatOptionsValid
= 1;
3462 parameterList
->DefectListHeader
.DefectListLengthLsb
= 8;
3464 parameterList
->FormatDescriptor
.NumberOfBlocks
[0] =
3465 (UCHAR
)((capacity
->NumberOfBlocks
>> 24) & 0xFF);
3467 parameterList
->FormatDescriptor
.NumberOfBlocks
[1] =
3468 (UCHAR
)((capacity
->NumberOfBlocks
>> 16) & 0xFF);
3470 parameterList
->FormatDescriptor
.NumberOfBlocks
[2] =
3471 (UCHAR
)((capacity
->NumberOfBlocks
>> 8) & 0xFF);
3473 parameterList
->FormatDescriptor
.NumberOfBlocks
[3] =
3474 (UCHAR
)(capacity
->NumberOfBlocks
& 0xFF);
3476 parameterList
->FormatDescriptor
.BlockLength
[0] =
3477 (UCHAR
)((capacity
->BlockLength
>> 16) & 0xFF);
3479 parameterList
->FormatDescriptor
.BlockLength
[1] =
3480 (UCHAR
)((capacity
->BlockLength
>> 8) & 0xFF);
3482 parameterList
->FormatDescriptor
.BlockLength
[2] =
3483 (UCHAR
)(capacity
->BlockLength
& 0xFF);
3486 for (cylinder
= formatParameters
->StartCylinderNumber
;
3487 cylinder
<= formatParameters
->EndCylinderNumber
;
3490 for (head
= formatParameters
->StartHeadNumber
;
3491 head
<= formatParameters
->EndHeadNumber
;
3494 // Initialize the SRB and CDB
3496 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
3498 srb
->CdbLength
= sizeof(CDB12FORMAT
);
3500 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3502 cdb
= (PCDB12FORMAT
)srb
->Cdb
;
3504 cdb
->OperationCode
= SCSIOP_FORMAT_UNIT
;
3505 cdb
->DefectListFormat
= 7;
3507 cdb
->TrackNumber
= (UCHAR
)cylinder
;
3508 cdb
->ParameterListLengthLsb
= sizeof(FORMAT_UNIT_PARAMETER_LIST
);
3510 parameterList
->DefectListHeader
.Side
= (UCHAR
)head
;
3513 // Send down the SCSIOP_FORMAT_UNIT request
3515 status
= ClassSendSrbSynchronous(DeviceObject
,
3518 sizeof(FORMAT_UNIT_PARAMETER_LIST
),
3521 if (!NT_SUCCESS(status
))
3526 if (!NT_SUCCESS(status
))
3532 if (NT_SUCCESS(status
) && formatParameters
->StartCylinderNumber
== 0)
3534 // Update the device geometry
3537 DebugPrint((2,"geometry was: %3d %2d %d %2d %4d %2d %08X\n",
3538 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3539 fdoExtension
->DiskGeometry
.MediaType
,
3540 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3541 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3542 fdoExtension
->DiskGeometry
.BytesPerSector
,
3543 fdoExtension
->SectorShift
,
3544 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3546 fdoExtension
->DiskGeometry
= *geometry
;
3549 // Calculate sector to byte shift.
3552 WHICH_BIT(fdoExtension
->DiskGeometry
.BytesPerSector
,
3553 fdoExtension
->SectorShift
);
3555 fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
=
3556 (LONGLONG
)capacity
->NumberOfBlocks
*
3557 capacity
->BlockLength
;
3559 DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n",
3560 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3561 fdoExtension
->DiskGeometry
.MediaType
,
3562 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3563 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3564 fdoExtension
->DiskGeometry
.BytesPerSector
,
3565 fdoExtension
->SectorShift
,
3566 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3569 // Free everything we allocated
3571 ExFreePool(parameterList
);