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