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 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 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