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)
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 {{.LowPart
= 80, .HighPart
= 0}, F3_640_512
, 2, 8, 512},
280 {{.LowPart
= 80, .HighPart
= 0}, F3_720_512
, 2, 9, 512},
281 {{.LowPart
= 80, .HighPart
= 0}, F3_1Pt2_512
, 2, 15, 512},
282 {{.LowPart
= 77, .HighPart
= 0}, F3_1Pt23_1024
, 2, 8, 1024},
283 {{.LowPart
= 80, .HighPart
= 0}, F3_1Pt44_512
, 2, 18, 512},
284 {{.LowPart
= 80, .HighPart
= 0}, F3_1Pt44_512
, 2, 21, 512}, // DMF -> F3_1Pt44_512
285 {{.LowPart
= 1024, .HighPart
= 0}, F3_32M_512
, 2, 32, 512},
286 {{.LowPart
= 963, .HighPart
= 0}, F3_120M_512
, 8, 32, 512},
287 {{.LowPart
= 890, .HighPart
= 0}, F3_200Mb_512
, 13, 34, 512},
288 {{.LowPart
= 262, .HighPart
= 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
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
,
702 sizeof(name
)/sizeof(UCHAR
),
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()
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
);
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
)/sizeof(WCHAR
),
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
)/sizeof(WCHAR
),
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
)/sizeof(WCHAR
),
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
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
) ) {
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
,
2520 context
= ExAllocatePool(NonPagedPool
,
2522 sizeof(COMPLETION_CONTEXT
));
2524 if (context
== NULL
) {
2528 #if (NTDDI_VERSION >= NTDDI_WIN8)
2529 srb
= &context
->Srb
.Srb
;
2531 srb
= &context
->Srb
;
2534 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2536 srb
->SrbFlags
= SRB_FLAGS_DISABLE_AUTOSENSE
;
2540 startStopCdb
= (struct _START_STOP
*)srb
->Cdb
;
2542 startStopCdb
->OperationCode
= SCSIOP_START_STOP_UNIT
;
2543 startStopCdb
->Start
= 1;
2545 // A Start Stop Unit request has no transfer buffer.
2546 // Set the request to IRP_MJ_FLUSH_BUFFERS when calling
2547 // IoBuildAsynchronousFsdRequest() so that it ignores
2548 // the buffer pointer and buffer length parameters.
2550 majorFunction
= IRP_MJ_FLUSH_BUFFERS
;
2552 } else if ((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_MEDIUM_ERROR
) {
2554 // Return ERROR_UNRECOGNIZED_MEDIA instead of
2555 // STATUS_DEVICE_DATA_ERROR to make shell happy.
2557 *Status
= STATUS_UNRECOGNIZED_MEDIA
;
2566 } else if (((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_NOT_READY
) &&
2567 senseBuffer
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_INIT_COMMAND_REQUIRED
||
2568 (senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) {
2570 } else if ((((senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_NOT_READY
) &&
2571 senseBuffer
->AdditionalSenseCodeQualifier
== SCSI_SENSEQ_INIT_COMMAND_REQUIRED
) ||
2572 (senseBuffer
->SenseKey
& 0xf) == SCSI_SENSE_UNIT_ATTENTION
) {
2579 DebugPrint((1, "ScsiFlopProcessError: Reinitializing the floppy.\n"));
2582 // Send the special mode sense command to enable writes on the
2586 alignment
= DeviceObject
->AlignmentRequirement
?
2587 DeviceObject
->AlignmentRequirement
: 1;
2591 if (SUCCEEDED(ULongAdd(sizeof(COMPLETION_CONTEXT
), 0x2a, &tmpSize
))) {
2593 if (SUCCEEDED(ULongAdd(tmpSize
, (ULONG
) alignment
, &sizeNeeded
))) {
2602 context
= ExAllocatePool(NonPagedPoolNx
, sizeNeeded
);
2604 context
= ExAllocatePool(NonPagedPool
, sizeNeeded
);
2608 if (context
== NULL
) {
2611 // If there is not enough memory to fulfill this request,
2612 // simply return. A subsequent retry will fail and another
2613 // chance to start the unit.
2619 #if (NTDDI_VERSION >= NTDDI_WIN8)
2620 srb
= &context
->Srb
.Srb
;
2622 srb
= &context
->Srb
;
2625 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
2628 // Set the transfer length.
2631 srb
->DataTransferLength
= 0x2a;
2632 srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_DISABLE_AUTOSENSE
| SRB_FLAGS_DISABLE_SYNCH_TRANSFER
;
2635 // The data buffer must be aligned.
2638 srb
->DataBuffer
= (PVOID
) (((ULONG_PTR
) (context
+ 1) + (alignment
- 1)) &
2643 // Build the start unit CDB.
2647 cdb
= (PCDB
)srb
->Cdb
;
2648 cdb
->MODE_SENSE
.OperationCode
= SCSIOP_MODE_SENSE
;
2649 cdb
->MODE_SENSE
.PageCode
= 0x2e;
2650 cdb
->MODE_SENSE
.AllocationLength
= 0x2a;
2652 majorFunction
= IRP_MJ_READ
;
2659 context
->DeviceObject
= DeviceObject
;
2662 // Write length to SRB.
2665 srb
->Length
= SCSI_REQUEST_BLOCK_SIZE
;
2667 srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
2668 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
2671 // Build the asynchronous request
2672 // to be sent to the port driver.
2675 irp
= IoBuildAsynchronousFsdRequest(majorFunction
,
2678 srb
->DataTransferLength
,
2683 ExFreePool(context
);
2688 IoSetCompletionRoutine(irp
,
2689 (PIO_COMPLETION_ROUTINE
)ClassAsynchronousCompletion
,
2695 ClassAcquireRemoveLock(DeviceObject
, irp
);
2697 irpStack
= IoGetNextIrpStackLocation(irp
);
2699 irpStack
->MajorFunction
= IRP_MJ_SCSI
;
2701 srb
->OriginalRequest
= irp
;
2704 // Save SRB address in next stack for port driver.
2707 irpStack
->Parameters
.Others
.Argument1
= (PVOID
)srb
;
2710 // Can't release the remove lock yet - let ClassAsynchronousCompletion
2711 // take care of that for us.
2714 (VOID
)IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, irp
);
2720 FlopticalFormatMedia(
2721 PDEVICE_OBJECT DeviceObject
,
2722 PFORMAT_PARAMETERS Format
2726 Routine Description:
2728 This routine is used to do perform a format tracks for the 20.8 MB
2729 floppy. Because the device does not support format tracks and the full
2730 format takes a long time a write of zeros is done instead.
2734 DeviceObject - Supplies the device object to be tested.
2736 Format - Supplies the format parameters.
2740 Returns a status for the operation.
2744 IO_STATUS_BLOCK ioStatus
;
2747 LARGE_INTEGER offset
;
2750 PDRIVE_MEDIA_CONSTANTS driveMediaConstants
;
2755 driveMediaConstants
= &DriveMediaConstants
[Drive2080Media2080
];
2758 // Calculate the length of the buffer.
2761 length
= ((Format
->EndCylinderNumber
- Format
->StartCylinderNumber
) *
2762 driveMediaConstants
->NumberOfHeads
+
2763 Format
->EndHeadNumber
- Format
->StartHeadNumber
+ 1) *
2764 driveMediaConstants
->SectorsPerTrack
*
2765 driveMediaConstants
->BytesPerSector
;
2768 buffer
= ExAllocatePool(NonPagedPoolNxCacheAligned
, length
);
2770 buffer
= ExAllocatePool(NonPagedPoolCacheAligned
, length
);
2773 if (buffer
== NULL
) {
2774 return(STATUS_INSUFFICIENT_RESOURCES
);
2777 RtlZeroMemory(buffer
, length
);
2780 (Format
->StartCylinderNumber
* driveMediaConstants
->NumberOfHeads
+
2781 Format
->StartHeadNumber
) * driveMediaConstants
->SectorsPerTrack
*
2782 driveMediaConstants
->BytesPerSector
;
2785 // Set the event object to the unsignaled state.
2786 // It will be used to signal request completion.
2789 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
2792 // Build the synchronous request with data transfer.
2795 irp
= IoBuildSynchronousFsdRequest(
2805 status
= IoCallDriver(DeviceObject
, irp
);
2807 if (status
== STATUS_PENDING
) {
2810 // Wait for the request to complete if necessary.
2813 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
2817 // If the call driver suceeded then set the status to the status block.
2820 if (NT_SUCCESS(status
)) {
2821 status
= ioStatus
.Status
;
2824 status
= STATUS_INSUFFICIENT_RESOURCES
;
2838 ScsiFlopRemoveDevice(
2839 IN PDEVICE_OBJECT DeviceObject
,
2844 Routine Description:
2846 This routine is responsible for releasing any resources in use by the
2847 sfloppy driver. This routine is called
2848 when all outstanding requests have been completed and the driver has
2849 disappeared - no requests may be issued to the lower drivers.
2853 DeviceObject - the device object being removed
2855 Type - the type of remove operation (QUERY, REMOVE or CANCEL)
2859 for a query - success if the device can be removed or a failure code
2860 indiciating why not.
2862 for a remove or cancel - STATUS_SUCCESS
2867 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension
=
2868 DeviceObject
->DeviceExtension
;
2869 PDISK_DATA diskData
= deviceExtension
->CommonExtension
.DriverData
;
2874 if((Type
== IRP_MN_QUERY_REMOVE_DEVICE
) ||
2875 (Type
== IRP_MN_CANCEL_REMOVE_DEVICE
)) {
2876 return STATUS_SUCCESS
;
2879 if (Type
== IRP_MN_REMOVE_DEVICE
){
2880 if(deviceExtension
->DeviceDescriptor
) {
2881 ExFreePool(deviceExtension
->DeviceDescriptor
);
2882 deviceExtension
->DeviceDescriptor
= NULL
;
2885 if(deviceExtension
->AdapterDescriptor
) {
2886 ExFreePool(deviceExtension
->AdapterDescriptor
);
2887 deviceExtension
->AdapterDescriptor
= NULL
;
2890 if(deviceExtension
->SenseData
) {
2891 ExFreePool(deviceExtension
->SenseData
);
2892 deviceExtension
->SenseData
= NULL
;
2895 ClassDeleteSrbLookasideList(&deviceExtension
->CommonExtension
);
2898 if(diskData
->FloppyInterfaceString
.Buffer
!= NULL
) {
2900 status
= IoSetDeviceInterfaceState(
2901 &(diskData
->FloppyInterfaceString
),
2904 if (!NT_SUCCESS(status
)) {
2905 // Failed to disable device interface during removal. Not a fatal error.
2906 DebugPrint((1, "ScsiFlopRemoveDevice: Unable to set device "
2907 "interface state to FALSE for fdo %p "
2909 DeviceObject
, status
));
2912 RtlFreeUnicodeString(&(diskData
->FloppyInterfaceString
));
2913 RtlInitUnicodeString(&(diskData
->FloppyInterfaceString
), NULL
);
2916 if(Type
== IRP_MN_REMOVE_DEVICE
) {
2917 IoGetConfigurationInformation()->FloppyCount
--;
2920 return STATUS_SUCCESS
;
2929 IN PDEVICE_OBJECT DeviceObject
,
2933 UNREFERENCED_PARAMETER(DeviceObject
);
2934 UNREFERENCED_PARAMETER(Type
);
2936 return STATUS_SUCCESS
;
2941 USBFlopGetMediaTypes(
2942 IN PDEVICE_OBJECT DeviceObject
,
2948 Routine Description:
2950 This routines determines the current or default geometry of the drive
2951 for IOCTL_DISK_GET_DRIVE_GEOMETRY, or all currently supported geometries
2952 of the drive (which is determined by its currently inserted media) for
2953 IOCTL_DISK_GET_MEDIA_TYPES.
2955 The returned geometries are determined by issuing a Read Format Capacities
2956 request and then matching the returned {Number of Blocks, Block Length}
2957 pairs in a table of known floppy geometries.
2961 DeviceObject - Supplies the device object.
2963 Irp - A IOCTL_DISK_GET_DRIVE_GEOMETRY or a IOCTL_DISK_GET_MEDIA_TYPES Irp.
2964 If NULL, the device geometry is updated with the current device
2972 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
2973 PIO_STACK_LOCATION irpStack
;
2974 ULONG ioControlCode
;
2975 PDISK_GEOMETRY outputBuffer
;
2976 PDISK_GEOMETRY outputBufferEnd
;
2977 ULONG outputBufferLength
;
2978 PSCSI_REQUEST_BLOCK srb
;
2980 ULONG dataTransferLength
;
2981 struct _READ_FORMATTED_CAPACITIES
*cdb
;
2982 PFORMATTED_CAPACITY_LIST capList
;
2987 fdoExtension
= DeviceObject
->DeviceExtension
;
2991 // Get the Irp parameters
2993 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
2995 ioControlCode
= irpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
2997 Irp
->IoStatus
.Information
= 0;
2999 outputBuffer
= (PDISK_GEOMETRY
) Irp
->AssociatedIrp
.SystemBuffer
;
3001 outputBufferLength
= irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
3003 if (outputBufferLength
< sizeof(DISK_GEOMETRY
))
3005 return STATUS_BUFFER_TOO_SMALL
;
3008 // Pointer arithmetic to allow multiple DISK_GEOMETRY's to be returned.
3009 // Rounds BufferEnd down to integral multiple of DISK_GEOMETRY structs.
3011 outputBufferEnd
= outputBuffer
+
3012 outputBufferLength
/ sizeof(DISK_GEOMETRY
);
3016 // No Irp to return the result in, just update the current geometry
3017 // in the device extension.
3019 ioControlCode
= IOCTL_DISK_GET_DRIVE_GEOMETRY
;
3021 outputBuffer
= NULL
;
3023 outputBufferEnd
= NULL
;
3025 outputBufferLength
= 0;
3028 if (ioControlCode
== IOCTL_DISK_GET_DRIVE_GEOMETRY
) {
3030 fdoExtension
->DiskGeometry
.MediaType
= Unknown
;
3032 status
= ClassReadDriveCapacity(DeviceObject
);
3034 if (!NT_SUCCESS(status
))
3036 // If the media is not recongized, we want to return the default
3037 // geometry so that the media can be formatted. Unrecognized media
3038 // causes SCSI_SENSE_MEDIUM_ERROR, which gets reported as
3039 // STATUS_DEVICE_DATA_ERROR. Ignore these errors, but return other
3040 // errors, such as STATUS_NO_MEDIA_IN_DEVICE.
3042 if (status
!= STATUS_UNRECOGNIZED_MEDIA
)
3044 DebugPrint((2,"IOCTL_DISK_GET_DRIVE_GEOMETRY returns %08X\n", status
));
3051 // Allocate an SRB for the SCSIOP_READ_FORMATTED_CAPACITY request
3054 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
3056 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
3061 return STATUS_INSUFFICIENT_RESOURCES
;
3064 // Allocate a transfer buffer for the SCSIOP_READ_FORMATTED_CAPACITY request
3065 // The length of the returned descriptor array is limited to a byte field
3066 // in the capacity list header.
3068 dataTransferLength
= sizeof(FORMATTED_CAPACITY_LIST
) +
3069 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3071 ASSERT(dataTransferLength
< 0x100);
3074 dataBuffer
= ExAllocatePool(NonPagedPoolNx
, dataTransferLength
);
3076 dataBuffer
= ExAllocatePool(NonPagedPool
, dataTransferLength
);
3079 if (dataBuffer
== NULL
)
3082 return STATUS_INSUFFICIENT_RESOURCES
;
3085 // Initialize the SRB and CDB
3087 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
3089 RtlZeroMemory(dataBuffer
, dataTransferLength
);
3091 srb
->CdbLength
= sizeof(struct _READ_FORMATTED_CAPACITIES
);
3093 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3095 cdb
= (struct _READ_FORMATTED_CAPACITIES
*)srb
->Cdb
;
3097 cdb
->OperationCode
= SCSIOP_READ_FORMATTED_CAPACITY
;
3098 cdb
->AllocationLength
[1] = (UCHAR
)dataTransferLength
;
3101 // Send down the SCSIOP_READ_FORMATTED_CAPACITY request
3103 status
= ClassSendSrbSynchronous(DeviceObject
,
3109 capList
= (PFORMATTED_CAPACITY_LIST
)dataBuffer
;
3111 // If we don't get as much data as requested, it is not an error.
3113 if (SRB_STATUS(srb
->SrbStatus
) == SRB_STATUS_DATA_OVERRUN
)
3115 status
= STATUS_SUCCESS
;
3118 if (NT_SUCCESS(status
) &&
3119 srb
->DataTransferLength
>= sizeof(FORMATTED_CAPACITY_LIST
) &&
3120 capList
->CapacityListLength
&&
3121 capList
->CapacityListLength
% sizeof(FORMATTED_CAPACITY_DESCRIPTOR
) == 0)
3123 ULONG NumberOfBlocks
;
3127 LONG currentGeometry
;
3128 BOOLEAN capacityMatches
[FLOPPY_CAPACITIES
];
3130 // Subtract the size of the Capacity List Header to get
3131 // just the size of the Capacity List Descriptor array.
3133 srb
->DataTransferLength
-= sizeof(FORMATTED_CAPACITY_LIST
);
3135 // Only look at the Capacity List Descriptors that were actually
3138 if (srb
->DataTransferLength
< capList
->CapacityListLength
)
3140 count
= srb
->DataTransferLength
/
3141 sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3145 count
= capList
->CapacityListLength
/
3146 sizeof(FORMATTED_CAPACITY_DESCRIPTOR
);
3149 // Updated only if a match is found for the first Capacity List
3150 // Descriptor returned by the device.
3152 currentGeometry
= -1;
3154 // Initialize the array of capacities that hit a match.
3156 RtlZeroMemory(capacityMatches
, sizeof(capacityMatches
));
3158 // Iterate over each Capacity List Descriptor returned from the device
3159 // and record matching capacities in the capacity match array.
3161 for (i
= 0; i
< count
; i
++)
3163 NumberOfBlocks
= (capList
->Descriptors
[i
].NumberOfBlocks
[0] << 24) +
3164 (capList
->Descriptors
[i
].NumberOfBlocks
[1] << 16) +
3165 (capList
->Descriptors
[i
].NumberOfBlocks
[2] << 8) +
3166 (capList
->Descriptors
[i
].NumberOfBlocks
[3]);
3168 BlockLength
= (capList
->Descriptors
[i
].BlockLength
[0] << 16) +
3169 (capList
->Descriptors
[i
].BlockLength
[1] << 8) +
3170 (capList
->Descriptors
[i
].BlockLength
[2]);
3172 // Given the {NumberOfBlocks, BlockLength} from this Capacity List
3173 // Descriptor, find a matching entry in FloppyCapacities[].
3175 for (j
= 0; j
< FLOPPY_CAPACITIES
; j
++)
3177 if (NumberOfBlocks
== FloppyCapacities
[j
].NumberOfBlocks
&&
3178 BlockLength
== FloppyCapacities
[j
].BlockLength
)
3180 // A matching capacity was found, record it.
3182 capacityMatches
[j
] = TRUE
;
3184 // A match was found for the first Capacity List
3185 // Descriptor returned by the device.
3189 currentGeometry
= j
;
3191 } else if ((capList
->Descriptors
[i
].Valid
) &&
3192 (BlockLength
== FloppyCapacities
[j
].BlockLength
)) {
3198 // Check if this is 32MB media type. 32MB media
3199 // reports variable NumberOfBlocks. So we cannot
3200 // use that to determine the drive type
3202 inx
= DetermineDriveType(DeviceObject
);
3203 if (inx
!= DRIVE_TYPE_NONE
) {
3204 mediaInx
= DriveMediaLimits
[inx
].HighestDriveMediaType
;
3205 if ((DriveMediaConstants
[mediaInx
].MediaType
)
3207 capacityMatches
[j
] = TRUE
;
3210 currentGeometry
= j
;
3218 // Default status is STATUS_UNRECOGNIZED_MEDIA, unless we return
3219 // either STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW.
3221 status
= STATUS_UNRECOGNIZED_MEDIA
;
3223 if (ioControlCode
== IOCTL_DISK_GET_DRIVE_GEOMETRY
) {
3225 if (currentGeometry
!= -1)
3227 // Update the current device geometry
3229 fdoExtension
->DiskGeometry
= FloppyGeometries
[currentGeometry
];
3232 // Calculate sector to byte shift.
3235 WHICH_BIT(fdoExtension
->DiskGeometry
.BytesPerSector
,
3236 fdoExtension
->SectorShift
);
3238 fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
=
3239 (LONGLONG
)FloppyCapacities
[currentGeometry
].NumberOfBlocks
*
3240 FloppyCapacities
[currentGeometry
].BlockLength
;
3242 DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n",
3243 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3244 fdoExtension
->DiskGeometry
.MediaType
,
3245 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3246 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3247 fdoExtension
->DiskGeometry
.BytesPerSector
,
3248 fdoExtension
->SectorShift
,
3249 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3251 // Return the current device geometry
3255 *outputBuffer
= FloppyGeometries
[currentGeometry
];
3257 Irp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
3260 status
= STATUS_SUCCESS
;
3265 // Iterate over the capacities and return the geometry
3266 // corresponding to each matching Capacity List Descriptor
3267 // returned from the device.
3269 // The resulting list should be in sorted ascending order,
3270 // assuming that the FloppyGeometries[] array is in sorted
3273 for (i
= 0; i
< FLOPPY_CAPACITIES
; i
++)
3275 if (capacityMatches
[i
] && FloppyCapacities
[i
].CanFormat
)
3277 if (outputBuffer
< outputBufferEnd
)
3279 *outputBuffer
++ = FloppyGeometries
[i
];
3281 Irp
->IoStatus
.Information
+= sizeof(DISK_GEOMETRY
);
3283 DebugPrint((2,"geometry : %3d %2d %d %2d %4d\n",
3284 FloppyGeometries
[i
].Cylinders
.LowPart
,
3285 FloppyGeometries
[i
].MediaType
,
3286 FloppyGeometries
[i
].TracksPerCylinder
,
3287 FloppyGeometries
[i
].SectorsPerTrack
,
3288 FloppyGeometries
[i
].BytesPerSector
));
3290 status
= STATUS_SUCCESS
;
3294 // We ran out of output buffer room before we ran out
3295 // geometries to return.
3297 status
= STATUS_BUFFER_OVERFLOW
;
3303 else if (NT_SUCCESS(status
))
3305 // The SCSIOP_READ_FORMATTED_CAPACITY request was successful, but
3306 // returned data does not appear valid.
3308 status
= STATUS_UNSUCCESSFUL
;
3311 ExFreePool(dataBuffer
);
3319 USBFlopFormatTracks(
3320 IN PDEVICE_OBJECT DeviceObject
,
3326 Routine Description:
3328 This routines formats the specified tracks. If multiple tracks are
3329 specified, each is formatted with a separate Format Unit request.
3333 DeviceObject - Supplies the device object.
3335 Irp - A IOCTL_DISK_FORMAT_TRACKS Irp.
3342 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
3343 PIO_STACK_LOCATION irpStack
;
3344 PFORMAT_PARAMETERS formatParameters
;
3345 PDISK_GEOMETRY geometry
;
3346 PFORMATTED_CAPACITY capacity
;
3347 PSCSI_REQUEST_BLOCK srb
;
3348 PFORMAT_UNIT_PARAMETER_LIST parameterList
;
3351 ULONG cylinder
, head
;
3352 NTSTATUS status
= STATUS_SUCCESS
;
3356 fdoExtension
= DeviceObject
->DeviceExtension
;
3358 // Get the Irp parameters
3360 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
3362 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
3363 sizeof(FORMAT_PARAMETERS
))
3365 return STATUS_INVALID_PARAMETER
;
3368 formatParameters
= (PFORMAT_PARAMETERS
)Irp
->AssociatedIrp
.SystemBuffer
;
3370 // Find the geometry / capacity entries corresponding to the format
3371 // parameters MediaType
3376 for (i
=0; i
<FLOPPY_CAPACITIES
; i
++)
3378 if (FloppyGeometries
[i
].MediaType
== formatParameters
->MediaType
)
3380 geometry
= &FloppyGeometries
[i
];
3381 capacity
= &FloppyCapacities
[i
];
3387 if (geometry
== NULL
)
3389 return STATUS_INVALID_PARAMETER
;
3392 // Check if the format parameters are valid
3394 if ((formatParameters
->StartCylinderNumber
>
3395 geometry
->Cylinders
.LowPart
- 1) ||
3397 (formatParameters
->EndCylinderNumber
>
3398 geometry
->Cylinders
.LowPart
- 1) ||
3400 (formatParameters
->StartHeadNumber
>
3401 geometry
->TracksPerCylinder
- 1) ||
3403 (formatParameters
->EndHeadNumber
>
3404 geometry
->TracksPerCylinder
- 1) ||
3406 (formatParameters
->StartCylinderNumber
>
3407 formatParameters
->EndCylinderNumber
) ||
3409 (formatParameters
->StartHeadNumber
>
3410 formatParameters
->EndHeadNumber
))
3412 return STATUS_INVALID_PARAMETER
;
3415 // Don't low level format LS-120 media, Imation says it's best to not
3418 if ((formatParameters
->MediaType
== F3_120M_512
) ||
3419 (formatParameters
->MediaType
== F3_240M_512
) ||
3420 (formatParameters
->MediaType
== F3_32M_512
))
3422 return STATUS_SUCCESS
;
3425 // Allocate an SRB for the SCSIOP_FORMAT_UNIT request
3428 srb
= ExAllocatePool(NonPagedPoolNx
, SCSI_REQUEST_BLOCK_SIZE
);
3430 srb
= ExAllocatePool(NonPagedPool
, SCSI_REQUEST_BLOCK_SIZE
);
3435 return STATUS_INSUFFICIENT_RESOURCES
;
3438 // Allocate a transfer buffer for the SCSIOP_FORMAT_UNIT parameter list
3441 parameterList
= ExAllocatePool(NonPagedPoolNx
,
3443 parameterList
= ExAllocatePool(NonPagedPool
,
3445 sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3447 if (parameterList
== NULL
)
3450 return STATUS_INSUFFICIENT_RESOURCES
;
3453 // Initialize the parameter list
3455 RtlZeroMemory(parameterList
, sizeof(FORMAT_UNIT_PARAMETER_LIST
));
3457 parameterList
->DefectListHeader
.SingleTrack
= 1;
3458 parameterList
->DefectListHeader
.DisableCert
= 1; // TEAC requires this set
3459 parameterList
->DefectListHeader
.FormatOptionsValid
= 1;
3460 parameterList
->DefectListHeader
.DefectListLengthLsb
= 8;
3462 parameterList
->FormatDescriptor
.NumberOfBlocks
[0] =
3463 (UCHAR
)((capacity
->NumberOfBlocks
>> 24) & 0xFF);
3465 parameterList
->FormatDescriptor
.NumberOfBlocks
[1] =
3466 (UCHAR
)((capacity
->NumberOfBlocks
>> 16) & 0xFF);
3468 parameterList
->FormatDescriptor
.NumberOfBlocks
[2] =
3469 (UCHAR
)((capacity
->NumberOfBlocks
>> 8) & 0xFF);
3471 parameterList
->FormatDescriptor
.NumberOfBlocks
[3] =
3472 (UCHAR
)(capacity
->NumberOfBlocks
& 0xFF);
3474 parameterList
->FormatDescriptor
.BlockLength
[0] =
3475 (UCHAR
)((capacity
->BlockLength
>> 16) & 0xFF);
3477 parameterList
->FormatDescriptor
.BlockLength
[1] =
3478 (UCHAR
)((capacity
->BlockLength
>> 8) & 0xFF);
3480 parameterList
->FormatDescriptor
.BlockLength
[2] =
3481 (UCHAR
)(capacity
->BlockLength
& 0xFF);
3484 for (cylinder
= formatParameters
->StartCylinderNumber
;
3485 cylinder
<= formatParameters
->EndCylinderNumber
;
3488 for (head
= formatParameters
->StartHeadNumber
;
3489 head
<= formatParameters
->EndHeadNumber
;
3492 // Initialize the SRB and CDB
3494 RtlZeroMemory(srb
, SCSI_REQUEST_BLOCK_SIZE
);
3496 srb
->CdbLength
= sizeof(CDB12FORMAT
);
3498 srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3500 cdb
= (PCDB12FORMAT
)srb
->Cdb
;
3502 cdb
->OperationCode
= SCSIOP_FORMAT_UNIT
;
3503 cdb
->DefectListFormat
= 7;
3505 cdb
->TrackNumber
= (UCHAR
)cylinder
;
3506 cdb
->ParameterListLengthLsb
= sizeof(FORMAT_UNIT_PARAMETER_LIST
);
3508 parameterList
->DefectListHeader
.Side
= (UCHAR
)head
;
3511 // Send down the SCSIOP_FORMAT_UNIT request
3513 status
= ClassSendSrbSynchronous(DeviceObject
,
3516 sizeof(FORMAT_UNIT_PARAMETER_LIST
),
3519 if (!NT_SUCCESS(status
))
3524 if (!NT_SUCCESS(status
))
3530 if (NT_SUCCESS(status
) && formatParameters
->StartCylinderNumber
== 0)
3532 // Update the device geometry
3535 DebugPrint((2,"geometry was: %3d %2d %d %2d %4d %2d %08X\n",
3536 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3537 fdoExtension
->DiskGeometry
.MediaType
,
3538 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3539 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3540 fdoExtension
->DiskGeometry
.BytesPerSector
,
3541 fdoExtension
->SectorShift
,
3542 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3544 fdoExtension
->DiskGeometry
= *geometry
;
3547 // Calculate sector to byte shift.
3550 WHICH_BIT(fdoExtension
->DiskGeometry
.BytesPerSector
,
3551 fdoExtension
->SectorShift
);
3553 fdoExtension
->CommonExtension
.PartitionLength
.QuadPart
=
3554 (LONGLONG
)capacity
->NumberOfBlocks
*
3555 capacity
->BlockLength
;
3557 DebugPrint((2,"geometry is: %3d %2d %d %2d %4d %2d %08X\n",
3558 fdoExtension
->DiskGeometry
.Cylinders
.LowPart
,
3559 fdoExtension
->DiskGeometry
.MediaType
,
3560 fdoExtension
->DiskGeometry
.TracksPerCylinder
,
3561 fdoExtension
->DiskGeometry
.SectorsPerTrack
,
3562 fdoExtension
->DiskGeometry
.BytesPerSector
,
3563 fdoExtension
->SectorShift
,
3564 fdoExtension
->CommonExtension
.PartitionLength
.LowPart
));
3567 // Free everything we allocated
3569 ExFreePool(parameterList
);