[FLOPPY_NEW] WindowsSync to 8fb512a (#2238)
[reactos.git] / drivers / storage / floppy_new / floppy.c
1 /*++
2
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4
5 Module Name:
6
7 floppy.c
8
9 Abstract:
10
11 SCSI floppy class driver
12
13 Author:
14
15 Jeff Havens (jhavens)
16
17 Environment:
18
19 kernel mode only
20
21 Notes:
22
23 Revision History:
24 02/28/96 georgioc Merged this code with code developed by compaq in
25 parallel with microsoft, for 120MB floppy support.
26
27 01/17/96 georgioc Made code PNP aware (uses the new \storage\classpnp/scsiport)
28
29 --*/
30
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
34 #endif
35
36 #include <stddef.h>
37 #include <ntddk.h>
38 #ifndef __REACTOS__
39 #include <winerror.h>
40 #endif
41 #include <scsi.h>
42 #include <classpnp.h>
43 #include <initguid.h>
44 #include <ntddstor.h>
45
46 #include <ntstrsafe.h>
47 #include <intsafe.h>
48
49 #define MODE_DATA_SIZE 192
50 #define SCSI_FLOPPY_TIMEOUT 20
51 #define SFLOPPY_SRB_LIST_SIZE 4
52 //
53 // Define all possible drive/media combinations, given drives listed above
54 // and media types in ntdddisk.h.
55 //
56 // These values are used to index the DriveMediaConstants table.
57 //
58
59 #define NUMBER_OF_DRIVE_TYPES 7
60 #define DRIVE_TYPE_120M 4 //120MB Floptical
61 #define DRIVE_TYPE_NONE NUMBER_OF_DRIVE_TYPES
62
63 //
64 // This array describes all media types we support.
65 // It should be arranged in the increasing order of density
66 //
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.
70 //
71 // Note that, DriveMediaConstants given below is grouped
72 // as drive and media combination
73 //
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
102 } DRIVE_MEDIA_TYPE;
103
104 //
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
108 // the drive.
109 //
110 // These values are used to select a DRIVE_MEDIA_TYPE value.
111 //
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
117 // order.
118 //
119
120 typedef struct _DRIVE_MEDIA_LIMITS {
121 DRIVE_MEDIA_TYPE HighestDriveMediaType;
122 DRIVE_MEDIA_TYPE LowestDriveMediaType;
123 } DRIVE_MEDIA_LIMITS, *PDRIVE_MEDIA_LIMITS;
124
125 #if 0
126 DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = {
127
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 }
134 };
135 #else
136 DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = {
137
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
145 };
146
147 #endif
148 //
149 // For each drive/media combination, define important constants.
150 //
151
152 typedef struct _DRIVE_MEDIA_CONSTANTS {
153 MEDIA_TYPE MediaType;
154 USHORT BytesPerSector;
155 UCHAR SectorsPerTrack;
156 USHORT MaximumTrack;
157 UCHAR NumberOfHeads;
158 } DRIVE_MEDIA_CONSTANTS, *PDRIVE_MEDIA_CONSTANTS;
159
160 //
161 // Magic value to add to the SectorLengthCode to use it as a shift value
162 // to determine the sector size.
163 //
164
165 #define SECTORLENGTHCODE_TO_BYTESHIFT 7
166
167 //
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.
171 //
172
173 DRIVE_MEDIA_CONSTANTS DriveMediaConstants[] =
174 {
175
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 },
181
182 { F3_720_512, 0x200, 0x09, 0x4f, 0x2 },
183
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 },
190
191 { F3_720_512, 0x200, 0x09, 0x4f, 0x2 },
192 { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
193
194 { F3_720_512, 0x200, 0x09, 0x4f, 0x2 },
195 { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
196 { F3_2Pt88_512, 0x200, 0x24, 0x4f, 0x2 },
197
198 { F3_720_512, 0x200, 0x09, 0x4f, 0x2 },
199 { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
200 { F3_20Pt8_512, 0x200, 0x1b, 0xfa, 0x6 },
201
202 { F3_32M_512, 0x200, 0x20, 0x3ff,0x2},
203
204 { F3_720_512, 0x200, 0x09, 0x4f, 0x2 },
205 { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
206 { F3_120M_512, 0x200, 0x20, 0x3c2,0x8 },
207
208 { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
209 { F3_120M_512, 0x200, 0x20, 0x3c2,0x8 },
210 { F3_240M_512, 0x200, 0x38, 0x105,0x20}
211 };
212
213
214 #define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS sizeof(DriveMediaConstants)/sizeof(DRIVE_MEDIA_CONSTANTS)
215
216 //
217 // floppy device data
218 //
219
220 typedef struct _DISK_DATA {
221 ULONG DriveType;
222 BOOLEAN IsDMF;
223 // BOOLEAN EnableDMF;
224 UNICODE_STRING FloppyInterfaceString;
225 } DISK_DATA, *PDISK_DATA;
226
227 //
228 // The FloppyCapacities and FloppyGeometries arrays are used by the
229 // USBFlopGetMediaTypes() and USBFlopFormatTracks() routines.
230
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].
233
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.
236 //
237
238 typedef struct _FORMATTED_CAPACITY
239 {
240 ULONG NumberOfBlocks;
241
242 ULONG BlockLength;
243
244 BOOLEAN CanFormat; // return for IOCTL_DISK_GET_MEDIA_TYPES ?
245
246 } FORMATTED_CAPACITY, *PFORMATTED_CAPACITY;
247
248
249 FORMATTED_CAPACITY FloppyCapacities[] =
250 {
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
262 };
263
264 DISK_GEOMETRY FloppyGeometries[] =
265 {
266 // Cyl MediaType Trk/Cyl Sec/Trk Bytes/Sec
267 #ifndef __REACTOS__
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}
278 #else
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}
289 #endif
290 };
291
292 #define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0]))
293
294 C_ASSERT((sizeof(FloppyGeometries)/sizeof(FloppyGeometries[0])) == FLOPPY_CAPACITIES);
295
296 //
297 // The following structures are used by USBFlopFormatTracks()
298 //
299
300 #pragma pack (push, 1)
301
302 typedef struct _CDB12FORMAT
303 {
304 UCHAR OperationCode;
305 UCHAR DefectListFormat : 3;
306 UCHAR CmpList : 1;
307 UCHAR FmtData : 1;
308 UCHAR LogicalUnitNumber : 3;
309 UCHAR TrackNumber;
310 UCHAR InterleaveMsb;
311 UCHAR InterleaveLsb;
312 UCHAR Reserved1[2];
313 UCHAR ParameterListLengthMsb;
314 UCHAR ParameterListLengthLsb;
315 UCHAR Reserved2[3];
316 } CDB12FORMAT, *PCDB12FORMAT;
317
318
319 typedef struct _DEFECT_LIST_HEADER
320 {
321 UCHAR Reserved1;
322 UCHAR Side : 1;
323 UCHAR Immediate : 1;
324 UCHAR Reserved2 : 2;
325 UCHAR SingleTrack : 1;
326 UCHAR DisableCert : 1;
327 UCHAR Reserved3 : 1;
328 UCHAR FormatOptionsValid : 1;
329 UCHAR DefectListLengthMsb;
330 UCHAR DefectListLengthLsb;
331 } DEFECT_LIST_HEADER, *PDEFECT_LIST_HEADER;
332
333 typedef struct _FORMAT_UNIT_PARAMETER_LIST
334 {
335 DEFECT_LIST_HEADER DefectListHeader;
336 FORMATTED_CAPACITY_DESCRIPTOR FormatDescriptor;
337 } FORMAT_UNIT_PARAMETER_LIST, *PFORMAT_UNIT_PARAMETER_LIST;
338
339 #pragma pack (pop)
340
341 DRIVER_INITIALIZE DriverEntry;
342
343 DRIVER_UNLOAD ScsiFlopUnload;
344
345 DRIVER_ADD_DEVICE ScsiFlopAddDevice;
346
347 NTSTATUS
348 #ifdef __REACTOS__
349 NTAPI
350 #endif
351 ScsiFlopInitDevice(
352 IN PDEVICE_OBJECT Fdo
353 );
354
355 NTSTATUS
356 #ifdef __REACTOS__
357 NTAPI
358 #endif
359 ScsiFlopStartDevice(
360 IN PDEVICE_OBJECT Fdo
361 );
362
363 NTSTATUS
364 #ifdef __REACTOS__
365 NTAPI
366 #endif
367 ScsiFlopRemoveDevice(
368 IN PDEVICE_OBJECT Fdo,
369 IN UCHAR Type
370 );
371
372 NTSTATUS
373 #ifdef __REACTOS__
374 NTAPI
375 #endif
376 ScsiFlopStopDevice(
377 IN PDEVICE_OBJECT Fdo,
378 IN UCHAR Type
379 );
380
381 BOOLEAN
382 FindScsiFlops(
383 IN PDRIVER_OBJECT DriverObject,
384 IN PUNICODE_STRING RegistryPath,
385 IN PCLASS_INIT_DATA InitializationData,
386 IN PDEVICE_OBJECT PortDeviceObject,
387 IN ULONG PortNumber
388 );
389
390 NTSTATUS
391 #ifdef __REACTOS__
392 NTAPI
393 #endif
394 ScsiFlopReadWriteVerification(
395 IN PDEVICE_OBJECT DeviceObject,
396 IN PIRP Irp
397 );
398
399 NTSTATUS
400 #ifdef __REACTOS__
401 NTAPI
402 #endif
403 ScsiFlopDeviceControl(
404 IN PDEVICE_OBJECT DeviceObject,
405 IN PIRP Irp
406 );
407
408 BOOLEAN
409 IsFloppyDevice(
410 PDEVICE_OBJECT DeviceObject
411 );
412
413 NTSTATUS
414 CreateFlopDeviceObject(
415 IN PDRIVER_OBJECT DriverObject,
416 IN PDEVICE_OBJECT PortDeviceObject,
417 IN ULONG DeviceCount
418 );
419
420 NTSTATUS
421 DetermineMediaType(
422 PDEVICE_OBJECT DeviceObject
423 );
424
425 ULONG
426 DetermineDriveType(
427 PDEVICE_OBJECT DeviceObject
428 );
429
430 BOOLEAN
431 FlCheckFormatParameters(
432 IN PDEVICE_OBJECT DeviceObject,
433 IN PFORMAT_PARAMETERS FormatParameters
434 );
435
436 NTSTATUS
437 FormatMedia(
438 PDEVICE_OBJECT DeviceObject,
439 MEDIA_TYPE MediaType
440 );
441
442 NTSTATUS
443 FlopticalFormatMedia(
444 PDEVICE_OBJECT DeviceObject,
445 PFORMAT_PARAMETERS Format
446 );
447
448 VOID
449 #ifdef __REACTOS__
450 NTAPI
451 #endif
452 ScsiFlopProcessError(
453 PDEVICE_OBJECT DeviceObject,
454 PSCSI_REQUEST_BLOCK Srb,
455 NTSTATUS *Status,
456 BOOLEAN *Retry
457 );
458
459 NTSTATUS
460 USBFlopGetMediaTypes(
461 IN PDEVICE_OBJECT DeviceObject,
462 IN PIRP Irp
463 );
464
465 NTSTATUS
466 USBFlopFormatTracks(
467 IN PDEVICE_OBJECT DeviceObject,
468 IN PIRP Irp
469 );
470
471 #ifdef ALLOC_PRAGMA
472 #pragma alloc_text(INIT, DriverEntry)
473
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)
487
488 #endif
489
490 \f
491 NTSTATUS
492 #ifdef __REACTOS__
493 NTAPI
494 #endif
495 DriverEntry(
496 IN PDRIVER_OBJECT DriverObject,
497 IN PUNICODE_STRING RegistryPath
498 )
499 /*++
500
501 Routine Description:
502
503 This is the system initialization routine for installable drivers.
504 It calls the SCSI class driver initialization routine.
505
506 Arguments:
507
508 DriverObject - Pointer to driver object created by system.
509
510 Return Value:
511
512 NTSTATUS
513
514 --*/
515
516 {
517 CLASS_INIT_DATA InitializationData;
518
519 //
520 // Zero InitData
521 //
522
523 RtlZeroMemory (&InitializationData, sizeof(CLASS_INIT_DATA));
524
525 //
526 // Set sizes
527 //
528
529 InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
530 InitializationData.FdoData.DeviceExtensionSize =
531 sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA);
532
533 InitializationData.FdoData.DeviceType = FILE_DEVICE_DISK;
534 InitializationData.FdoData.DeviceCharacteristics = FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE;
535
536 //
537 // Set entry points
538 //
539
540 InitializationData.FdoData.ClassInitDevice = ScsiFlopInitDevice;
541 InitializationData.FdoData.ClassStartDevice = ScsiFlopStartDevice;
542 InitializationData.FdoData.ClassStopDevice = ScsiFlopStopDevice;
543 InitializationData.FdoData.ClassRemoveDevice = ScsiFlopRemoveDevice;
544
545 InitializationData.FdoData.ClassReadWriteVerification = ScsiFlopReadWriteVerification;
546 InitializationData.FdoData.ClassDeviceControl = ScsiFlopDeviceControl;
547
548 InitializationData.FdoData.ClassShutdownFlush = NULL;
549 InitializationData.FdoData.ClassCreateClose = NULL;
550 InitializationData.FdoData.ClassError = ScsiFlopProcessError;
551 InitializationData.ClassStartIo = NULL;
552
553 InitializationData.ClassAddDevice = ScsiFlopAddDevice;
554 InitializationData.ClassUnload = ScsiFlopUnload;
555 //
556 // Call the class init routine
557 //
558
559 return ClassInitialize( DriverObject, RegistryPath, &InitializationData);
560
561
562 } // end DriverEntry()
563 \f
564 VOID
565 #ifdef __REACTOS__
566 NTAPI
567 #endif
568 ScsiFlopUnload(
569 IN PDRIVER_OBJECT DriverObject
570 )
571 {
572 PAGED_CODE();
573 UNREFERENCED_PARAMETER(DriverObject);
574 return;
575 }
576
577 //
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
585 // using #pragma.
586 //
587
588 #if !defined(__REACTOS__) || defined(_MSC_VER)
589 #pragma warning(push)
590 #pragma warning(disable:28152)
591 #endif
592 \f
593 NTSTATUS
594 #ifdef __REACTOS__
595 NTAPI
596 #endif
597 ScsiFlopAddDevice (
598 IN PDRIVER_OBJECT DriverObject,
599 IN PDEVICE_OBJECT Pdo
600 )
601 /*++
602
603 Routine Description:
604
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.
608
609 Arguments:
610
611 DriverObject - Scsiscan class driver object.
612
613 Pdo - the physical device object we are being added to
614
615 Return Value:
616
617 status
618
619 --*/
620 {
621 NTSTATUS status;
622 ULONG floppyCount = IoGetConfigurationInformation()->FloppyCount;
623
624 PAGED_CODE();
625
626 //
627 // Get the number of disks already initialized.
628 //
629
630 status = CreateFlopDeviceObject(DriverObject, Pdo, floppyCount);
631
632 if (NT_SUCCESS(status)) {
633
634 //
635 // Increment system floppy device count.
636 //
637
638 IoGetConfigurationInformation()->FloppyCount++;
639 }
640
641 return status;
642 }
643
644 NTSTATUS
645 CreateFlopDeviceObject(
646 IN PDRIVER_OBJECT DriverObject,
647 IN PDEVICE_OBJECT Pdo,
648 IN ULONG DeviceCount
649 )
650
651 /*++
652
653 Routine Description:
654
655 This routine creates an object for the device and then calls the
656 SCSI port driver for media capacity and sector size.
657
658 Arguments:
659
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.
666
667 Return Value:
668
669 --*/
670 {
671 NTSTATUS status;
672 PDEVICE_OBJECT deviceObject = NULL;
673 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = NULL;
674 PDISK_DATA diskData;
675
676 PAGED_CODE();
677
678 DebugPrint((3,"CreateFlopDeviceObject: Enter routine\n"));
679
680 //
681 // Try to claim the device.
682 //
683
684 status = ClassClaimDevice(Pdo,FALSE);
685
686 if (!NT_SUCCESS(status)) {
687 return(status);
688 }
689
690 DeviceCount--;
691
692 do {
693 UCHAR name[256];
694
695 //
696 // Create device object for this device.
697 //
698
699 DeviceCount++;
700
701 status = RtlStringCbPrintfA((PCCHAR) name,
702 sizeof(name),
703 "\\Device\\Floppy%u",
704 DeviceCount);
705 if (NT_SUCCESS(status)) {
706
707 status = ClassCreateDeviceObject(DriverObject,
708 (PCCHAR) name,
709 Pdo,
710 TRUE,
711 &deviceObject);
712 }
713 } while ((status == STATUS_OBJECT_NAME_COLLISION) ||
714 (status == STATUS_OBJECT_NAME_EXISTS));
715
716 if (!NT_SUCCESS(status)) {
717 DebugPrint((1,"CreateFlopDeviceObjects: Can not create device\n"));
718 goto CreateFlopDeviceObjectExit;
719 }
720
721 //
722 // Indicate that IRPs should include MDLs.
723 //
724
725 deviceObject->Flags |= DO_DIRECT_IO;
726
727 fdoExtension = deviceObject->DeviceExtension;
728
729 //
730 // Back pointer to device object.
731 //
732
733 fdoExtension->CommonExtension.DeviceObject = deviceObject;
734
735 //
736 // This is the physical device.
737 //
738
739 fdoExtension->CommonExtension.PartitionZeroExtension = fdoExtension;
740
741 //
742 // Reset the drive type.
743 //
744
745 diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
746 diskData->DriveType = DRIVE_TYPE_NONE;
747 diskData->IsDMF = FALSE;
748 // diskData->EnableDMF = TRUE;
749
750 //
751 // Initialize lock count to zero. The lock count is used to
752 // disable the ejection mechanism when media is mounted.
753 //
754
755 fdoExtension->LockCount = 0;
756
757 //
758 // Save system floppy number
759 //
760
761 fdoExtension->DeviceNumber = DeviceCount;
762
763 //
764 // Set the alignment requirements for the device based on the
765 // host adapter requirements
766 //
767
768 if (Pdo->AlignmentRequirement > deviceObject->AlignmentRequirement) {
769 deviceObject->AlignmentRequirement = Pdo->AlignmentRequirement;
770 }
771
772 //
773 // Clear the SrbFlags and disable synchronous transfers
774 //
775
776 fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
777
778 //
779 // Finally, attach to the PDO
780 //
781
782 fdoExtension->LowerPdo = Pdo;
783
784 fdoExtension->CommonExtension.LowerDeviceObject =
785 IoAttachDeviceToDeviceStack(deviceObject, Pdo);
786
787 if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {
788
789 status = STATUS_UNSUCCESSFUL;
790 goto CreateFlopDeviceObjectExit;
791 }
792
793 deviceObject->StackSize++;
794
795 //
796 // The device is initialized properly - mark it as such.
797 //
798
799 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
800
801 return STATUS_SUCCESS;
802
803 CreateFlopDeviceObjectExit:
804
805 if (deviceObject != NULL) {
806 IoDeleteDevice(deviceObject);
807 }
808
809 return status;
810
811 } // end CreateFlopDeviceObject()
812 #if !defined(__REACTOS__) || defined(_MSC_VER)
813 #pragma warning(pop)
814 #endif
815
816 NTSTATUS
817 #ifdef __REACTOS__
818 NTAPI
819 #endif
820 ScsiFlopInitDevice(
821 IN PDEVICE_OBJECT Fdo
822 )
823 {
824 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
825 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
826 PDISK_DATA diskData = commonExtension->DriverData;
827
828 PVOID senseData = NULL;
829 ULONG timeOut;
830
831 NTSTATUS status = STATUS_SUCCESS;
832
833 //
834 // Allocate request sense buffer.
835 //
836
837 #ifndef __REACTOS__
838 senseData = ExAllocatePool(NonPagedPoolNxCacheAligned, SENSE_BUFFER_SIZE);
839 #else
840 senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
841 #endif
842
843 if (senseData == NULL) {
844
845 //
846 // The buffer cannot be allocated.
847 //
848
849 status = STATUS_INSUFFICIENT_RESOURCES;
850 return status;
851 }
852
853 //
854 // Set the sense data pointer in the device extension.
855 //
856
857 fdoExtension->SenseData = senseData;
858
859 //
860 // Build the lookaside list for srb's for this device.
861 //
862
863 ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION)fdoExtension,
864 SFLOPPY_SRB_LIST_SIZE);
865
866 //
867 // Register for media change notification
868 //
869 ClassInitializeMediaChangeDetection(fdoExtension,
870 (PUCHAR) "SFloppy");
871
872 //
873 // Set timeout value in seconds.
874 //
875
876 timeOut = ClassQueryTimeOutRegistryValue(Fdo);
877 if (timeOut) {
878 fdoExtension->TimeOutValue = timeOut;
879 } else {
880 fdoExtension->TimeOutValue = SCSI_FLOPPY_TIMEOUT;
881 }
882
883 //
884 // Floppies are not partitionable so starting offset is 0.
885 //
886
887 fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)0;
888
889 #if 0
890 if (!IsFloppyDevice(Fdo) ||
891 !(Fdo->Characteristics & FILE_REMOVABLE_MEDIA) ||
892 (fdoExtension->DeviceDescriptor->DeviceType != DIRECT_ACCESS_DEVICE)) {
893
894 ExFreePool(senseData);
895 status = STATUS_NO_SUCH_DEVICE;
896 return status;
897 }
898 #endif
899
900 RtlZeroMemory(&(fdoExtension->DiskGeometry),
901 sizeof(DISK_GEOMETRY));
902
903 //
904 // Determine the media type if possible. Set the current media type to
905 // Unknown so that determine media type will check the media.
906 //
907
908 fdoExtension->DiskGeometry.MediaType = Unknown;
909
910 //
911 // Register interfaces for this device.
912 //
913
914 {
915 UNICODE_STRING interfaceName;
916
917 RtlInitUnicodeString(&interfaceName, NULL);
918
919 status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
920 (LPGUID) &GUID_DEVINTERFACE_FLOPPY,
921 NULL,
922 &interfaceName);
923
924 if(NT_SUCCESS(status)) {
925 diskData->FloppyInterfaceString = interfaceName;
926 } else {
927 RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL);
928 DebugPrint((1, "ScsiFlopStartDevice: Unable to register device "
929 "interface for fdo %p [%08lx]\n",
930 Fdo, status));
931 }
932 }
933
934 return (STATUS_SUCCESS);
935 }
936
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
939 #endif
940 #ifdef __REACTOS__
941 NTSTATUS NTAPI ScsiFlopStartDevice(
942 #else
943 NTSTATUS ScsiFlopStartDevice(
944 #endif
945 IN PDEVICE_OBJECT Fdo
946 )
947 {
948 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
949 PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
950
951 PIRP irp;
952 IO_STATUS_BLOCK ioStatus;
953
954 SCSI_ADDRESS scsiAddress;
955
956 WCHAR ntNameBuffer[256];
957 UNICODE_STRING ntUnicodeString;
958
959 WCHAR arcNameBuffer[256];
960 UNICODE_STRING arcUnicodeString;
961
962 KEVENT event;
963
964 NTSTATUS status = STATUS_SUCCESS;
965
966 PAGED_CODE();
967
968 KeInitializeEvent(&event,SynchronizationEvent,FALSE);
969
970 DetermineMediaType(Fdo); // ignore unsuccessful here
971
972 //
973 // Create device object for this device.
974 //
975
976 RtlStringCbPrintfW(ntNameBuffer,
977 sizeof(ntNameBuffer),
978 L"\\Device\\Floppy%u",
979 fdoExtension->DeviceNumber);
980
981 //
982 // Create local copy of unicode string
983 //
984 RtlInitUnicodeString(&ntUnicodeString,ntNameBuffer);
985
986 //
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...
992 //
993
994 irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_ADDRESS,
995 Fdo,
996 NULL,
997 0,
998 &scsiAddress,
999 sizeof(scsiAddress),
1000 FALSE,
1001 &event,
1002 &ioStatus);
1003
1004 if (irp == NULL) {
1005 return STATUS_INSUFFICIENT_RESOURCES;
1006 }
1007
1008 status = IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp);
1009
1010 if (status == STATUS_PENDING) {
1011 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
1012 status = ioStatus.Status;
1013 }
1014
1015 //
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.
1019 //
1020 if (NT_SUCCESS(status)) {
1021
1022 RtlStringCbPrintfW(arcNameBuffer,
1023 sizeof(arcNameBuffer),
1024 L"\\ArcName\\scsi(%u)disk(%u)fdisk(%u)",
1025 scsiAddress.PortNumber,
1026 scsiAddress.TargetId,
1027 scsiAddress.Lun);
1028
1029 RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer);
1030
1031 IoAssignArcName(&arcUnicodeString, &ntUnicodeString);
1032 }
1033
1034 status = STATUS_SUCCESS;
1035
1036 //
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.
1042 //
1043
1044 RtlStringCbPrintfW(arcNameBuffer,
1045 sizeof(arcNameBuffer),
1046 L"\\ArcName\\multi(%u)disk(%u)fdisk(%u)",
1047 0,
1048 0,
1049 fdoExtension->DeviceNumber);
1050
1051 RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer);
1052
1053 IoAssignArcName(&arcUnicodeString, &ntUnicodeString);
1054
1055 //
1056 // Set our interface state.
1057 //
1058
1059 {
1060 PDISK_DATA diskData = commonExtension->DriverData;
1061
1062 if(diskData->FloppyInterfaceString.Buffer != NULL) {
1063
1064 status = IoSetDeviceInterfaceState(
1065 &(diskData->FloppyInterfaceString),
1066 TRUE);
1067
1068 if(!NT_SUCCESS(status)) {
1069 DebugPrint((1, "ScsiFlopStartDevice: Unable to set device "
1070 "interface state to TRUE for fdo %p "
1071 "[%08lx]\n",
1072 Fdo, status));
1073 }
1074 }
1075 }
1076
1077 return STATUS_SUCCESS;
1078 }
1079
1080 \f
1081 NTSTATUS
1082 #ifdef __REACTOS__
1083 NTAPI
1084 #endif
1085 ScsiFlopReadWriteVerification(
1086 IN PDEVICE_OBJECT DeviceObject,
1087 IN PIRP Irp
1088 )
1089
1090 /*++
1091
1092 Routine Description:
1093
1094 Arguments:
1095
1096 Return Value:
1097
1098 NT Status
1099
1100 --*/
1101
1102 {
1103 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1104 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1105 NTSTATUS status = STATUS_SUCCESS;
1106
1107 //
1108 // Make sure that the number of bytes to transfer is a multiple of the sector size
1109 //
1110 if ((irpSp->Parameters.Read.Length & (fdoExtension->DiskGeometry.BytesPerSector - 1)) != 0)
1111 {
1112 status = STATUS_INVALID_PARAMETER;
1113 }
1114
1115 Irp->IoStatus.Status = status;
1116
1117 return status;
1118 }
1119
1120
1121 NTSTATUS
1122 #ifdef __REACTOS__
1123 NTAPI
1124 #endif
1125 ScsiFlopDeviceControl(
1126 PDEVICE_OBJECT DeviceObject,
1127 PIRP Irp
1128 )
1129
1130 /*++
1131
1132 Routine Description:
1133
1134 Arguments:
1135
1136 Return Value:
1137
1138 Status is returned.
1139
1140 --*/
1141
1142 {
1143 KIRQL currentIrql;
1144 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
1145 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1146 PSCSI_REQUEST_BLOCK srb;
1147 PCDB cdb;
1148 NTSTATUS status;
1149 PDISK_GEOMETRY outputBuffer;
1150 ULONG outputBufferLength;
1151 ULONG i;
1152 DRIVE_MEDIA_TYPE lowestDriveMediaType;
1153 DRIVE_MEDIA_TYPE highestDriveMediaType;
1154 PFORMAT_PARAMETERS formatParameters;
1155 PMODE_PARAMETER_HEADER modeData;
1156 ULONG length;
1157
1158 //
1159 // Initialize the information field
1160 //
1161 Irp->IoStatus.Information = 0;
1162
1163 #ifndef __REACTOS__
1164 srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE);
1165 #else
1166 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
1167 #endif
1168
1169 if (srb == NULL) {
1170
1171 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1172 if (IoIsErrorUserInduced(Irp->IoStatus.Status)) {
1173
1174 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
1175 }
1176
1177 KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
1178 ClassReleaseRemoveLock(DeviceObject, Irp);
1179 ClassCompleteRequest(DeviceObject, Irp, 0);
1180 KeLowerIrql(currentIrql);
1181
1182 return(STATUS_INSUFFICIENT_RESOURCES);
1183 }
1184
1185 //
1186 // Write zeros to Srb.
1187 //
1188
1189 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
1190
1191 cdb = (PCDB)srb->Cdb;
1192
1193 switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
1194
1195
1196 case IOCTL_DISK_VERIFY: {
1197
1198 PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
1199 LARGE_INTEGER byteOffset;
1200 ULONG sectorOffset;
1201 USHORT sectorCount;
1202
1203 //
1204 // Validate buffer length.
1205 //
1206
1207 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
1208 sizeof(VERIFY_INFORMATION)) {
1209
1210 status = STATUS_INFO_LENGTH_MISMATCH;
1211 break;
1212 }
1213
1214 //
1215 // Perform a bounds check on the sector range
1216 //
1217 if ((verifyInfo->StartingOffset.QuadPart > fdoExtension->CommonExtension.PartitionLength.QuadPart) ||
1218 (verifyInfo->StartingOffset.QuadPart < 0))
1219 {
1220 status = STATUS_NONEXISTENT_SECTOR;
1221 break;
1222 }
1223 else
1224 {
1225 ULONGLONG bytesRemaining = fdoExtension->CommonExtension.PartitionLength.QuadPart - verifyInfo->StartingOffset.QuadPart;
1226
1227 if ((ULONGLONG)verifyInfo->Length > bytesRemaining)
1228 {
1229 status = STATUS_NONEXISTENT_SECTOR;
1230 break;
1231 }
1232 }
1233
1234 //
1235 // Verify sectors
1236 //
1237
1238 srb->CdbLength = 10;
1239
1240 cdb->CDB10.OperationCode = SCSIOP_VERIFY;
1241
1242 //
1243 // Add disk offset to starting sector.
1244 //
1245
1246 byteOffset.QuadPart = fdoExtension->CommonExtension.StartingOffset.QuadPart +
1247 verifyInfo->StartingOffset.QuadPart;
1248
1249 //
1250 // Convert byte offset to sector offset.
1251 //
1252
1253 sectorOffset = (ULONG)(byteOffset.QuadPart >> fdoExtension->SectorShift);
1254
1255 //
1256 // Convert ULONG byte count to USHORT sector count.
1257 //
1258
1259 sectorCount = (USHORT)(verifyInfo->Length >> fdoExtension->SectorShift);
1260
1261 //
1262 // Move little endian values into CDB in big endian format.
1263 //
1264
1265 cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&sectorOffset)->Byte3;
1266 cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&sectorOffset)->Byte2;
1267 cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&sectorOffset)->Byte1;
1268 cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&sectorOffset)->Byte0;
1269
1270 cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&sectorCount)->Byte1;
1271 cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&sectorCount)->Byte0;
1272
1273 //
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.
1278 //
1279
1280 srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) *
1281 fdoExtension->TimeOutValue;
1282
1283 status = ClassSendSrbAsynchronous(DeviceObject,
1284 srb,
1285 Irp,
1286 NULL,
1287 0,
1288 FALSE);
1289 return(status);
1290
1291 }
1292
1293 case IOCTL_DISK_GET_PARTITION_INFO: {
1294
1295 if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) {
1296
1297 USBFlopGetMediaTypes(DeviceObject, NULL);
1298
1299 // Don't need to propagate any error if one occurs
1300 //
1301 status = STATUS_SUCCESS;
1302
1303 } else {
1304
1305 status = DetermineMediaType(DeviceObject);
1306 }
1307
1308 if (!NT_SUCCESS(status)) {
1309 // so will propogate error
1310 NOTHING;
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;
1314 } else {
1315 //
1316 // Free the Srb, since it is not needed.
1317 //
1318
1319 ExFreePool(srb);
1320
1321 //
1322 // Pass the request to the common device control routine.
1323 //
1324
1325 return(ClassDeviceControl(DeviceObject, Irp));
1326 }
1327 break;
1328 }
1329
1330 case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
1331
1332 DebugPrint((3,"ScsiDeviceIoControl: Get drive geometry\n"));
1333
1334 if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb)
1335 {
1336 status = USBFlopGetMediaTypes(DeviceObject,
1337 Irp);
1338 break;
1339 }
1340
1341 //
1342 // If there's not enough room to write the
1343 // data, then fail the request.
1344 //
1345
1346 if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1347 sizeof( DISK_GEOMETRY ) ) {
1348
1349 status = STATUS_INVALID_PARAMETER;
1350 break;
1351 }
1352
1353 status = DetermineMediaType(DeviceObject);
1354
1355 if (!NT_SUCCESS(status)) {
1356
1357 Irp->IoStatus.Information = 0;
1358 Irp->IoStatus.Status = status;
1359
1360 } else {
1361
1362 //
1363 // Copy drive geometry information from device extension.
1364 //
1365
1366 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
1367 &(fdoExtension->DiskGeometry),
1368 sizeof(DISK_GEOMETRY));
1369
1370 Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
1371 status = STATUS_SUCCESS;
1372
1373 }
1374
1375 break;
1376 }
1377
1378 case IOCTL_DISK_GET_MEDIA_TYPES: {
1379
1380 if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb)
1381 {
1382 status = USBFlopGetMediaTypes(DeviceObject,
1383 Irp);
1384 break;
1385 }
1386
1387 i = DetermineDriveType(DeviceObject);
1388
1389 if (i == DRIVE_TYPE_NONE) {
1390 status = STATUS_UNRECOGNIZED_MEDIA;
1391 break;
1392 }
1393
1394 lowestDriveMediaType = DriveMediaLimits[i].LowestDriveMediaType;
1395 highestDriveMediaType = DriveMediaLimits[i].HighestDriveMediaType;
1396
1397 outputBufferLength =
1398 irpStack->Parameters.DeviceIoControl.OutputBufferLength;
1399
1400 //
1401 // Make sure that the input buffer has enough room to return
1402 // at least one descriptions of a supported media type.
1403 //
1404
1405 if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) ) ) {
1406
1407 status = STATUS_BUFFER_TOO_SMALL;
1408 break;
1409 }
1410
1411 //
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).
1415 //
1416
1417 status = STATUS_SUCCESS;
1418
1419 if (outputBufferLength < ( sizeof( DISK_GEOMETRY ) *
1420 ( highestDriveMediaType - lowestDriveMediaType + 1 ) ) ) {
1421
1422 //
1423 // The buffer is too small for all of the descriptions;
1424 // calculate what CAN fit in the buffer.
1425 //
1426
1427 status = STATUS_BUFFER_OVERFLOW;
1428
1429 highestDriveMediaType = (DRIVE_MEDIA_TYPE)( ( lowestDriveMediaType - 1 ) +
1430 ( outputBufferLength /
1431 sizeof( DISK_GEOMETRY ) ) );
1432 }
1433
1434 outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
1435
1436 for (i = (UCHAR)lowestDriveMediaType;i <= (UCHAR)highestDriveMediaType;i++ ) {
1437
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;
1448 outputBuffer++;
1449
1450 Irp->IoStatus.Information += sizeof( DISK_GEOMETRY );
1451 }
1452
1453 break;
1454 }
1455
1456 case IOCTL_DISK_FORMAT_TRACKS: {
1457
1458 if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb)
1459 {
1460 status = USBFlopFormatTracks(DeviceObject,
1461 Irp);
1462 break;
1463 }
1464
1465 //
1466 // Make sure that we got all the necessary format parameters.
1467 //
1468
1469 if ( irpStack->Parameters.DeviceIoControl.InputBufferLength <sizeof( FORMAT_PARAMETERS ) ) {
1470
1471 status = STATUS_INVALID_PARAMETER;
1472 break;
1473 }
1474
1475 formatParameters = (PFORMAT_PARAMETERS) Irp->AssociatedIrp.SystemBuffer;
1476
1477 //
1478 // Make sure the parameters we got are reasonable.
1479 //
1480
1481 if ( !FlCheckFormatParameters(DeviceObject, formatParameters)) {
1482
1483 status = STATUS_INVALID_PARAMETER;
1484 break;
1485 }
1486
1487 //
1488 // If this request is for a 20.8 MB floppy then call a special
1489 // floppy format routine.
1490 //
1491
1492 if (formatParameters->MediaType == F3_20Pt8_512) {
1493 status = FlopticalFormatMedia(DeviceObject,
1494 formatParameters
1495 );
1496
1497 break;
1498 }
1499
1500 //
1501 // All the work is done in the pass. If this is not the first pass,
1502 // then complete the request and return;
1503 //
1504
1505 if (formatParameters->StartCylinderNumber != 0 || formatParameters->StartHeadNumber != 0) {
1506
1507 status = STATUS_SUCCESS;
1508 break;
1509 }
1510
1511 status = FormatMedia( DeviceObject, formatParameters->MediaType);
1512 break;
1513 }
1514
1515 case IOCTL_DISK_IS_WRITABLE: {
1516
1517 if ((fdoExtension->DiskGeometry.MediaType) == F3_32M_512) {
1518
1519 //
1520 // 32MB media is READ ONLY. Just return
1521 // STATUS_MEDIA_WRITE_PROTECTED
1522 //
1523
1524 status = STATUS_MEDIA_WRITE_PROTECTED;
1525
1526 break;
1527 }
1528
1529 //
1530 // Determine if the device is writable.
1531 //
1532
1533 #ifndef __REACTOS__
1534 modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE);
1535 #else
1536 modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE);
1537 #endif
1538
1539 if (modeData == NULL) {
1540 status = STATUS_INSUFFICIENT_RESOURCES;
1541 break;
1542 }
1543
1544 RtlZeroMemory(modeData, MODE_DATA_SIZE);
1545
1546 length = ClassModeSense(DeviceObject,
1547 (PCHAR) modeData,
1548 MODE_DATA_SIZE,
1549 MODE_SENSE_RETURN_ALL);
1550
1551 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1552
1553 //
1554 // Retry the request in case of a check condition.
1555 //
1556
1557 length = ClassModeSense(DeviceObject,
1558 (PCHAR) modeData,
1559 MODE_DATA_SIZE,
1560 MODE_SENSE_RETURN_ALL);
1561
1562 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1563 status = STATUS_IO_DEVICE_ERROR;
1564 ExFreePool(modeData);
1565 break;
1566 }
1567 }
1568
1569 if (modeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT) {
1570 status = STATUS_MEDIA_WRITE_PROTECTED;
1571 } else {
1572 status = STATUS_SUCCESS;
1573 }
1574
1575 DebugPrint((2,"IOCTL_DISK_IS_WRITABLE returns %08X\n", status));
1576
1577 ExFreePool(modeData);
1578 break;
1579 }
1580
1581 default: {
1582
1583 DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n"));
1584
1585 //
1586 // Free the Srb, since it is not needed.
1587 //
1588
1589 ExFreePool(srb);
1590
1591 //
1592 // Pass the request to the common device control routine.
1593 //
1594
1595 return(ClassDeviceControl(DeviceObject, Irp));
1596
1597 break;
1598 }
1599
1600 } // end switch( ...
1601
1602 //
1603 // Check if SL_OVERRIDE_VERIFY_VOLUME flag is set in the IRP.
1604 // If so, do not return STATUS_VERIFY_REQUIRED
1605 //
1606 if ((status == STATUS_VERIFY_REQUIRED) &&
1607 (TEST_FLAG(irpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))) {
1608
1609 status = STATUS_IO_DEVICE_ERROR;
1610
1611 }
1612
1613 Irp->IoStatus.Status = status;
1614
1615 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) {
1616
1617 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
1618 }
1619
1620 KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
1621 ClassReleaseRemoveLock(DeviceObject, Irp);
1622 ClassCompleteRequest(DeviceObject, Irp, 0);
1623 KeLowerIrql(currentIrql);
1624
1625 ExFreePool(srb);
1626
1627 return status;
1628
1629 } // end ScsiFlopDeviceControl()
1630
1631 #if 0
1632 \f
1633 BOOLEAN
1634 IsFloppyDevice(
1635 PDEVICE_OBJECT DeviceObject
1636 )
1637 /*++
1638
1639 Routine Description:
1640
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.
1645
1646 Arguments:
1647
1648 DeviceObject - Supplies the device object to be tested.
1649
1650 Return Value:
1651
1652 Return TRUE if the indicated device is a floppy.
1653
1654 --*/
1655 {
1656
1657 PVOID modeData;
1658 PUCHAR pageData;
1659 ULONG length;
1660
1661 modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE);
1662
1663 if (modeData == NULL) {
1664 return(FALSE);
1665 }
1666
1667 RtlZeroMemory(modeData, MODE_DATA_SIZE);
1668
1669 length = ClassModeSense(DeviceObject, modeData, MODE_DATA_SIZE, MODE_SENSE_RETURN_ALL);
1670
1671 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1672
1673 //
1674 // Retry the request in case of a check condition.
1675 //
1676
1677 length = ClassModeSense(DeviceObject,
1678 modeData,
1679 MODE_DATA_SIZE,
1680 MODE_SENSE_RETURN_ALL);
1681
1682 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1683
1684 ExFreePool(modeData);
1685 return(FALSE);
1686
1687 }
1688 }
1689
1690 #if 0
1691 //
1692 // Some drives incorrectly report this. In particular the SONY RMO-S350
1693 // when in disk mode.
1694 //
1695
1696 if (((PMODE_PARAMETER_HEADER) modeData)->MediumType >= MODE_FD_SINGLE_SIDE
1697 && ((PMODE_PARAMETER_HEADER) modeData)->MediumType <= MODE_FD_MAXIMUM_TYPE) {
1698
1699 DebugPrint((1, "ScsiFlop: MediumType value %2x, This is a floppy.\n", ((PMODE_PARAMETER_HEADER) modeData)->MediumType));
1700 ExFreePool(modeData);
1701 return(TRUE);
1702 }
1703
1704 #endif
1705
1706 //
1707 // If the length is greater than length indiated by the mode data reset
1708 // the data to the mode data.
1709 //
1710 if (length > (ULONG)((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) {
1711 length = (ULONG)((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1;
1712
1713 }
1714
1715 //
1716 // Look for the flexible disk mode page.
1717 //
1718
1719 pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE);
1720
1721 if (pageData != NULL) {
1722
1723 DebugPrint((1, "ScsiFlop: Flexible disk page found, This is a floppy.\n"));
1724
1725 //
1726 // As a special case for the floptical driver do a magic mode sense to
1727 // enable the drive.
1728 //
1729
1730 ClassModeSense(DeviceObject, modeData, 0x2a, 0x2e);
1731
1732 ExFreePool(modeData);
1733 return(TRUE);
1734
1735 }
1736
1737 ExFreePool(modeData);
1738 return(FALSE);
1739
1740 }
1741 #endif
1742
1743 \f
1744 NTSTATUS
1745 DetermineMediaType(
1746 PDEVICE_OBJECT DeviceObject
1747 )
1748 /*++
1749
1750 Routine Description:
1751
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.
1754
1755 Arguments:
1756
1757 DeviceObject - Supplies the device object to be tested.
1758
1759 Return Value:
1760
1761 None
1762
1763 --*/
1764 {
1765 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1766 PDISK_GEOMETRY geometry;
1767 LONG index;
1768 NTSTATUS status;
1769
1770 PAGED_CODE();
1771
1772 geometry = &(fdoExtension->DiskGeometry);
1773
1774 //
1775 // Issue ReadCapacity to update device extension
1776 // with information for current media.
1777 //
1778
1779 status = ClassReadDriveCapacity(DeviceObject);
1780
1781 if (!NT_SUCCESS(status)) {
1782
1783 //
1784 // Set the media type to unknow and zero the geometry information.
1785 //
1786
1787 geometry->MediaType = Unknown;
1788
1789 return status;
1790
1791 }
1792
1793 //
1794 // Look at the capcity of disk to determine its type.
1795 //
1796
1797 for (index = NUMBER_OF_DRIVE_MEDIA_COMBINATIONS - 1; index >= 0; index--) {
1798
1799 //
1800 // Walk the table backward untill the drive capacity holds all of the
1801 // data and the bytes per setor are equal
1802 //
1803
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) {
1811
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;
1816 break;
1817 }
1818 }
1819
1820 if (index == -1) {
1821
1822 //
1823 // Set the media type to unknow and zero the geometry information.
1824 //
1825
1826 geometry->MediaType = Unknown;
1827
1828
1829 } else {
1830 //
1831 // DMF check breaks the insight SCSI floppy, so its disabled for that case
1832 //
1833 PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
1834
1835 // if (diskData->EnableDMF == TRUE) {
1836
1837 //
1838 //check to see if DMF
1839 //
1840
1841 PSCSI_REQUEST_BLOCK srb;
1842 PVOID readData;
1843
1844 //
1845 // Allocate a Srb for the read command.
1846 //
1847
1848 #ifndef __REACTOS__
1849 readData = ExAllocatePool(NonPagedPoolNx, geometry->BytesPerSector);
1850 #else
1851 readData = ExAllocatePool(NonPagedPool, geometry->BytesPerSector);
1852 #endif
1853 if (readData == NULL) {
1854 return STATUS_NO_MEMORY;
1855 }
1856
1857 #ifndef __REACTOS__
1858 srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE);
1859 #else
1860 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
1861 #endif
1862
1863 if (srb == NULL) {
1864
1865 ExFreePool(readData);
1866 return STATUS_NO_MEMORY;
1867 }
1868
1869 RtlZeroMemory(readData, geometry->BytesPerSector);
1870 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
1871
1872 srb->CdbLength = 10;
1873 srb->Cdb[0] = SCSIOP_READ;
1874 srb->Cdb[5] = 0;
1875 srb->Cdb[8] = (UCHAR) 1;
1876
1877 //
1878 // Set timeout value.
1879 //
1880
1881 srb->TimeOutValue = fdoExtension->TimeOutValue;
1882
1883 //
1884 // Send the mode select data.
1885 //
1886
1887 status = ClassSendSrbSynchronous(DeviceObject,
1888 srb,
1889 readData,
1890 geometry->BytesPerSector,
1891 FALSE
1892 );
1893
1894 if (NT_SUCCESS(status)) {
1895 char *pchar = (char *)readData;
1896
1897 pchar += 3; //skip 3 bytes jump code
1898
1899 // If the MSDMF3. signature is there then mark it as DMF diskette
1900 if (RtlCompareMemory(pchar, "MSDMF3.", 7) == 7) {
1901 diskData->IsDMF = TRUE;
1902 }
1903
1904 }
1905 ExFreePool(readData);
1906 ExFreePool(srb);
1907 // }// else
1908 }
1909 return status;
1910 }
1911 \f
1912 ULONG
1913 DetermineDriveType(
1914 PDEVICE_OBJECT DeviceObject
1915 )
1916 /*++
1917
1918 Routine Description:
1919
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.
1923
1924 Arguments:
1925
1926 DeviceObject - Supplies the device object to be tested.
1927
1928 Return Value:
1929
1930 None
1931
1932 --*/
1933 {
1934 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1935 PVOID modeData;
1936 PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
1937 PMODE_FLEXIBLE_DISK_PAGE pageData;
1938 ULONG length;
1939 LONG index;
1940 UCHAR numberOfHeads;
1941 UCHAR sectorsPerTrack;
1942 USHORT maximumTrack;
1943 BOOLEAN applyFix = FALSE;
1944
1945 PAGED_CODE();
1946
1947 if (diskData->DriveType != DRIVE_TYPE_NONE) {
1948 return(diskData->DriveType);
1949 }
1950
1951 #ifndef __REACTOS__
1952 modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE);
1953 #else
1954 modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE);
1955 #endif
1956
1957 if (modeData == NULL) {
1958 return(DRIVE_TYPE_NONE);
1959 }
1960
1961 RtlZeroMemory(modeData, MODE_DATA_SIZE);
1962
1963 length = ClassModeSense(DeviceObject,
1964 modeData,
1965 MODE_DATA_SIZE,
1966 MODE_PAGE_FLEXIBILE);
1967
1968 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1969
1970 //
1971 // Retry the request one more time
1972 // in case of a check condition.
1973 //
1974 length = ClassModeSense(DeviceObject,
1975 modeData,
1976 MODE_DATA_SIZE,
1977 MODE_PAGE_FLEXIBILE);
1978
1979 if (length < sizeof(MODE_PARAMETER_HEADER)) {
1980
1981 ExFreePool(modeData);
1982 return(DRIVE_TYPE_NONE);
1983 }
1984 }
1985
1986 //
1987 // Look for the flexible disk mode page.
1988 //
1989
1990 pageData = ClassFindModePage( modeData,
1991 length,
1992 MODE_PAGE_FLEXIBILE,
1993 TRUE);
1994
1995 //
1996 // Make sure the page is returned and is large enough.
1997 //
1998
1999 if ((pageData != NULL) &&
2000 (pageData->PageLength + 2 >=
2001 (UCHAR)offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) {
2002
2003 //
2004 // Pull out the heads, cylinders, and sectors.
2005 //
2006
2007 numberOfHeads = pageData->NumberOfHeads;
2008 maximumTrack = pageData->NumberOfCylinders[1];
2009 maximumTrack |= pageData->NumberOfCylinders[0] << 8;
2010 sectorsPerTrack = pageData->SectorsPerTrack;
2011
2012
2013 //
2014 // Convert from number of cylinders to maximum track.
2015 //
2016
2017 maximumTrack--;
2018
2019 //
2020 // Search for the maximum supported media. Based on the number of heads,
2021 // sectors per track and number of cylinders
2022 //
2023 for (index = 0; index < NUMBER_OF_DRIVE_MEDIA_COMBINATIONS; index++) {
2024
2025 //
2026 // Walk the table forward until the drive capacity holds all of the
2027 // data and the bytes per setor are equal
2028 //
2029
2030 if (DriveMediaConstants[index].NumberOfHeads == numberOfHeads &&
2031 DriveMediaConstants[index].MaximumTrack == maximumTrack &&
2032 DriveMediaConstants[index].SectorsPerTrack ==sectorsPerTrack) {
2033
2034 ExFreePool(modeData);
2035
2036 //
2037 // index is now a drive media combination. Compare this to
2038 // the maximum drive media type in the drive media table.
2039 //
2040
2041 for (length = 0; length < NUMBER_OF_DRIVE_TYPES; length++) {
2042
2043 if (DriveMediaLimits[length].HighestDriveMediaType == index) {
2044 return(length);
2045 }
2046 }
2047 return(DRIVE_TYPE_NONE);
2048 }
2049 }
2050
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.
2054 //
2055
2056 if (!applyFix && maximumTrack >= 0x0100) {
2057 maximumTrack++;
2058 maximumTrack /= 3;
2059 maximumTrack--;
2060 numberOfHeads *= 3;
2061 } else {
2062 ExFreePool(modeData);
2063 return(DRIVE_TYPE_NONE);
2064 }
2065
2066 }
2067
2068 ExFreePool(modeData);
2069 return(DRIVE_TYPE_NONE);
2070 }
2071
2072 \f
2073 BOOLEAN
2074 FlCheckFormatParameters(
2075 IN PDEVICE_OBJECT DeviceObject,
2076 IN PFORMAT_PARAMETERS FormatParameters
2077 )
2078
2079 /*++
2080
2081 Routine Description:
2082
2083 This routine checks the supplied format parameters to make sure that
2084 they'll work on the drive to be formatted.
2085
2086 Arguments:
2087
2088 DeviceObject - Pointer to the device object to be formated.
2089
2090 FormatParameters - a pointer to the caller's parameters for the FORMAT.
2091
2092 Return Value:
2093
2094 TRUE if parameters are OK.
2095 FALSE if the parameters are bad.
2096
2097 --*/
2098
2099 {
2100 PDRIVE_MEDIA_CONSTANTS driveMediaConstants;
2101 DRIVE_MEDIA_TYPE driveMediaType;
2102 ULONG index;
2103
2104 PAGED_CODE();
2105
2106 //
2107 // Get the device type.
2108 //
2109
2110 index = DetermineDriveType(DeviceObject);
2111
2112 if (index == DRIVE_TYPE_NONE) {
2113
2114 //
2115 // If the determine device type failed then just use the media type
2116 // and try the parameters.
2117 //
2118
2119 driveMediaType = Drive360Media160;
2120
2121 while (( DriveMediaConstants[driveMediaType].MediaType !=
2122 FormatParameters->MediaType ) &&
2123 ( driveMediaType < Drive288Media288) ) {
2124
2125 driveMediaType++;
2126 }
2127
2128 } else {
2129
2130 //
2131 // Figure out which entry in the DriveMediaConstants table to use.
2132 //
2133
2134 driveMediaType =
2135 DriveMediaLimits[index].HighestDriveMediaType;
2136
2137 while ( ( DriveMediaConstants[driveMediaType].MediaType !=
2138 FormatParameters->MediaType ) &&
2139 ( driveMediaType > DriveMediaLimits[index].
2140 LowestDriveMediaType ) ) {
2141
2142 driveMediaType--;
2143 }
2144
2145 }
2146
2147
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
2152 #endif
2153 if ( DriveMediaConstants[driveMediaType].MediaType !=
2154 FormatParameters->MediaType ) {
2155 return FALSE;
2156
2157 } else {
2158
2159 driveMediaConstants = &DriveMediaConstants[driveMediaType];
2160
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 ) ) {
2171
2172 return FALSE;
2173
2174 } else {
2175
2176 return TRUE;
2177 }
2178 }
2179 #if !defined(__REACTOS__) || defined(_MSC_VER)
2180 #pragma warning(pop)
2181 #endif
2182 }
2183 \f
2184 NTSTATUS
2185 FormatMedia(
2186 PDEVICE_OBJECT DeviceObject,
2187 MEDIA_TYPE MediaType
2188 )
2189 /*++
2190
2191 Routine Description:
2192
2193 This routine formats the floppy disk. The entire floppy is formated in
2194 one shot.
2195
2196 Arguments:
2197
2198 DeviceObject - Supplies the device object to be tested.
2199
2200 Irp - Supplies a pointer to the requesting Irp.
2201
2202 MediaType - Supplies the media type format the device for.
2203
2204 Return Value:
2205
2206 Returns a status for the operation.
2207
2208 --*/
2209 {
2210 PVOID modeData;
2211 PSCSI_REQUEST_BLOCK srb;
2212 PMODE_FLEXIBLE_DISK_PAGE pageData;
2213 DRIVE_MEDIA_TYPE driveMediaType;
2214 PDRIVE_MEDIA_CONSTANTS driveMediaConstants;
2215 ULONG length;
2216 NTSTATUS status;
2217
2218 PAGED_CODE();
2219
2220 #ifndef __REACTOS__
2221 modeData = ExAllocatePool(NonPagedPoolNxCacheAligned, MODE_DATA_SIZE);
2222 #else
2223 modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE);
2224 #endif
2225
2226 if (modeData == NULL) {
2227 return(STATUS_INSUFFICIENT_RESOURCES);
2228 }
2229
2230 RtlZeroMemory(modeData, MODE_DATA_SIZE);
2231
2232 length = ClassModeSense(DeviceObject,
2233 modeData,
2234 MODE_DATA_SIZE,
2235 MODE_PAGE_FLEXIBILE);
2236
2237 if (length < sizeof(MODE_PARAMETER_HEADER)) {
2238 ExFreePool(modeData);
2239 return(STATUS_INVALID_DEVICE_REQUEST);
2240 }
2241
2242 //
2243 // Look for the flexible disk mode page.
2244 //
2245
2246 pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE);
2247
2248 //
2249 // Make sure the page is returned and is large enough.
2250 //
2251
2252 if ((pageData == NULL) ||
2253 (pageData->PageLength + 2 <
2254 (UCHAR)offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) {
2255
2256 ExFreePool(modeData);
2257 return(STATUS_INVALID_DEVICE_REQUEST);
2258
2259 }
2260
2261 //
2262 // Look for a drive media type which matches the requested media type.
2263 //
2264 //
2265 //start from Drive120MMedia120M instead of Drive2080Media2080
2266 //
2267 for (driveMediaType = Drive120MMedia120M;
2268 DriveMediaConstants[driveMediaType].MediaType != MediaType;
2269 driveMediaType--) {
2270 if (driveMediaType == Drive360Media160) {
2271
2272 ExFreePool(modeData);
2273 return(STATUS_INVALID_PARAMETER);
2274
2275 }
2276 }
2277
2278 driveMediaConstants = &DriveMediaConstants[driveMediaType];
2279
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 )) {
2285
2286 //
2287 // Update the flexible parameters page with the new parameters.
2288 //
2289
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;
2295
2296 //
2297 // Clear the mode parameter header.
2298 //
2299
2300 RtlZeroMemory(modeData, sizeof(MODE_PARAMETER_HEADER));
2301
2302 //
2303 // Set the length equal to the length returned for the flexible page.
2304 //
2305
2306 length = pageData->PageLength + 2;
2307
2308 //
2309 // Copy the page after the mode parameter header.
2310 //
2311
2312 RtlMoveMemory((PCHAR) modeData + sizeof(MODE_PARAMETER_HEADER),
2313 pageData,
2314 length
2315 );
2316 length += sizeof(MODE_PARAMETER_HEADER);
2317
2318
2319 //
2320 // Allocate a Srb for the format command.
2321 //
2322
2323 #ifndef __REACTOS__
2324 srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE);
2325 #else
2326 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
2327 #endif
2328
2329 if (srb == NULL) {
2330
2331 ExFreePool(modeData);
2332 return(STATUS_INSUFFICIENT_RESOURCES);
2333 }
2334
2335 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
2336
2337 srb->CdbLength = 6;
2338 srb->Cdb[0] = SCSIOP_MODE_SELECT;
2339 srb->Cdb[4] = (UCHAR) length;
2340
2341 //
2342 // Set the PF bit.
2343 //
2344
2345 srb->Cdb[1] |= 0x10;
2346
2347 //
2348 // Set timeout value.
2349 //
2350
2351 srb->TimeOutValue = 2;
2352
2353 //
2354 // Send the mode select data.
2355 //
2356
2357 status = ClassSendSrbSynchronous(DeviceObject,
2358 srb,
2359 modeData,
2360 length,
2361 TRUE
2362 );
2363
2364 //
2365 // The mode data not needed any more so free it.
2366 //
2367
2368 ExFreePool(modeData);
2369
2370 if (!NT_SUCCESS(status)) {
2371 ExFreePool(srb);
2372 return(status);
2373 }
2374
2375 } else {
2376
2377 //
2378 // The mode data not needed any more so free it.
2379 //
2380
2381 ExFreePool(modeData);
2382
2383 //
2384 // Allocate a Srb for the format command.
2385 //
2386
2387 #ifndef __REACTOS__
2388 srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE);
2389 #else
2390 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
2391 #endif
2392
2393 if (srb == NULL) {
2394 return(STATUS_INSUFFICIENT_RESOURCES);
2395 }
2396
2397 }
2398
2399 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
2400
2401 srb->CdbLength = 6;
2402
2403 srb->Cdb[0] = SCSIOP_FORMAT_UNIT;
2404
2405 //
2406 // Set timeout value.
2407 //
2408
2409 srb->TimeOutValue = 10 * 60;
2410
2411 status = ClassSendSrbSynchronous(DeviceObject,
2412 srb,
2413 NULL,
2414 0,
2415 FALSE
2416 );
2417 ExFreePool(srb);
2418
2419 return(status);
2420
2421 }
2422 \f
2423 VOID
2424 #ifdef __REACTOS__
2425 NTAPI
2426 #endif
2427 ScsiFlopProcessError(
2428 PDEVICE_OBJECT DeviceObject,
2429 PSCSI_REQUEST_BLOCK Srb,
2430 NTSTATUS *Status,
2431 BOOLEAN *Retry
2432 )
2433 /*++
2434
2435 Routine Description:
2436
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.
2439
2440 Arguments:
2441
2442 DeviceObject - Supplies a pointer to the device object.
2443
2444 Srb - Supplies a pointer to the failing Srb.
2445
2446 Status - Status with which the IRP will be completed.
2447
2448 Retry - Indication of whether the request will be retried.
2449
2450 Return Value:
2451
2452 None.
2453
2454 --*/
2455
2456 {
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;
2461 PIRP irp;
2462 PSCSI_REQUEST_BLOCK srb;
2463 LARGE_INTEGER largeInt;
2464 PCOMPLETION_CONTEXT context;
2465 PCDB cdb;
2466 ULONG_PTR alignment;
2467 ULONG majorFunction;
2468
2469 UNREFERENCED_PARAMETER(Status);
2470 UNREFERENCED_PARAMETER(Retry);
2471
2472 largeInt.QuadPart = 1;
2473
2474 //
2475 // Check the status. The initialization command only needs to be sent
2476 // if UNIT ATTENTION or LUN NOT READY is returned.
2477 //
2478
2479 if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) {
2480
2481 //
2482 // The drive does not require reinitialization.
2483 //
2484
2485 return;
2486 }
2487
2488 //
2489 // Reset the drive type.
2490 //
2491
2492 diskData->DriveType = DRIVE_TYPE_NONE;
2493 diskData->IsDMF = FALSE;
2494
2495 fdoExtension->DiskGeometry.MediaType = Unknown;
2496
2497 if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) {
2498
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.
2505 //
2506 // This is something that should probably be revisited at some point.
2507 //
2508 fdoExtension->MediaChangeCount = 0;
2509
2510 if (((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) &&
2511 (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_MEDIUM_CHANGED)) {
2512
2513 struct _START_STOP *startStopCdb;
2514
2515 DebugPrint((2,"Sending SCSIOP_START_STOP_UNIT\n"));
2516
2517 #ifndef __REACTOS__
2518 context = ExAllocatePool(NonPagedPoolNx,
2519 sizeof(COMPLETION_CONTEXT));
2520 #else
2521 context = ExAllocatePool(NonPagedPool,
2522 sizeof(COMPLETION_CONTEXT));
2523 #endif
2524
2525 if (context == NULL) {
2526
2527 return;
2528 }
2529 #if (NTDDI_VERSION >= NTDDI_WIN8)
2530 srb = &context->Srb.Srb;
2531 #else
2532 srb = &context->Srb;
2533 #endif
2534
2535 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
2536
2537 srb->SrbFlags = SRB_FLAGS_DISABLE_AUTOSENSE;
2538
2539 srb->CdbLength = 6;
2540
2541 startStopCdb = (struct _START_STOP *)srb->Cdb;
2542
2543 startStopCdb->OperationCode = SCSIOP_START_STOP_UNIT;
2544 startStopCdb->Start = 1;
2545
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.
2550 //
2551 majorFunction = IRP_MJ_FLUSH_BUFFERS;
2552
2553 } else if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_MEDIUM_ERROR) {
2554
2555 // Return ERROR_UNRECOGNIZED_MEDIA instead of
2556 // STATUS_DEVICE_DATA_ERROR to make shell happy.
2557 //
2558 *Status = STATUS_UNRECOGNIZED_MEDIA;
2559 return;
2560
2561 } else {
2562
2563 return;
2564 }
2565
2566 #ifndef __REACTOS__
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) {
2570 #else
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) {
2574 #endif
2575
2576 ULONG sizeNeeded;
2577 ULONG tmpSize;
2578 BOOLEAN overFlow;
2579
2580 DebugPrint((1, "ScsiFlopProcessError: Reinitializing the floppy.\n"));
2581
2582 //
2583 // Send the special mode sense command to enable writes on the
2584 // floptical drive.
2585 //
2586
2587 alignment = DeviceObject->AlignmentRequirement ?
2588 DeviceObject->AlignmentRequirement : 1;
2589
2590 sizeNeeded = 0;
2591 overFlow = TRUE;
2592 if (SUCCEEDED(ULongAdd(sizeof(COMPLETION_CONTEXT), 0x2a, &tmpSize))) {
2593
2594 if (SUCCEEDED(ULongAdd(tmpSize, (ULONG) alignment, &sizeNeeded))) {
2595 overFlow = FALSE;
2596 }
2597 }
2598
2599 context = NULL;
2600
2601 if (!overFlow) {
2602 #ifndef __REACTOS__
2603 context = ExAllocatePool(NonPagedPoolNx, sizeNeeded);
2604 #else
2605 context = ExAllocatePool(NonPagedPool, sizeNeeded);
2606 #endif
2607 }
2608
2609 if (context == NULL) {
2610
2611 //
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.
2615 //
2616
2617 return;
2618 }
2619
2620 #if (NTDDI_VERSION >= NTDDI_WIN8)
2621 srb = &context->Srb.Srb;
2622 #else
2623 srb = &context->Srb;
2624 #endif
2625
2626 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
2627
2628 //
2629 // Set the transfer length.
2630 //
2631
2632 srb->DataTransferLength = 0x2a;
2633 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2634
2635 //
2636 // The data buffer must be aligned.
2637 //
2638
2639 srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) &
2640 ~(alignment - 1));
2641
2642
2643 //
2644 // Build the start unit CDB.
2645 //
2646
2647 srb->CdbLength = 6;
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;
2652
2653 majorFunction = IRP_MJ_READ;
2654
2655 } else {
2656
2657 return;
2658 }
2659
2660 context->DeviceObject = DeviceObject;
2661
2662 //
2663 // Write length to SRB.
2664 //
2665
2666 srb->Length = SCSI_REQUEST_BLOCK_SIZE;
2667
2668 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2669 srb->TimeOutValue = fdoExtension->TimeOutValue;
2670
2671 //
2672 // Build the asynchronous request
2673 // to be sent to the port driver.
2674 //
2675
2676 irp = IoBuildAsynchronousFsdRequest(majorFunction,
2677 DeviceObject,
2678 srb->DataBuffer,
2679 srb->DataTransferLength,
2680 &largeInt,
2681 NULL);
2682
2683 if(irp == NULL) {
2684 ExFreePool(context);
2685 return;
2686 }
2687
2688
2689 IoSetCompletionRoutine(irp,
2690 (PIO_COMPLETION_ROUTINE)ClassAsynchronousCompletion,
2691 context,
2692 TRUE,
2693 TRUE,
2694 TRUE);
2695
2696 ClassAcquireRemoveLock(DeviceObject, irp);
2697
2698 irpStack = IoGetNextIrpStackLocation(irp);
2699
2700 irpStack->MajorFunction = IRP_MJ_SCSI;
2701
2702 srb->OriginalRequest = irp;
2703
2704 //
2705 // Save SRB address in next stack for port driver.
2706 //
2707
2708 irpStack->Parameters.Others.Argument1 = (PVOID)srb;
2709
2710 //
2711 // Can't release the remove lock yet - let ClassAsynchronousCompletion
2712 // take care of that for us.
2713 //
2714
2715 (VOID)IoCallDriver(fdoExtension->CommonExtension.LowerDeviceObject, irp);
2716
2717 return;
2718 }
2719 \f
2720 NTSTATUS
2721 FlopticalFormatMedia(
2722 PDEVICE_OBJECT DeviceObject,
2723 PFORMAT_PARAMETERS Format
2724 )
2725 /*++
2726
2727 Routine Description:
2728
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.
2732
2733 Arguments:
2734
2735 DeviceObject - Supplies the device object to be tested.
2736
2737 Format - Supplies the format parameters.
2738
2739 Return Value:
2740
2741 Returns a status for the operation.
2742
2743 --*/
2744 {
2745 IO_STATUS_BLOCK ioStatus;
2746 PIRP irp;
2747 KEVENT event;
2748 LARGE_INTEGER offset;
2749 ULONG length;
2750 PVOID buffer;
2751 PDRIVE_MEDIA_CONSTANTS driveMediaConstants;
2752 NTSTATUS status;
2753
2754 PAGED_CODE();
2755
2756 driveMediaConstants = &DriveMediaConstants[Drive2080Media2080];
2757
2758 //
2759 // Calculate the length of the buffer.
2760 //
2761
2762 length = ((Format->EndCylinderNumber - Format->StartCylinderNumber) *
2763 driveMediaConstants->NumberOfHeads +
2764 Format->EndHeadNumber - Format->StartHeadNumber + 1) *
2765 driveMediaConstants->SectorsPerTrack *
2766 driveMediaConstants->BytesPerSector;
2767
2768 #ifndef __REACTOS__
2769 buffer = ExAllocatePool(NonPagedPoolNxCacheAligned, length);
2770 #else
2771 buffer = ExAllocatePool(NonPagedPoolCacheAligned, length);
2772 #endif
2773
2774 if (buffer == NULL) {
2775 return(STATUS_INSUFFICIENT_RESOURCES);
2776 }
2777
2778 RtlZeroMemory(buffer, length);
2779
2780 offset.QuadPart =
2781 (Format->StartCylinderNumber * driveMediaConstants->NumberOfHeads +
2782 Format->StartHeadNumber) * driveMediaConstants->SectorsPerTrack *
2783 driveMediaConstants->BytesPerSector;
2784
2785 //
2786 // Set the event object to the unsignaled state.
2787 // It will be used to signal request completion.
2788 //
2789
2790 KeInitializeEvent(&event, NotificationEvent, FALSE);
2791
2792 //
2793 // Build the synchronous request with data transfer.
2794 //
2795
2796 irp = IoBuildSynchronousFsdRequest(
2797 IRP_MJ_WRITE,
2798 DeviceObject,
2799 buffer,
2800 length,
2801 &offset,
2802 &event,
2803 &ioStatus);
2804
2805 if (irp != NULL) {
2806 status = IoCallDriver(DeviceObject, irp);
2807
2808 if (status == STATUS_PENDING) {
2809
2810 //
2811 // Wait for the request to complete if necessary.
2812 //
2813
2814 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
2815 }
2816
2817 //
2818 // If the call driver suceeded then set the status to the status block.
2819 //
2820
2821 if (NT_SUCCESS(status)) {
2822 status = ioStatus.Status;
2823 }
2824 } else {
2825 status = STATUS_INSUFFICIENT_RESOURCES;
2826 }
2827
2828 ExFreePool(buffer);
2829
2830 return(status);
2831
2832 }
2833
2834 \f
2835 NTSTATUS
2836 #ifdef __REACTOS__
2837 NTAPI
2838 #endif
2839 ScsiFlopRemoveDevice(
2840 IN PDEVICE_OBJECT DeviceObject,
2841 IN UCHAR Type
2842 )
2843 /*++
2844
2845 Routine Description:
2846
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.
2851
2852 Arguments:
2853
2854 DeviceObject - the device object being removed
2855
2856 Type - the type of remove operation (QUERY, REMOVE or CANCEL)
2857
2858 Return Value:
2859
2860 for a query - success if the device can be removed or a failure code
2861 indiciating why not.
2862
2863 for a remove or cancel - STATUS_SUCCESS
2864
2865 --*/
2866
2867 {
2868 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension =
2869 DeviceObject->DeviceExtension;
2870 PDISK_DATA diskData = deviceExtension->CommonExtension.DriverData;
2871 NTSTATUS status;
2872
2873 PAGED_CODE();
2874
2875 if((Type == IRP_MN_QUERY_REMOVE_DEVICE) ||
2876 (Type == IRP_MN_CANCEL_REMOVE_DEVICE)) {
2877 return STATUS_SUCCESS;
2878 }
2879
2880 if (Type == IRP_MN_REMOVE_DEVICE){
2881 if(deviceExtension->DeviceDescriptor) {
2882 ExFreePool(deviceExtension->DeviceDescriptor);
2883 deviceExtension->DeviceDescriptor = NULL;
2884 }
2885
2886 if(deviceExtension->AdapterDescriptor) {
2887 ExFreePool(deviceExtension->AdapterDescriptor);
2888 deviceExtension->AdapterDescriptor = NULL;
2889 }
2890
2891 if(deviceExtension->SenseData) {
2892 ExFreePool(deviceExtension->SenseData);
2893 deviceExtension->SenseData = NULL;
2894 }
2895
2896 ClassDeleteSrbLookasideList(&deviceExtension->CommonExtension);
2897 }
2898
2899 if(diskData->FloppyInterfaceString.Buffer != NULL) {
2900
2901 status = IoSetDeviceInterfaceState(
2902 &(diskData->FloppyInterfaceString),
2903 FALSE);
2904
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 "
2909 "[%08lx]\n",
2910 DeviceObject, status));
2911 }
2912
2913 RtlFreeUnicodeString(&(diskData->FloppyInterfaceString));
2914 RtlInitUnicodeString(&(diskData->FloppyInterfaceString), NULL);
2915 }
2916
2917 if(Type == IRP_MN_REMOVE_DEVICE) {
2918 IoGetConfigurationInformation()->FloppyCount--;
2919 }
2920
2921 return STATUS_SUCCESS;
2922 }
2923
2924 \f
2925 NTSTATUS
2926 #ifdef __REACTOS__
2927 NTAPI
2928 #endif
2929 ScsiFlopStopDevice(
2930 IN PDEVICE_OBJECT DeviceObject,
2931 IN UCHAR Type
2932 )
2933 {
2934 UNREFERENCED_PARAMETER(DeviceObject);
2935 UNREFERENCED_PARAMETER(Type);
2936
2937 return STATUS_SUCCESS;
2938 }
2939
2940 \f
2941 NTSTATUS
2942 USBFlopGetMediaTypes(
2943 IN PDEVICE_OBJECT DeviceObject,
2944 IN PIRP Irp
2945 )
2946 {
2947 /*++
2948
2949 Routine Description:
2950
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.
2955
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.
2959
2960 Arguments:
2961
2962 DeviceObject - Supplies the device object.
2963
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
2966 geometry.
2967
2968 Return Value:
2969
2970 Status is returned.
2971
2972 --*/
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;
2980 PVOID dataBuffer;
2981 ULONG dataTransferLength;
2982 struct _READ_FORMATTED_CAPACITIES *cdb;
2983 PFORMATTED_CAPACITY_LIST capList;
2984 NTSTATUS status;
2985
2986 PAGED_CODE();
2987
2988 fdoExtension = DeviceObject->DeviceExtension;
2989
2990 if (Irp != NULL) {
2991
2992 // Get the Irp parameters
2993 //
2994 irpStack = IoGetCurrentIrpStackLocation(Irp);
2995
2996 ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
2997
2998 Irp->IoStatus.Information = 0;
2999
3000 outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
3001
3002 outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
3003
3004 if (outputBufferLength < sizeof(DISK_GEOMETRY))
3005 {
3006 return STATUS_BUFFER_TOO_SMALL;
3007 }
3008
3009 // Pointer arithmetic to allow multiple DISK_GEOMETRY's to be returned.
3010 // Rounds BufferEnd down to integral multiple of DISK_GEOMETRY structs.
3011 //
3012 outputBufferEnd = outputBuffer +
3013 outputBufferLength / sizeof(DISK_GEOMETRY);
3014
3015 } else {
3016
3017 // No Irp to return the result in, just update the current geometry
3018 // in the device extension.
3019 //
3020 ioControlCode = IOCTL_DISK_GET_DRIVE_GEOMETRY;
3021
3022 outputBuffer = NULL;
3023
3024 outputBufferEnd = NULL;
3025
3026 outputBufferLength = 0;
3027 }
3028
3029 if (ioControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) {
3030
3031 fdoExtension->DiskGeometry.MediaType = Unknown;
3032
3033 status = ClassReadDriveCapacity(DeviceObject);
3034
3035 if (!NT_SUCCESS(status))
3036 {
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.
3042 //
3043 if (status != STATUS_UNRECOGNIZED_MEDIA)
3044 {
3045 DebugPrint((2,"IOCTL_DISK_GET_DRIVE_GEOMETRY returns %08X\n", status));
3046
3047 return status;
3048 }
3049 }
3050 }
3051
3052 // Allocate an SRB for the SCSIOP_READ_FORMATTED_CAPACITY request
3053 //
3054 #ifndef __REACTOS__
3055 srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE);
3056 #else
3057 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
3058 #endif
3059
3060 if (srb == NULL)
3061 {
3062 return STATUS_INSUFFICIENT_RESOURCES;
3063 }
3064
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.
3068 //
3069 dataTransferLength = sizeof(FORMATTED_CAPACITY_LIST) +
3070 31 * sizeof(FORMATTED_CAPACITY_DESCRIPTOR);
3071
3072 ASSERT(dataTransferLength < 0x100);
3073
3074 #ifndef __REACTOS__
3075 dataBuffer = ExAllocatePool(NonPagedPoolNx, dataTransferLength);
3076 #else
3077 dataBuffer = ExAllocatePool(NonPagedPool, dataTransferLength);
3078 #endif
3079
3080 if (dataBuffer == NULL)
3081 {
3082 ExFreePool(srb);
3083 return STATUS_INSUFFICIENT_RESOURCES;
3084 }
3085
3086 // Initialize the SRB and CDB
3087 //
3088 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
3089
3090 RtlZeroMemory(dataBuffer, dataTransferLength);
3091
3092 srb->CdbLength = sizeof(struct _READ_FORMATTED_CAPACITIES);
3093
3094 srb->TimeOutValue = fdoExtension->TimeOutValue;
3095
3096 cdb = (struct _READ_FORMATTED_CAPACITIES *)srb->Cdb;
3097
3098 cdb->OperationCode = SCSIOP_READ_FORMATTED_CAPACITY;
3099 cdb->AllocationLength[1] = (UCHAR)dataTransferLength;
3100
3101 //
3102 // Send down the SCSIOP_READ_FORMATTED_CAPACITY request
3103 //
3104 status = ClassSendSrbSynchronous(DeviceObject,
3105 srb,
3106 dataBuffer,
3107 dataTransferLength,
3108 FALSE);
3109
3110 capList = (PFORMATTED_CAPACITY_LIST)dataBuffer;
3111
3112 // If we don't get as much data as requested, it is not an error.
3113 //
3114 if (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)
3115 {
3116 status = STATUS_SUCCESS;
3117 }
3118
3119 if (NT_SUCCESS(status) &&
3120 srb->DataTransferLength >= sizeof(FORMATTED_CAPACITY_LIST) &&
3121 capList->CapacityListLength &&
3122 capList->CapacityListLength % sizeof(FORMATTED_CAPACITY_DESCRIPTOR) == 0)
3123 {
3124 ULONG NumberOfBlocks;
3125 ULONG BlockLength;
3126 ULONG count;
3127 ULONG i, j;
3128 LONG currentGeometry;
3129 BOOLEAN capacityMatches[FLOPPY_CAPACITIES];
3130
3131 // Subtract the size of the Capacity List Header to get
3132 // just the size of the Capacity List Descriptor array.
3133 //
3134 srb->DataTransferLength -= sizeof(FORMATTED_CAPACITY_LIST);
3135
3136 // Only look at the Capacity List Descriptors that were actually
3137 // returned.
3138 //
3139 if (srb->DataTransferLength < capList->CapacityListLength)
3140 {
3141 count = srb->DataTransferLength /
3142 sizeof(FORMATTED_CAPACITY_DESCRIPTOR);
3143 }
3144 else
3145 {
3146 count = capList->CapacityListLength /
3147 sizeof(FORMATTED_CAPACITY_DESCRIPTOR);
3148 }
3149
3150 // Updated only if a match is found for the first Capacity List
3151 // Descriptor returned by the device.
3152 //
3153 currentGeometry = -1;
3154
3155 // Initialize the array of capacities that hit a match.
3156 //
3157 RtlZeroMemory(capacityMatches, sizeof(capacityMatches));
3158
3159 // Iterate over each Capacity List Descriptor returned from the device
3160 // and record matching capacities in the capacity match array.
3161 //
3162 for (i = 0; i < count; i++)
3163 {
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]);
3168
3169 BlockLength = (capList->Descriptors[i].BlockLength[0] << 16) +
3170 (capList->Descriptors[i].BlockLength[1] << 8) +
3171 (capList->Descriptors[i].BlockLength[2]);
3172
3173 // Given the {NumberOfBlocks, BlockLength} from this Capacity List
3174 // Descriptor, find a matching entry in FloppyCapacities[].
3175 //
3176 for (j = 0; j < FLOPPY_CAPACITIES; j++)
3177 {
3178 if (NumberOfBlocks == FloppyCapacities[j].NumberOfBlocks &&
3179 BlockLength == FloppyCapacities[j].BlockLength)
3180 {
3181 // A matching capacity was found, record it.
3182 //
3183 capacityMatches[j] = TRUE;
3184
3185 // A match was found for the first Capacity List
3186 // Descriptor returned by the device.
3187 //
3188 if (i == 0)
3189 {
3190 currentGeometry = j;
3191 }
3192 } else if ((capList->Descriptors[i].Valid) &&
3193 (BlockLength == FloppyCapacities[j].BlockLength)) {
3194
3195 ULONG inx;
3196 ULONG mediaInx;
3197
3198 //
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
3202 //
3203 inx = DetermineDriveType(DeviceObject);
3204 if (inx != DRIVE_TYPE_NONE) {
3205 mediaInx = DriveMediaLimits[inx].HighestDriveMediaType;
3206 if ((DriveMediaConstants[mediaInx].MediaType)
3207 == F3_32M_512) {
3208 capacityMatches[j] = TRUE;
3209
3210 if (i == 0) {
3211 currentGeometry = j;
3212 }
3213 }
3214 }
3215 }
3216 }
3217 }
3218
3219 // Default status is STATUS_UNRECOGNIZED_MEDIA, unless we return
3220 // either STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW.
3221 //
3222 status = STATUS_UNRECOGNIZED_MEDIA;
3223
3224 if (ioControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) {
3225
3226 if (currentGeometry != -1)
3227 {
3228 // Update the current device geometry
3229 //
3230 fdoExtension->DiskGeometry = FloppyGeometries[currentGeometry];
3231
3232 //
3233 // Calculate sector to byte shift.
3234 //
3235
3236 WHICH_BIT(fdoExtension->DiskGeometry.BytesPerSector,
3237 fdoExtension->SectorShift);
3238
3239 fdoExtension->CommonExtension.PartitionLength.QuadPart =
3240 (LONGLONG)FloppyCapacities[currentGeometry].NumberOfBlocks *
3241 FloppyCapacities[currentGeometry].BlockLength;
3242
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));
3251
3252 // Return the current device geometry
3253 //
3254 if (Irp != NULL)
3255 {
3256 *outputBuffer = FloppyGeometries[currentGeometry];
3257
3258 Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
3259 }
3260
3261 status = STATUS_SUCCESS;
3262 }
3263
3264 } else {
3265
3266 // Iterate over the capacities and return the geometry
3267 // corresponding to each matching Capacity List Descriptor
3268 // returned from the device.
3269 //
3270 // The resulting list should be in sorted ascending order,
3271 // assuming that the FloppyGeometries[] array is in sorted
3272 // ascending order.
3273 //
3274 for (i = 0; i < FLOPPY_CAPACITIES; i++)
3275 {
3276 if (capacityMatches[i] && FloppyCapacities[i].CanFormat)
3277 {
3278 if (outputBuffer < outputBufferEnd)
3279 {
3280 *outputBuffer++ = FloppyGeometries[i];
3281
3282 Irp->IoStatus.Information += sizeof(DISK_GEOMETRY);
3283
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));
3290
3291 status = STATUS_SUCCESS;
3292 }
3293 else
3294 {
3295 // We ran out of output buffer room before we ran out
3296 // geometries to return.
3297 //
3298 status = STATUS_BUFFER_OVERFLOW;
3299 }
3300 }
3301 }
3302 }
3303 }
3304 else if (NT_SUCCESS(status))
3305 {
3306 // The SCSIOP_READ_FORMATTED_CAPACITY request was successful, but
3307 // returned data does not appear valid.
3308 //
3309 status = STATUS_UNSUCCESSFUL;
3310 }
3311
3312 ExFreePool(dataBuffer);
3313 ExFreePool(srb);
3314
3315 return status;
3316 }
3317
3318 \f
3319 NTSTATUS
3320 USBFlopFormatTracks(
3321 IN PDEVICE_OBJECT DeviceObject,
3322 IN PIRP Irp
3323 )
3324 {
3325 /*++
3326
3327 Routine Description:
3328
3329 This routines formats the specified tracks. If multiple tracks are
3330 specified, each is formatted with a separate Format Unit request.
3331
3332 Arguments:
3333
3334 DeviceObject - Supplies the device object.
3335
3336 Irp - A IOCTL_DISK_FORMAT_TRACKS Irp.
3337
3338 Return Value:
3339
3340 Status is returned.
3341
3342 --*/
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;
3350 PCDB12FORMAT cdb;
3351 ULONG i;
3352 ULONG cylinder, head;
3353 NTSTATUS status = STATUS_SUCCESS;
3354
3355 PAGED_CODE();
3356
3357 fdoExtension = DeviceObject->DeviceExtension;
3358
3359 // Get the Irp parameters
3360 //
3361 irpStack = IoGetCurrentIrpStackLocation(Irp);
3362
3363 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
3364 sizeof(FORMAT_PARAMETERS))
3365 {
3366 return STATUS_INVALID_PARAMETER;
3367 }
3368
3369 formatParameters = (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
3370
3371 // Find the geometry / capacity entries corresponding to the format
3372 // parameters MediaType
3373 //
3374 geometry = NULL;
3375 capacity = NULL;
3376
3377 for (i=0; i<FLOPPY_CAPACITIES; i++)
3378 {
3379 if (FloppyGeometries[i].MediaType == formatParameters->MediaType)
3380 {
3381 geometry = &FloppyGeometries[i];
3382 capacity = &FloppyCapacities[i];
3383
3384 break;
3385 }
3386 }
3387
3388 if (geometry == NULL)
3389 {
3390 return STATUS_INVALID_PARAMETER;
3391 }
3392
3393 // Check if the format parameters are valid
3394 //
3395 if ((formatParameters->StartCylinderNumber >
3396 geometry->Cylinders.LowPart - 1) ||
3397
3398 (formatParameters->EndCylinderNumber >
3399 geometry->Cylinders.LowPart - 1) ||
3400
3401 (formatParameters->StartHeadNumber >
3402 geometry->TracksPerCylinder - 1) ||
3403
3404 (formatParameters->EndHeadNumber >
3405 geometry->TracksPerCylinder - 1) ||
3406
3407 (formatParameters->StartCylinderNumber >
3408 formatParameters->EndCylinderNumber) ||
3409
3410 (formatParameters->StartHeadNumber >
3411 formatParameters->EndHeadNumber))
3412 {
3413 return STATUS_INVALID_PARAMETER;
3414 }
3415
3416 // Don't low level format LS-120 media, Imation says it's best to not
3417 // do this.
3418 //
3419 if ((formatParameters->MediaType == F3_120M_512) ||
3420 (formatParameters->MediaType == F3_240M_512) ||
3421 (formatParameters->MediaType == F3_32M_512))
3422 {
3423 return STATUS_SUCCESS;
3424 }
3425
3426 // Allocate an SRB for the SCSIOP_FORMAT_UNIT request
3427 //
3428 #ifndef __REACTOS__
3429 srb = ExAllocatePool(NonPagedPoolNx, SCSI_REQUEST_BLOCK_SIZE);
3430 #else
3431 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
3432 #endif
3433
3434 if (srb == NULL)
3435 {
3436 return STATUS_INSUFFICIENT_RESOURCES;
3437 }
3438
3439 // Allocate a transfer buffer for the SCSIOP_FORMAT_UNIT parameter list
3440 //
3441 #ifndef __REACTOS__
3442 parameterList = ExAllocatePool(NonPagedPoolNx,
3443 sizeof(FORMAT_UNIT_PARAMETER_LIST));
3444 #else
3445 parameterList = ExAllocatePool(NonPagedPool,
3446 sizeof(FORMAT_UNIT_PARAMETER_LIST));
3447 #endif
3448
3449 if (parameterList == NULL)
3450 {
3451 ExFreePool(srb);
3452 return STATUS_INSUFFICIENT_RESOURCES;
3453 }
3454
3455 // Initialize the parameter list
3456 //
3457 RtlZeroMemory(parameterList, sizeof(FORMAT_UNIT_PARAMETER_LIST));
3458
3459 parameterList->DefectListHeader.SingleTrack = 1;
3460 parameterList->DefectListHeader.DisableCert = 1; // TEAC requires this set
3461 parameterList->DefectListHeader.FormatOptionsValid = 1;
3462 parameterList->DefectListHeader.DefectListLengthLsb = 8;
3463
3464 parameterList->FormatDescriptor.NumberOfBlocks[0] =
3465 (UCHAR)((capacity->NumberOfBlocks >> 24) & 0xFF);
3466
3467 parameterList->FormatDescriptor.NumberOfBlocks[1] =
3468 (UCHAR)((capacity->NumberOfBlocks >> 16) & 0xFF);
3469
3470 parameterList->FormatDescriptor.NumberOfBlocks[2] =
3471 (UCHAR)((capacity->NumberOfBlocks >> 8) & 0xFF);
3472
3473 parameterList->FormatDescriptor.NumberOfBlocks[3] =
3474 (UCHAR)(capacity->NumberOfBlocks & 0xFF);
3475
3476 parameterList->FormatDescriptor.BlockLength[0] =
3477 (UCHAR)((capacity->BlockLength >> 16) & 0xFF);
3478
3479 parameterList->FormatDescriptor.BlockLength[1] =
3480 (UCHAR)((capacity->BlockLength >> 8) & 0xFF);
3481
3482 parameterList->FormatDescriptor.BlockLength[2] =
3483 (UCHAR)(capacity->BlockLength & 0xFF);
3484
3485
3486 for (cylinder = formatParameters->StartCylinderNumber;
3487 cylinder <= formatParameters->EndCylinderNumber;
3488 cylinder++)
3489 {
3490 for (head = formatParameters->StartHeadNumber;
3491 head <= formatParameters->EndHeadNumber;
3492 head++)
3493 {
3494 // Initialize the SRB and CDB
3495 //
3496 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
3497
3498 srb->CdbLength = sizeof(CDB12FORMAT);
3499
3500 srb->TimeOutValue = fdoExtension->TimeOutValue;
3501
3502 cdb = (PCDB12FORMAT)srb->Cdb;
3503
3504 cdb->OperationCode = SCSIOP_FORMAT_UNIT;
3505 cdb->DefectListFormat = 7;
3506 cdb->FmtData = 1;
3507 cdb->TrackNumber = (UCHAR)cylinder;
3508 cdb->ParameterListLengthLsb = sizeof(FORMAT_UNIT_PARAMETER_LIST);
3509
3510 parameterList->DefectListHeader.Side = (UCHAR)head;
3511
3512 //
3513 // Send down the SCSIOP_FORMAT_UNIT request
3514 //
3515 status = ClassSendSrbSynchronous(DeviceObject,
3516 srb,
3517 parameterList,
3518 sizeof(FORMAT_UNIT_PARAMETER_LIST),
3519 TRUE);
3520
3521 if (!NT_SUCCESS(status))
3522 {
3523 break;
3524 }
3525 }
3526 if (!NT_SUCCESS(status))
3527 {
3528 break;
3529 }
3530 }
3531
3532 if (NT_SUCCESS(status) && formatParameters->StartCylinderNumber == 0)
3533 {
3534 // Update the device geometry
3535 //
3536
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));
3545
3546 fdoExtension->DiskGeometry = *geometry;
3547
3548 //
3549 // Calculate sector to byte shift.
3550 //
3551
3552 WHICH_BIT(fdoExtension->DiskGeometry.BytesPerSector,
3553 fdoExtension->SectorShift);
3554
3555 fdoExtension->CommonExtension.PartitionLength.QuadPart =
3556 (LONGLONG)capacity->NumberOfBlocks *
3557 capacity->BlockLength;
3558
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));
3567 }
3568
3569 // Free everything we allocated
3570 //
3571 ExFreePool(parameterList);
3572 ExFreePool(srb);
3573
3574 return status;
3575 }
3576