public unsafe int ReadRandomSectors(TimeSpan timeout, int stopOnNthFail = 0)
        {
            int goodSectors = Params.Image.GoodSectors;
            int imageTracks = Params.Image.SizeTracks;

            try
            {
                bool          useTimeout  = timeout > TimeSpan.Zero;
                DateTime      timeoutTime = DateTime.Now.Add(timeout);
                Timer         sectorTimer = new Timer();
                Random        random      = new Random();
                MList <Point> sectorArray = new MList <Point>(Params.Image.SizeSectors);
                for (int track = Params.FirstTrack; track < Params.LastTrack; track++)
                {
                    if (Params.Side == DiskSide.Side0 && track % 2 != 0)
                    {
                        continue;
                    }
                    if (Params.Side == DiskSide.Side1 && track % 2 != 1)
                    {
                        continue;
                    }
                    for (int sector = 0; sector < Params.Image[track].Layout.Cnt; sector++)
                    {
                        if (Params.Image[track][sector].ProcessResult != SectorProcessResult.Good)
                        {
                            sectorArray.Add(new Point(track, sector));
                        }
                    }
                }
                int prevCylinder = -1;
                int failCounter  = 0;
                while (sectorArray.Cnt > 0 && ((useTimeout && DateTime.Now < timeoutTime) || !useTimeout) && (stopOnNthFail == 0 || (failCounter < stopOnNthFail)))
                {
                    int         index       = random.Next(sectorArray.Cnt);
                    int         track       = sectorArray[index].X;
                    int         sectorIndex = sectorArray[index].Y;
                    SectorInfo  sector      = Params.Image[track][sectorIndex];
                    TrackFormat tf          = Params.Image[track];
                    int         error       = 23;
                    Params.Map.MarkSectorAsProcessing(track, sectorIndex);
                    bool badWritten = sector.ProcessResult == SectorProcessResult.Bad;
                    for (int attempt = 0; attempt < Params.SectorReadAttempts; attempt++)
                    {
                        if (Aborted)
                        {
                            goto abort;
                        }
                        int cylinder = track / 2;
                        if (cylinder == prevCylinder)
                        {
                            int tempCylinder = cylinder + (random.Next(2) == 0 ? -1 : 1);
                            tempCylinder = Math.Max(0, tempCylinder);
                            tempCylinder = Math.Min(tempCylinder, Params.LastTrack / 2);
                            Driver.Seek(DriverHandle, tempCylinder * 2);
                            if (Aborted)
                            {
                                goto abort;
                            }
                            Thread.Sleep(random.Next((int)TrackFormat.SpinTimeStandard)); // Ждем случайное время чтобы приехать на нужный цилиндр в случайной точке.
                        }
                        prevCylinder = cylinder;
                        Driver.Seek(DriverHandle, track);
                        if (Aborted)
                        {
                            goto abort;
                        }
                        WinApi.RtlZeroMemory(memoryHandle, (UIntPtr)sector.SizeBytes);
                        sectorTimer.Start();
                        error = Driver.ReadSectorF(DriverHandle, memoryHandle, sector.Cylinder, sector.SectorNumber, sector.SizeCode, track & 1, sector.Head, 0x0a, 0xff);
                        sectorTimer.Stop();
                        if (error == 0)
                        {
                            Params.Image.WriteGoodSector(memoryHandle, tf, sectorIndex);
                            sectorArray.RemoveAt(index);
                            failCounter = 0;
                            timeoutTime = DateTime.Now.Add(timeout);
                            break;
                        }
                        // Ошибка 27 может быть как в случае отсутствия заголовка, так и в случае когда заголовок имеет ошибку CRC.
                        // Тут сложный вопрос что с этим делать: писать сектор как CrcError или как NoHeader. Пишется как NoHeader.
                        // (проверить была ошибка CRC в заголовке или заголовок вообще не был найден можно сравнив sectorTimer.ElapsedMs с временем вращения tf.SpinTime)
                        bool noHeader = error == 21 || error == 1112 || error == 27;
                        Make30HeadPositionings(error, track);
                        if (error == 23)
                        {
                            Params.Image.WriteBadSector(memoryHandle, tf, sectorIndex);
                            badWritten = true;
                        }
                        else if (noHeader && !badWritten)
                        {
                            Params.Image.WriteNoHeader(memoryHandle, tf, sectorIndex);
                        }
                    }
                    failCounter++;
                }
                return(Params.Image.GoodSectors - goodSectors);

abort:
                Log.Info?.Out("Чтение прервано.");
            }
            finally
            {
                Params.Map?.ClearHighlight(MapCell.Processing);
            }
            return(Params.Image.GoodSectors - goodSectors);
        }
