xref: /reactos/modules/rosapps/drivers/vfd/vfdfmt.c (revision e7b2aa65)
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