1 /*
2 vfdfmt.c
3
4 Virtual Floppy Drive for Windows NT platform
5 Kernel mode driver: disk format functions
6
7 Copyright (C) 2003-2005 Ken Kato
8 */
9
10 #include "imports.h"
11 #include "vfddrv.h"
12 #include "vfddbg.h"
13
14 #ifdef ALLOC_PRAGMA
15 #pragma alloc_text(PAGE, VfdFormatCheck)
16 #pragma alloc_text(PAGE, VfdFormatTrack)
17 #endif // ALLOC_PRAGMA
18
19 //
20 // Media geometry constant table
21 //
22 // MediaTypes values added since Win NT DDK
23 #ifndef F3_640_512
24 #define F3_640_512 (MEDIA_TYPE)14
25 #endif
26 #ifndef F3_1Pt2_512
27 #define F3_1Pt2_512 (MEDIA_TYPE)17
28 #endif
29
30 #ifndef __REACTOS__
31 extern DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = {
32 {{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default
33 {{ 40 }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K
34 {{ 40 }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K
35 {{ 40 }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K
36 {{ 40 }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K
37 {{ 80 }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
38 {{ 80 }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
39 {{ 80 }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
40 {{ 80 }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
41 {{ 82 }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K
42 {{ 80 }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
43 {{ 80 }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
44 {{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K
45 {{ 80 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF
46 {{ 82 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF
47 {{ 80 }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K
48 #else
49 DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = {
50 {{ {80} }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default
51 {{ {40} }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K
52 {{ {40} }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K
53 {{ {40} }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K
54 {{ {40} }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K
55 {{ {80} }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
56 {{ {80} }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
57 {{ {80} }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
58 {{ {80} }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
59 {{ {82} }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K
60 {{ {80} }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
61 {{ {80} }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
62 {{ {80} }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K
63 {{ {80} }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF
64 {{ {82} }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF
65 {{ {80} }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K
66 #endif
67 };
68
69 //
70 // Parameter check for IOCTL_DISK_FORMAT_TRACK and IOCTL_DISK_FORMAT_TRACK_EX
71 //
72 NTSTATUS
VfdFormatCheck(PDEVICE_EXTENSION DeviceExtension,PFORMAT_PARAMETERS FormatParams,ULONG InputLength,ULONG ControlCode)73 VfdFormatCheck(
74 PDEVICE_EXTENSION DeviceExtension,
75 PFORMAT_PARAMETERS FormatParams,
76 ULONG InputLength,
77 ULONG ControlCode)
78 {
79 const DISK_GEOMETRY *geometry;
80
81 // Check media status
82
83 if (!DeviceExtension->FileHandle &&
84 !DeviceExtension->FileBuffer) {
85 return STATUS_NO_MEDIA_IN_DEVICE;
86 }
87
88 // Media is writable?
89
90 if (DeviceExtension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) {
91 return STATUS_MEDIA_WRITE_PROTECTED;
92 }
93
94 // Check input parameter size
95
96 if (InputLength < sizeof(FORMAT_PARAMETERS)) {
97 return STATUS_INVALID_PARAMETER;
98 }
99
100 // Choose appropriate DISK_GEOMETRY for current image size
101
102 geometry = DeviceExtension->Geometry;
103
104 if (!geometry) {
105 return STATUS_DRIVER_INTERNAL_ERROR;
106 }
107
108 // Input parameter sanity check
109
110 if ((FormatParams->StartHeadNumber > geometry->TracksPerCylinder - 1) ||
111 (FormatParams->EndHeadNumber > geometry->TracksPerCylinder - 1) ||
112 (FormatParams->StartCylinderNumber > geometry->Cylinders.LowPart) ||
113 (FormatParams->EndCylinderNumber > geometry->Cylinders.LowPart) ||
114 (FormatParams->EndCylinderNumber < FormatParams->StartCylinderNumber))
115 {
116 return STATUS_INVALID_PARAMETER;
117 }
118
119 // If this is an EX request then make a couple of extra checks
120
121 if (ControlCode == IOCTL_DISK_FORMAT_TRACKS_EX) {
122
123 PFORMAT_EX_PARAMETERS exparams;
124
125 if (InputLength < sizeof(FORMAT_EX_PARAMETERS)) {
126 return STATUS_INVALID_PARAMETER;
127 }
128
129 exparams = (PFORMAT_EX_PARAMETERS)FormatParams;
130
131 if (InputLength <
132 FIELD_OFFSET(FORMAT_EX_PARAMETERS, SectorNumber) +
133 exparams->SectorsPerTrack * sizeof(USHORT))
134 {
135 return STATUS_INVALID_PARAMETER;
136 }
137
138 if (exparams->FormatGapLength > geometry->SectorsPerTrack ||
139 exparams->SectorsPerTrack != geometry->SectorsPerTrack)
140 {
141 return STATUS_INVALID_PARAMETER;
142 }
143 }
144
145 return STATUS_SUCCESS;
146 }
147
148 //
149 // Format tracks
150 // Actually, just fills specified range of tracks with fill characters
151 //
152 NTSTATUS
VfdFormatTrack(IN PDEVICE_EXTENSION DeviceExtension,IN PFORMAT_PARAMETERS FormatParams)153 VfdFormatTrack(
154 IN PDEVICE_EXTENSION DeviceExtension,
155 IN PFORMAT_PARAMETERS FormatParams)
156 {
157 const DISK_GEOMETRY *geometry;
158 ULONG track_length;
159 PUCHAR format_buffer;
160 LARGE_INTEGER start_offset;
161 LARGE_INTEGER end_offset;
162 NTSTATUS status;
163
164 VFDTRACE(0, ("[VFD] VfdFormatTrack - IN\n"));
165
166 ASSERT(DeviceExtension != NULL);
167
168 geometry = DeviceExtension->Geometry;
169
170 if (!geometry) {
171 return STATUS_DRIVER_INTERNAL_ERROR;
172 }
173
174 track_length = geometry->BytesPerSector * geometry->SectorsPerTrack;
175
176 format_buffer = (PUCHAR)ExAllocatePoolWithTag(
177 PagedPool, track_length, VFD_POOL_TAG);
178
179 if (format_buffer == NULL) {
180 VFDTRACE(0, ("[VFD] cannot allocate a format buffer\n"));
181 return STATUS_INSUFFICIENT_RESOURCES;
182 }
183
184 RtlFillMemory(format_buffer, track_length, VFD_FORMAT_FILL_DATA);
185
186 start_offset.QuadPart =
187 FormatParams->StartCylinderNumber * geometry->TracksPerCylinder * track_length +
188 FormatParams->StartHeadNumber * track_length;
189
190 end_offset.QuadPart =
191 FormatParams->EndCylinderNumber * geometry->TracksPerCylinder * track_length +
192 FormatParams->EndHeadNumber * track_length;
193
194 do {
195 if (DeviceExtension->FileHandle) {
196 IO_STATUS_BLOCK io_status;
197
198 status = ZwWriteFile(
199 DeviceExtension->FileHandle,
200 NULL,
201 NULL,
202 NULL,
203 &io_status,
204 format_buffer,
205 track_length,
206 &start_offset,
207 NULL);
208
209 if (!NT_SUCCESS(status)) {
210 VFDTRACE(0, ("[VFD] ZwWriteFile - %s\n",
211 GetStatusName(status)));
212 break;
213 }
214 }
215 else {
216 RtlMoveMemory(
217 DeviceExtension->FileBuffer + start_offset.QuadPart,
218 format_buffer,
219 track_length);
220
221 status = STATUS_SUCCESS;
222 }
223
224 start_offset.QuadPart += track_length;
225 }
226 while (start_offset.QuadPart <= end_offset.QuadPart);
227
228 ExFreePool(format_buffer);
229
230 VFDTRACE(0, ("[VFD] VfdFormatTrack - OUT\n"));
231
232 return status;
233 }
234