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); }
/// <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); }
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); }