mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 14:18:41 +00:00
234 lines
6.4 KiB
C
234 lines
6.4 KiB
C
/*
|
|
vfdfmt.c
|
|
|
|
Virtual Floppy Drive for Windows NT platform
|
|
Kernel mode driver: disk format functions
|
|
|
|
Copyright (C) 2003-2005 Ken Kato
|
|
*/
|
|
|
|
#include "imports.h"
|
|
#include "vfddrv.h"
|
|
#include "vfddbg.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, VfdFormatCheck)
|
|
#pragma alloc_text(PAGE, VfdFormatTrack)
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
//
|
|
// Media geometry constant table
|
|
//
|
|
// MediaTypes values added since Win NT DDK
|
|
#ifndef F3_640_512
|
|
#define F3_640_512 (MEDIA_TYPE)14
|
|
#endif
|
|
#ifndef F3_1Pt2_512
|
|
#define F3_1Pt2_512 (MEDIA_TYPE)17
|
|
#endif
|
|
|
|
#ifndef __REACTOS__
|
|
extern DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = {
|
|
{{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default
|
|
{{ 40 }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K
|
|
{{ 40 }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K
|
|
{{ 40 }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K
|
|
{{ 40 }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K
|
|
{{ 80 }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
|
|
{{ 80 }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
|
|
{{ 80 }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
|
|
{{ 80 }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
|
|
{{ 82 }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K
|
|
{{ 80 }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
|
|
{{ 80 }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
|
|
{{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K
|
|
{{ 80 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF
|
|
{{ 82 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF
|
|
{{ 80 }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K
|
|
#else
|
|
DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = {
|
|
{{ {80} }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default
|
|
{{ {40} }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K
|
|
{{ {40} }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K
|
|
{{ {40} }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K
|
|
{{ {40} }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K
|
|
{{ {80} }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
|
|
{{ {80} }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k
|
|
{{ {80} }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
|
|
{{ {80} }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K
|
|
{{ {82} }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K
|
|
{{ {80} }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
|
|
{{ {80} }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K
|
|
{{ {80} }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K
|
|
{{ {80} }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF
|
|
{{ {82} }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF
|
|
{{ {80} }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K
|
|
#endif
|
|
};
|
|
|
|
//
|
|
// Parameter check for IOCTL_DISK_FORMAT_TRACK and IOCTL_DISK_FORMAT_TRACK_EX
|
|
//
|
|
NTSTATUS
|
|
VfdFormatCheck(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
PFORMAT_PARAMETERS FormatParams,
|
|
ULONG InputLength,
|
|
ULONG ControlCode)
|
|
{
|
|
const DISK_GEOMETRY *geometry;
|
|
|
|
// Check media status
|
|
|
|
if (!DeviceExtension->FileHandle &&
|
|
!DeviceExtension->FileBuffer) {
|
|
return STATUS_NO_MEDIA_IN_DEVICE;
|
|
}
|
|
|
|
// Media is writable?
|
|
|
|
if (DeviceExtension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) {
|
|
return STATUS_MEDIA_WRITE_PROTECTED;
|
|
}
|
|
|
|
// Check input parameter size
|
|
|
|
if (InputLength < sizeof(FORMAT_PARAMETERS)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Choose appropriate DISK_GEOMETRY for current image size
|
|
|
|
geometry = DeviceExtension->Geometry;
|
|
|
|
if (!geometry) {
|
|
return STATUS_DRIVER_INTERNAL_ERROR;
|
|
}
|
|
|
|
// Input parameter sanity check
|
|
|
|
if ((FormatParams->StartHeadNumber > geometry->TracksPerCylinder - 1) ||
|
|
(FormatParams->EndHeadNumber > geometry->TracksPerCylinder - 1) ||
|
|
(FormatParams->StartCylinderNumber > geometry->Cylinders.LowPart) ||
|
|
(FormatParams->EndCylinderNumber > geometry->Cylinders.LowPart) ||
|
|
(FormatParams->EndCylinderNumber < FormatParams->StartCylinderNumber))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
// If this is an EX request then make a couple of extra checks
|
|
|
|
if (ControlCode == IOCTL_DISK_FORMAT_TRACKS_EX) {
|
|
|
|
PFORMAT_EX_PARAMETERS exparams;
|
|
|
|
if (InputLength < sizeof(FORMAT_EX_PARAMETERS)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
exparams = (PFORMAT_EX_PARAMETERS)FormatParams;
|
|
|
|
if (InputLength <
|
|
FIELD_OFFSET(FORMAT_EX_PARAMETERS, SectorNumber) +
|
|
exparams->SectorsPerTrack * sizeof(USHORT))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (exparams->FormatGapLength > geometry->SectorsPerTrack ||
|
|
exparams->SectorsPerTrack != geometry->SectorsPerTrack)
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Format tracks
|
|
// Actually, just fills specified range of tracks with fill characters
|
|
//
|
|
NTSTATUS
|
|
VfdFormatTrack(
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
IN PFORMAT_PARAMETERS FormatParams)
|
|
{
|
|
const DISK_GEOMETRY *geometry;
|
|
ULONG track_length;
|
|
PUCHAR format_buffer;
|
|
LARGE_INTEGER start_offset;
|
|
LARGE_INTEGER end_offset;
|
|
NTSTATUS status;
|
|
|
|
VFDTRACE(0, ("[VFD] VfdFormatTrack - IN\n"));
|
|
|
|
ASSERT(DeviceExtension != NULL);
|
|
|
|
geometry = DeviceExtension->Geometry;
|
|
|
|
if (!geometry) {
|
|
return STATUS_DRIVER_INTERNAL_ERROR;
|
|
}
|
|
|
|
track_length = geometry->BytesPerSector * geometry->SectorsPerTrack;
|
|
|
|
format_buffer = (PUCHAR)ExAllocatePoolWithTag(
|
|
PagedPool, track_length, VFD_POOL_TAG);
|
|
|
|
if (format_buffer == NULL) {
|
|
VFDTRACE(0, ("[VFD] cannot allocate a format buffer\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlFillMemory(format_buffer, track_length, VFD_FORMAT_FILL_DATA);
|
|
|
|
start_offset.QuadPart =
|
|
FormatParams->StartCylinderNumber * geometry->TracksPerCylinder * track_length +
|
|
FormatParams->StartHeadNumber * track_length;
|
|
|
|
end_offset.QuadPart =
|
|
FormatParams->EndCylinderNumber * geometry->TracksPerCylinder * track_length +
|
|
FormatParams->EndHeadNumber * track_length;
|
|
|
|
do {
|
|
if (DeviceExtension->FileHandle) {
|
|
IO_STATUS_BLOCK io_status;
|
|
|
|
status = ZwWriteFile(
|
|
DeviceExtension->FileHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&io_status,
|
|
format_buffer,
|
|
track_length,
|
|
&start_offset,
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
VFDTRACE(0, ("[VFD] ZwWriteFile - %s\n",
|
|
GetStatusName(status)));
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
RtlMoveMemory(
|
|
DeviceExtension->FileBuffer + start_offset.QuadPart,
|
|
format_buffer,
|
|
track_length);
|
|
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
start_offset.QuadPart += track_length;
|
|
}
|
|
while (start_offset.QuadPart <= end_offset.QuadPart);
|
|
|
|
ExFreePool(format_buffer);
|
|
|
|
VFDTRACE(0, ("[VFD] VfdFormatTrack - OUT\n"));
|
|
|
|
return status;
|
|
}
|