Exemple #2
0
        public unsafe int ReadRandomSectors(TimeSpan timeout, int stopOnNthFail = 0)
        {
            int  goodSectors = Params.Image.GoodSectors;
            int  imageTracks = Params.Image.SizeTracks;
            int *trackHead   = stackalloc int[imageTracks];

            for (int i = 0; i < imageTracks; i++)
            {
                trackHead[i] = -1;
            }
            try
            {
                bool          useTimeout           = timeout > TimeSpan.Zero;
                DateTime      timeoutTime          = DateTime.Now.Add(timeout);
                Timer         sectorTimer          = new Timer();
                Random        random               = new Random();
                UpperSideHead upperSideHead        = Params.UpperSideHead;
                bool          upperSideHeadScanned = false;
                MList <int>   sectorArray          = new MList <int>(Params.Image.SizeSectors);
                for (int i = Params.FirstSectorNum; i < Params.LastSectorNum; i++)
                {
                    int track = i / Params.Image.SectorsOnTrack;
                    if (Params.Side == DiskSide.Side0 && track % 2 != 0)
                    {
                        continue;
                    }
                    if (Params.Side == DiskSide.Side1 && track % 2 != 1)
                    {
                        continue;
                    }
                    if (Params.Image.Sectors[i] != SectorProcessResult.Good)
                    {
                        sectorArray.Add(i);
                    }
                }
                int prevCylinder = -1;
                int failCounter  = 0;
                while (sectorArray.Cnt > 0 && ((useTimeout && DateTime.Now < timeoutTime) || !useTimeout) && (stopOnNthFail == 0 || (failCounter < stopOnNthFail)))
                {
                    int        index     = random.Next(sectorArray.Cnt);
                    int        sectorNum = sectorArray.Data[index];
                    int        track     = sectorNum / Params.SectorsOnTrack;
                    SectorInfo sector    = Params.Image.StandardFormat.Layout.Data[sectorNum - track * Params.SectorsOnTrack];
                    int        error     = 23;
                    Params.Image.Map?.ClearHighlight(MapCell.Processing);
                    Params.Image.Map?.MarkAsProcessing(sectorNum);
                    if (Params.UpperSideHeadAutodetect && trackHead[track] != -1)
                    {
                        upperSideHead = (UpperSideHead)trackHead[track];
                    }
                    if (Params.UpperSideHeadAutodetect && !upperSideHeadScanned && (track & 1) != 0 && trackHead[track] == -1)
                    {
                        UpperSideHead ush = upperSideHead;
                        if (ScanHeadParameter(ref ush, track, Params.CurrentTrackFormat) == 0)
                        {
                            upperSideHead    = ush;
                            trackHead[track] = (int)upperSideHead;
                            Log.Trace?.Out($"Параметр Head для трека {track} определен: {(int)upperSideHead}");
                        }
                        else
                        {
                            Log.Trace?.Out($"Параметр Head для трека {track} определить не удалось.");
                        }
                        upperSideHeadScanned = true;
                    }
                    bool noHeader   = false;
                    bool badWritten = Params.Image.Sectors[sectorNum] == SectorProcessResult.Bad;
                    for (int attempt = 0; attempt < Params.SectorReadAttempts; attempt++)
                    {
                        if (Aborted)
                        {
                            goto abort;
                        }
                        int cylinder = track / 2;
                        if (cylinder == prevCylinder)
                        {
                            int tempCylinder = cylinder + (random.Next(2) == 0 ? -1 : 1);
                            tempCylinder = Math.Max(0, tempCylinder);
                            tempCylinder = Math.Min(tempCylinder, Params.LastTrack / 2);
                            Driver.Seek(DriverHandle, tempCylinder * 2);
                            if (Aborted)
                            {
                                goto abort;
                            }
                            Thread.Sleep(random.Next((int)TrackFormat.SpinTimeStandard)); // Ждем случайное время чтобы приехать на нужный цилиндр в случайной точке.
                        }
                        prevCylinder = cylinder;
                        Driver.Seek(DriverHandle, track);
                        if (Aborted)
                        {
                            goto abort;
                        }
                        sectorTimer.Start();
                        error = Driver.ReadSector(DriverHandle, memoryHandle, track, sector.SectorNumber, upperSideHead, sector.SizeCode);
                        sectorTimer.Stop();
                        if (error == 0)
                        {
                            goto sectorReadSuccessfully;
                        }
                        noHeader = error == 21 || (error == 27 && sectorTimer.ElapsedMs > Params.CurrentTrackFormat.SpinTime);
                        Make30HeadPositionings(error, track);
                        if (error == 23)
                        {
                            Params.Image.WriteBadSectors(sectorNum, memoryHandle, 1, false);
                            badWritten = true;
                        }
                        if (noHeader && track % 2 == 1 && Params.UpperSideHeadAutodetect && trackHead[track] == -1)
                        {
                            UpperSideHead ush = upperSideHead;
                            if (ScanHeadParameter(ref ush, track, Params.CurrentTrackFormat) == 0)
                            {
                                upperSideHead    = ush;
                                trackHead[track] = (int)upperSideHead;
                                Log.Trace?.Out($"Параметр Head для трека {track} определен: {(int)upperSideHead}");
                                attempt--;
                            }
                            else
                            {
                                Log.Trace?.Out($"Параметр Head для трека {track} определить не удалось.");
                            }
                        }
                    }
                    failCounter++;
                    if (!badWritten)
                    {
                        Params.Image.WriteBadSectors(sectorNum, 1, noHeader);
                    }
                    continue;
sectorReadSuccessfully:
                    Params.Image.WriteGoodSectors(sectorNum, memoryHandle, 1);
                    trackHead[track] = (int)upperSideHead;
                    sectorArray.RemoveAt(index);
                    failCounter = 0;
                    timeoutTime = DateTime.Now.Add(timeout);
                }
                return(Params.Image.GoodSectors - goodSectors);

abort:
                Log.Info?.Out("Чтение прервано.");
            }
            finally
            {
                Params.Image.Map?.ClearHighlight(MapCell.Processing);
            }
            return(Params.Image.GoodSectors - goodSectors);
        }