public DiskReader2(DiskReaderParams2 pars) { Params = pars; }
public object Clone() { DiskReaderParams2 r = (DiskReaderParams2)MemberwiseClone(); return(r); }
public unsafe void ReadTrack(int track, DiskReaderParams2 pars, ScanMode scanMode) { // Массив sectors: // D0 - Признак обработанного сектора при чтении трека в одной попытке. Обнуляется перед каждой попыткой чтения трека. // D1 - Используется в блоке чтения заголовков. Отмечаются сектора заголовки которых были найдены. Вне этого блока не используется. // D2 - Запрет чтения сектора из-за того что его заголовок был прочитан SectorReadAttempts раз и не был найден. Параметр сохраняется между попытками чтения трека. TrackFormat trackF = pars.Image.Tracks[track]; const int sectorArrayLen = 50; int * sectors = stackalloc int[sectorArrayLen]; for (int i = 0; i < sectorArrayLen; i++) { sectors[i] = 0; } bool trackScanned = false; for (int attempt = 0; attempt < pars.SectorReadAttempts; attempt++) { if (Aborted) { return; } // Сканирование трека. if ( ((scanMode == ScanMode.Once && !trackScanned) || (scanMode == ScanMode.UnscannedOnly && trackF.FormatName == TrackFormatName.Unscanned) || scanMode == ScanMode.EachTrackRead) && (trackF.MaxGap() > 128 + TrackFormat.MinSectorHeaderSize || trackF.ContainsCalculatedTime()) ) { // workTrackFormat и longestTrackFormat используются чтобы не плодить объекты. // Объект scanFormatBuffer используется функциями ScanFormat и CombineFormats, поэтому его брать нельзя. trackF.Scanning = true; trackF.MapModified = true; if (ScanFormat(workTrackFormat, track, true)) { for (int i = 0; i < workTrackFormat.Layout.Cnt; i++) { workTrackFormat.Layout.Data[i].MapCellValue = MapCell.Unprocessed; } if (CombineFormats(track, trackF, workTrackFormat, longestTrackFormat)) { trackF.Assign(longestTrackFormat); trackF.MapModified = true; } } trackF.Scanning = false; trackF.MapModified = true; trackScanned = true; if (Aborted) { return; } } if (trackF.Layout.Cnt > sectorArrayLen) { Log.Error?.Out($"Число секторов превышает размер рабочего массива: {trackF.Layout.Cnt}"); throw new Exception(); } for (int i = 0; i < trackF.Layout.Cnt; i++) { sectors[i] &= ~1; } bool wasError = false; trackTimer.Restart(); int skip = 0; int processedSectors = 0; int sectorCounter = 0; SectorInfo diskSector; while (processedSectors < trackF.Layout.Cnt) { diskSector = trackF.Layout.Data[sectorCounter]; int sectorIndex = sectorCounter; sectorCounter++; skip++; if ((sectors[sectorIndex] & 1) != 0) { continue; } sectors[sectorIndex] |= 1; processedSectors++; if ((sectors[sectorIndex] & 4) != 0) { continue; } if (trackF.Layout.Data[sectorIndex].ProcessResult == SectorProcessResult.Good) { continue; } skip = 0; pars.Map.MarkSectorAsProcessing(track, sectorIndex); WinApi.RtlZeroMemory(memoryHandle, (UIntPtr)diskSector.SizeBytes); int error = Driver.ReadSectorF(DriverHandle, memoryHandle, diskSector.Cylinder, diskSector.SectorNumber, diskSector.SizeCode, track & 1, diskSector.Head, 0x0a, 0xff); double curTimeSinceSync = trackF.Timer.ElapsedMs; bool badWritten = diskSector.ProcessResult == SectorProcessResult.Bad; if (error == 0) { pars.Image.WriteGoodSector(memoryHandle, trackF, sectorIndex); } else { wasError = true; // Если надо проверить CRC-Error заголовка: (error == 27 && curTimeSinceSync > trackF.SpinTime) bool noHeader = error == 21 || error == 1112 || error == 27; if (noHeader) { if (!badWritten) { pars.Image.WriteNoHeader(memoryHandle, trackF, sectorIndex); } Make30HeadPositionings(error, track); } else if (error == 23) { pars.Image.WriteBadSector(memoryHandle, trackF, sectorIndex); badWritten = true; } else { Log.Info?.Out($"Необработанная ошибка при чтении сектора: {error}"); } } if (Aborted) { return; } } Log.Trace?.Out($"Время чтения трека: {GP.ToString(trackTimer.ElapsedMs, 2)}"); trackTimer.Restart(); if (!wasError) { break; } } }