125c7e1a8SPierre Schweitzer /*
225c7e1a8SPierre Schweitzer vfdfmt.c
325c7e1a8SPierre Schweitzer
425c7e1a8SPierre Schweitzer Virtual Floppy Drive for Windows NT platform
525c7e1a8SPierre Schweitzer Kernel mode driver: disk format functions
625c7e1a8SPierre Schweitzer
725c7e1a8SPierre Schweitzer Copyright (C) 2003-2005 Ken Kato
825c7e1a8SPierre Schweitzer */
925c7e1a8SPierre Schweitzer
1025c7e1a8SPierre Schweitzer #include "imports.h"
1125c7e1a8SPierre Schweitzer #include "vfddrv.h"
1225c7e1a8SPierre Schweitzer #include "vfddbg.h"
1325c7e1a8SPierre Schweitzer
1425c7e1a8SPierre Schweitzer #ifdef ALLOC_PRAGMA
1525c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdFormatCheck)
1625c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdFormatTrack)
1725c7e1a8SPierre Schweitzer #endif // ALLOC_PRAGMA
1825c7e1a8SPierre Schweitzer
1925c7e1a8SPierre Schweitzer //
2025c7e1a8SPierre Schweitzer // Media geometry constant table
2125c7e1a8SPierre Schweitzer //
2225c7e1a8SPierre Schweitzer // MediaTypes values added since Win NT DDK
2325c7e1a8SPierre Schweitzer #ifndef F3_640_512
2425c7e1a8SPierre Schweitzer #define F3_640_512 (MEDIA_TYPE)14
2525c7e1a8SPierre Schweitzer #endif
2625c7e1a8SPierre Schweitzer #ifndef F3_1Pt2_512
2725c7e1a8SPierre Schweitzer #define F3_1Pt2_512 (MEDIA_TYPE)17
2825c7e1a8SPierre Schweitzer #endif
2925c7e1a8SPierre Schweitzer
3025c7e1a8SPierre Schweitzer #ifndef __REACTOS__
3125c7e1a8SPierre Schweitzer extern DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = {
3225c7e1a8SPierre Schweitzer {{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default
3325c7e1a8SPierre Schweitzer {{ 40 }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K
3425c7e1a8SPierre Schweitzer {{ 40 }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K
3525c7e1a8SPierre Schweitzer {{ 40 }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K
3625c7e1a8SPierre Schweitzer {{ 40 }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K
3725c7e1a8SPierre Schweitzer {{ 80 }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
3825c7e1a8SPierre Schweitzer {{ 80 }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
3925c7e1a8SPierre Schweitzer {{ 80 }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
4025c7e1a8SPierre Schweitzer {{ 80 }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
4125c7e1a8SPierre Schweitzer {{ 82 }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K
4225c7e1a8SPierre Schweitzer {{ 80 }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
4325c7e1a8SPierre Schweitzer {{ 80 }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
4425c7e1a8SPierre Schweitzer {{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K
4525c7e1a8SPierre Schweitzer {{ 80 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF
4625c7e1a8SPierre Schweitzer {{ 82 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF
4725c7e1a8SPierre Schweitzer {{ 80 }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K
4825c7e1a8SPierre Schweitzer #else
4925c7e1a8SPierre Schweitzer DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = {
50*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default
51*e7b2aa65SHermès Bélusca-Maïto {{ {40} }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K
52*e7b2aa65SHermès Bélusca-Maïto {{ {40} }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K
53*e7b2aa65SHermès Bélusca-Maïto {{ {40} }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K
54*e7b2aa65SHermès Bélusca-Maïto {{ {40} }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K
55*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
56*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
57*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
58*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
59*e7b2aa65SHermès Bélusca-Maïto {{ {82} }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K
60*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
61*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
62*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K
63*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF
64*e7b2aa65SHermès Bélusca-Maïto {{ {82} }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF
65*e7b2aa65SHermès Bélusca-Maïto {{ {80} }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K
6625c7e1a8SPierre Schweitzer #endif
6725c7e1a8SPierre Schweitzer };
6825c7e1a8SPierre Schweitzer
6925c7e1a8SPierre Schweitzer //
7025c7e1a8SPierre Schweitzer // Parameter check for IOCTL_DISK_FORMAT_TRACK and IOCTL_DISK_FORMAT_TRACK_EX
7125c7e1a8SPierre Schweitzer //
7225c7e1a8SPierre Schweitzer NTSTATUS
VfdFormatCheck(PDEVICE_EXTENSION DeviceExtension,PFORMAT_PARAMETERS FormatParams,ULONG InputLength,ULONG ControlCode)7325c7e1a8SPierre Schweitzer VfdFormatCheck(
7425c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension,
7525c7e1a8SPierre Schweitzer PFORMAT_PARAMETERS FormatParams,
7625c7e1a8SPierre Schweitzer ULONG InputLength,
7725c7e1a8SPierre Schweitzer ULONG ControlCode)
7825c7e1a8SPierre Schweitzer {
7925c7e1a8SPierre Schweitzer const DISK_GEOMETRY *geometry;
8025c7e1a8SPierre Schweitzer
8125c7e1a8SPierre Schweitzer // Check media status
8225c7e1a8SPierre Schweitzer
8325c7e1a8SPierre Schweitzer if (!DeviceExtension->FileHandle &&
8425c7e1a8SPierre Schweitzer !DeviceExtension->FileBuffer) {
8525c7e1a8SPierre Schweitzer return STATUS_NO_MEDIA_IN_DEVICE;
8625c7e1a8SPierre Schweitzer }
8725c7e1a8SPierre Schweitzer
8825c7e1a8SPierre Schweitzer // Media is writable?
8925c7e1a8SPierre Schweitzer
9025c7e1a8SPierre Schweitzer if (DeviceExtension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) {
9125c7e1a8SPierre Schweitzer return STATUS_MEDIA_WRITE_PROTECTED;
9225c7e1a8SPierre Schweitzer }
9325c7e1a8SPierre Schweitzer
9425c7e1a8SPierre Schweitzer // Check input parameter size
9525c7e1a8SPierre Schweitzer
9625c7e1a8SPierre Schweitzer if (InputLength < sizeof(FORMAT_PARAMETERS)) {
9725c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
9825c7e1a8SPierre Schweitzer }
9925c7e1a8SPierre Schweitzer
10025c7e1a8SPierre Schweitzer // Choose appropriate DISK_GEOMETRY for current image size
10125c7e1a8SPierre Schweitzer
10225c7e1a8SPierre Schweitzer geometry = DeviceExtension->Geometry;
10325c7e1a8SPierre Schweitzer
10425c7e1a8SPierre Schweitzer if (!geometry) {
10525c7e1a8SPierre Schweitzer return STATUS_DRIVER_INTERNAL_ERROR;
10625c7e1a8SPierre Schweitzer }
10725c7e1a8SPierre Schweitzer
10825c7e1a8SPierre Schweitzer // Input parameter sanity check
10925c7e1a8SPierre Schweitzer
11025c7e1a8SPierre Schweitzer if ((FormatParams->StartHeadNumber > geometry->TracksPerCylinder - 1) ||
11125c7e1a8SPierre Schweitzer (FormatParams->EndHeadNumber > geometry->TracksPerCylinder - 1) ||
11225c7e1a8SPierre Schweitzer (FormatParams->StartCylinderNumber > geometry->Cylinders.LowPart) ||
11325c7e1a8SPierre Schweitzer (FormatParams->EndCylinderNumber > geometry->Cylinders.LowPart) ||
11425c7e1a8SPierre Schweitzer (FormatParams->EndCylinderNumber < FormatParams->StartCylinderNumber))
11525c7e1a8SPierre Schweitzer {
11625c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
11725c7e1a8SPierre Schweitzer }
11825c7e1a8SPierre Schweitzer
11925c7e1a8SPierre Schweitzer // If this is an EX request then make a couple of extra checks
12025c7e1a8SPierre Schweitzer
12125c7e1a8SPierre Schweitzer if (ControlCode == IOCTL_DISK_FORMAT_TRACKS_EX) {
12225c7e1a8SPierre Schweitzer
12325c7e1a8SPierre Schweitzer PFORMAT_EX_PARAMETERS exparams;
12425c7e1a8SPierre Schweitzer
12525c7e1a8SPierre Schweitzer if (InputLength < sizeof(FORMAT_EX_PARAMETERS)) {
12625c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
12725c7e1a8SPierre Schweitzer }
12825c7e1a8SPierre Schweitzer
12925c7e1a8SPierre Schweitzer exparams = (PFORMAT_EX_PARAMETERS)FormatParams;
13025c7e1a8SPierre Schweitzer
13125c7e1a8SPierre Schweitzer if (InputLength <
13225c7e1a8SPierre Schweitzer FIELD_OFFSET(FORMAT_EX_PARAMETERS, SectorNumber) +
13325c7e1a8SPierre Schweitzer exparams->SectorsPerTrack * sizeof(USHORT))
13425c7e1a8SPierre Schweitzer {
13525c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
13625c7e1a8SPierre Schweitzer }
13725c7e1a8SPierre Schweitzer
13825c7e1a8SPierre Schweitzer if (exparams->FormatGapLength > geometry->SectorsPerTrack ||
13925c7e1a8SPierre Schweitzer exparams->SectorsPerTrack != geometry->SectorsPerTrack)
14025c7e1a8SPierre Schweitzer {
14125c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
14225c7e1a8SPierre Schweitzer }
14325c7e1a8SPierre Schweitzer }
14425c7e1a8SPierre Schweitzer
14525c7e1a8SPierre Schweitzer return STATUS_SUCCESS;
14625c7e1a8SPierre Schweitzer }
14725c7e1a8SPierre Schweitzer
14825c7e1a8SPierre Schweitzer //
14925c7e1a8SPierre Schweitzer // Format tracks
15025c7e1a8SPierre Schweitzer // Actually, just fills specified range of tracks with fill characters
15125c7e1a8SPierre Schweitzer //
15225c7e1a8SPierre Schweitzer NTSTATUS
VfdFormatTrack(IN PDEVICE_EXTENSION DeviceExtension,IN PFORMAT_PARAMETERS FormatParams)15325c7e1a8SPierre Schweitzer VfdFormatTrack(
15425c7e1a8SPierre Schweitzer IN PDEVICE_EXTENSION DeviceExtension,
15525c7e1a8SPierre Schweitzer IN PFORMAT_PARAMETERS FormatParams)
15625c7e1a8SPierre Schweitzer {
15725c7e1a8SPierre Schweitzer const DISK_GEOMETRY *geometry;
15825c7e1a8SPierre Schweitzer ULONG track_length;
15925c7e1a8SPierre Schweitzer PUCHAR format_buffer;
16025c7e1a8SPierre Schweitzer LARGE_INTEGER start_offset;
16125c7e1a8SPierre Schweitzer LARGE_INTEGER end_offset;
16225c7e1a8SPierre Schweitzer NTSTATUS status;
16325c7e1a8SPierre Schweitzer
16425c7e1a8SPierre Schweitzer VFDTRACE(0, ("[VFD] VfdFormatTrack - IN\n"));
16525c7e1a8SPierre Schweitzer
16625c7e1a8SPierre Schweitzer ASSERT(DeviceExtension != NULL);
16725c7e1a8SPierre Schweitzer
16825c7e1a8SPierre Schweitzer geometry = DeviceExtension->Geometry;
16925c7e1a8SPierre Schweitzer
17025c7e1a8SPierre Schweitzer if (!geometry) {
17125c7e1a8SPierre Schweitzer return STATUS_DRIVER_INTERNAL_ERROR;
17225c7e1a8SPierre Schweitzer }
17325c7e1a8SPierre Schweitzer
17425c7e1a8SPierre Schweitzer track_length = geometry->BytesPerSector * geometry->SectorsPerTrack;
17525c7e1a8SPierre Schweitzer
17625c7e1a8SPierre Schweitzer format_buffer = (PUCHAR)ExAllocatePoolWithTag(
17725c7e1a8SPierre Schweitzer PagedPool, track_length, VFD_POOL_TAG);
17825c7e1a8SPierre Schweitzer
17925c7e1a8SPierre Schweitzer if (format_buffer == NULL) {
18025c7e1a8SPierre Schweitzer VFDTRACE(0, ("[VFD] cannot allocate a format buffer\n"));
18125c7e1a8SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
18225c7e1a8SPierre Schweitzer }
18325c7e1a8SPierre Schweitzer
18425c7e1a8SPierre Schweitzer RtlFillMemory(format_buffer, track_length, VFD_FORMAT_FILL_DATA);
18525c7e1a8SPierre Schweitzer
18625c7e1a8SPierre Schweitzer start_offset.QuadPart =
18725c7e1a8SPierre Schweitzer FormatParams->StartCylinderNumber * geometry->TracksPerCylinder * track_length +
18825c7e1a8SPierre Schweitzer FormatParams->StartHeadNumber * track_length;
18925c7e1a8SPierre Schweitzer
19025c7e1a8SPierre Schweitzer end_offset.QuadPart =
19125c7e1a8SPierre Schweitzer FormatParams->EndCylinderNumber * geometry->TracksPerCylinder * track_length +
19225c7e1a8SPierre Schweitzer FormatParams->EndHeadNumber * track_length;
19325c7e1a8SPierre Schweitzer
19425c7e1a8SPierre Schweitzer do {
19525c7e1a8SPierre Schweitzer if (DeviceExtension->FileHandle) {
19625c7e1a8SPierre Schweitzer IO_STATUS_BLOCK io_status;
19725c7e1a8SPierre Schweitzer
19825c7e1a8SPierre Schweitzer status = ZwWriteFile(
19925c7e1a8SPierre Schweitzer DeviceExtension->FileHandle,
20025c7e1a8SPierre Schweitzer NULL,
20125c7e1a8SPierre Schweitzer NULL,
20225c7e1a8SPierre Schweitzer NULL,
20325c7e1a8SPierre Schweitzer &io_status,
20425c7e1a8SPierre Schweitzer format_buffer,
20525c7e1a8SPierre Schweitzer track_length,
20625c7e1a8SPierre Schweitzer &start_offset,
20725c7e1a8SPierre Schweitzer NULL);
20825c7e1a8SPierre Schweitzer
20925c7e1a8SPierre Schweitzer if (!NT_SUCCESS(status)) {
21025c7e1a8SPierre Schweitzer VFDTRACE(0, ("[VFD] ZwWriteFile - %s\n",
21125c7e1a8SPierre Schweitzer GetStatusName(status)));
21225c7e1a8SPierre Schweitzer break;
21325c7e1a8SPierre Schweitzer }
21425c7e1a8SPierre Schweitzer }
21525c7e1a8SPierre Schweitzer else {
21625c7e1a8SPierre Schweitzer RtlMoveMemory(
21725c7e1a8SPierre Schweitzer DeviceExtension->FileBuffer + start_offset.QuadPart,
21825c7e1a8SPierre Schweitzer format_buffer,
21925c7e1a8SPierre Schweitzer track_length);
22025c7e1a8SPierre Schweitzer
22125c7e1a8SPierre Schweitzer status = STATUS_SUCCESS;
22225c7e1a8SPierre Schweitzer }
22325c7e1a8SPierre Schweitzer
22425c7e1a8SPierre Schweitzer start_offset.QuadPart += track_length;
22525c7e1a8SPierre Schweitzer }
22625c7e1a8SPierre Schweitzer while (start_offset.QuadPart <= end_offset.QuadPart);
22725c7e1a8SPierre Schweitzer
22825c7e1a8SPierre Schweitzer ExFreePool(format_buffer);
22925c7e1a8SPierre Schweitzer
23025c7e1a8SPierre Schweitzer VFDTRACE(0, ("[VFD] VfdFormatTrack - OUT\n"));
23125c7e1a8SPierre Schweitzer
23225c7e1a8SPierre Schweitzer return status;
23325c7e1a8SPierre Schweitzer }
234