Example #1
0
        public static unsafe bool GetResult(IntPtr driverHandle, out tagFD_CMD_RESULT cmdResult)
        {
            tagFD_CMD_RESULT result;
            int  inBuffer;
            uint dwRead;
            bool r = DeviceIoControl(driverHandle, IOCTL_FD_GET_RESULT, (IntPtr)(&inBuffer), 0, (IntPtr)(&result), (uint)sizeof(tagFD_CMD_RESULT), out dwRead, IntPtr.Zero);

            cmdResult = result;
            return(r);
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="result">0 - head определен. 1 - Заголовки не найдены. 2 - Заголовок найден, но он не TR-DOS</param>
        /// <param name="track"></param>
        /// <param name="trackFormat"></param>
        /// <returns></returns>
        private int ScanHeadParameter(ref UpperSideHead result, int track, TrackFormat trackFormat)
        {
            tagFD_READ_ID_PARAMS pars = new tagFD_READ_ID_PARAMS()
            {
                flags = Driver.FD_OPTION_MFM,
                head  = (byte)(track & 1)
            };
            tagFD_CMD_RESULT cmdResult = new tagFD_CMD_RESULT();

            if (!Driver.ReadId(DriverHandle, pars, out cmdResult))
            {
                Log.Trace?.Out($"Функция ReadId вернула false. Cylinder: {cmdResult.cyl} | Sector: {cmdResult.sector} | Size: {cmdResult.size} | Head: {cmdResult.head} | LastError: {Marshal.GetLastWin32Error()}");
                return(1);
            }
            //if (cmdResult.sector < 1 || cmdResult.sector > 16 || cmdResult.size != 1)
            //{
            //    Log.Trace?.Out($"Формат не TR-DOS. Cylinder: {cmdResult.cyl} | Sector: {cmdResult.sector} | Size: {cmdResult.size} | Head: {cmdResult.head}");
            //    return 2;
            //}
            trackFormat.SyncByHeader(track, cmdResult.sector);
            Log.Trace?.Out($"Cylinder: {cmdResult.cyl} | Sector: {cmdResult.sector} | Size: {cmdResult.size} | Head: {cmdResult.head}");
            result = (UpperSideHead)cmdResult.head;
            return(0);
        }
        /// <summary>
        /// Сканирование трека. Сканировать может в двух режимах: по времени оборота диска и по зацикливанию потока секторов.
        /// При сканировании по времени оборота диска скорость диска должна быть в районе 300 об/мин, т.е. замедлять диск не надо, иначе будут ошибки.
        /// Если byLooping == true, то конец трека определяется по зацикливанию потока секторов, но сектора сканируются не менее 150 мс и не более 1000 мс.
        /// </summary>
        /// <param name="track"></param>
        /// <returns></returns>
        public unsafe bool ScanFormat(TrackFormat result, int track, bool byLooping)
        {
            int ilayoutCnt = 0;

            scanFormatBuffer.Layout.Cnt = 0;
            SectorInfo[]         layout = scanFormatBuffer.Layout.Data;
            tagFD_READ_ID_PARAMS pars   = new tagFD_READ_ID_PARAMS()
            {
                flags = Driver.FD_OPTION_MFM,
                head  = (byte)(track & 1)
            };
            tagFD_CMD_RESULT cmdResult = new tagFD_CMD_RESULT();

            scanFormatStopwatch.Restart();
            scanFormatTotalTime.Stop();
            int firstIndex = 1;

            for (int i = 0; i < scanFormatBuffer.Layout.Capacity; i++)
            {
                if (Aborted)
                {
                    return(false);
                }
                if (!Driver.ReadId(DriverHandle, pars, out cmdResult))
                {
                    int error = Marshal.GetLastWin32Error();
                    Log.Trace?.Out($"Функция ReadId вернула false. i={i}. LastError={error}");
                    if (Aborted)
                    {
                        return(false);
                    }
                    Make30HeadPositionings(error, track);
                    if (scanFormatBuffer.Layout.Cnt == 0)
                    {
                        goto success;
                    }
                    return(false);
                }
                double timeMs = scanFormatStopwatch.ElapsedMs;
                scanFormatStopwatch.Restart();
                if (!scanFormatTotalTime.IsRunning)
                {
                    scanFormatTotalTime.Restart();
                }
                if (!byLooping && scanFormatTotalTime.ElapsedMs > 209)
                {
                    goto success;
                }
                layout[ilayoutCnt] = new SectorInfo()
                {
                    Cylinder     = cmdResult.cyl,
                    Head         = cmdResult.head,
                    SectorNumber = cmdResult.sector,
                    SizeCode     = cmdResult.size,
                    TimeMs       = timeMs
                };
                ilayoutCnt++;
                scanFormatBuffer.Layout.Cnt = ilayoutCnt;

                // Бывают случаи когда заголовок сектора читается на первом обороте и не читается на втором.
                // Из-за этого алгоритм, в котором повтор сектора определяется сравнением с первым прочитанным заголовком, иногда даёт сбои.
                // Поэтому ищем встечался ли ранее только что прочитанный сектор среди всех прочитанных заголовков, а не только сравниваем с первым.
                // По отношению к найденному сектору замеряем время вращения. Если оно больше 250 мс, значит этот сектор был пропущен на одном из оборотов
                // и такую последовательность брать нельзя. Если время меньше 150, значит на треке есть сектора с одинаковыми параметрами.

                if (byLooping)
                {
                    for (int u = 0; u < ilayoutCnt - 1; u++)
                    {
                        if (layout[u].Cylinder == cmdResult.cyl &&
                            layout[u].Head == cmdResult.head &&
                            layout[u].SectorNumber == cmdResult.sector &&
                            layout[u].SizeCode == cmdResult.size)
                        {
                            double spinTime = 0;
                            for (int p = u + 1; p < ilayoutCnt; p++)
                            {
                                spinTime += layout[p].TimeMs;
                            }
                            if (spinTime > 250 || spinTime < 150)
                            {
                                continue;
                            }
                            firstIndex = u + 1;
                            goto success;
                        }
                    }
                    if (scanFormatTotalTime.ElapsedMs > 1000)
                    {
                        Log.Trace?.Out($"Не удалось найти цикл в последовательности секторов из-за нестабильного чтения. Сканироваие прервано по таймауту.");
                        return(false);
                    }
                }
            }
            return(false);

success:
            result.AssignLayout(scanFormatBuffer, track, cmdResult.sector, firstIndex);
            Log.Trace?.Out($"Время сканирования трека {track}: {GP.ToString(scanFormatTotalTime.ElapsedMs, 2)}");
            return(true);
        }
Example #4
0
        public static unsafe bool ReadId(IntPtr driverHandle, tagFD_READ_ID_PARAMS pars, out tagFD_CMD_RESULT cmdResult)
        {
            tagFD_CMD_RESULT result;
            uint             dwRead;
            bool             r = DeviceIoControl(driverHandle, IOCTL_FDCMD_READ_ID, (IntPtr)(&pars), (uint)sizeof(tagFD_READ_ID_PARAMS), (IntPtr)(&result), (uint)sizeof(tagFD_CMD_RESULT), out dwRead, IntPtr.Zero);

            cmdResult = result;
            return(r);
        }