Episode 2
Понемногу тестируем используя два экземпляра моста3.
Вносятся некоторые правки, в основном касающиеся web-интерфеса и немного затрагивающие программы, непосредственно работающие с дисками.
Есть пара-тройка больших достижений:
1) Дописана прога замера скорости 140кб. Её особенность в том, что так как индекса на этом приводе нет, приходится читать магнитную запись и делать измерение по ней. Т.е. декодировать адресные поля, но сохраняя при этом первоначальные тайминги читаемого с поверхности потока. Цепочка декодеров, которая используется в остальном софте, так делать не умеет. Поэтому для 140ки я дописал сложнейший код (как я думал, поэтому долго его откладывал) размеров 80 строк и 3 процедуры. Одна процедура собирает биты из потока, вторая складывает их в байты и если находит пролог адресного поля, сразу декодирует его (там FM-кодирование), вытягивая номер трека и номер сектора. И третья процедура запускает дважды вторую, находя повтор какого нибудь адресного поля, после чего замеряет время между первой и второй копией одного и того же адресного поля.
2) Вроде бы выстроилась в конкретный код идея о ручном съёме. Это когда пользователь задаёт диапазон дорожек и формат, а дальше софт - уже с этими знаниями, без обзорного прохода - пытается ковырять отдельные дорожки в соответствии с заданным форматом.
Сложность тут была в том, чтобы переиспользовать код дочитывания диска без кода обзорного прохода. Проще говоря: декодеры используют много параметров (около 10) и надо как-то получить их от пользователя. Если с форматами вроде агатовских всё понятно: указал 140 или 840 и дальше ясно чего ожидать, то с PC нужна и плотность записи и битрейт и количество секторов и т.д. Ещё можно задать сложность автоподбора таблиц фазовой коррекции и подстройку скорости (битрейта). Это позволяет выбирать между более высокой скоростью и более надежным чтением.
3) Я покопался в коде линухового ядра, который умеет изображать USB-device. К сожалению, код, который умеет изображать накопитель данных (mass storage) завязан на понятие драйвера блочного устройства, т.е. по простому пробросить флопик через USB наружу не получится. Это надо, фактически, писать собственный блочный драйвер, который будет работать внутри ядра.
Зато удалось разобрать вопрос о пробросе IP over USB. Там куча протоколов и стандартов, которые заменялись в течение последних лет. В чём полезно для моста3: это позволит протащить web-интерфейс и его настройку через USB, минуя физический Ethernet и упростив, таким образом, подключение моста напрямую к компу (например, к ноуту на выезде). Естесно, с сохранением web-интерфейса.
2 и 3 пункты пока в процессе, но некоторые проведённые тесты обнадеживают.
==
Ошибок в коде читалок пока не находилось. До вчерашнего дня.
Ошибка интересная и я решил её описать.
Итак, мне передали коробку дисков с эпловскими игрушками с просьбой прочитать. Первый диск зашел успешно, с небольшим дочитыванием и без ошибок в итоге.
Второй читался тоже, но как-то неуверенно. Третий шел совсем плохо, выбранный наугад пятый - то же самое.
Интересно, что, судя по спектрам, там была вполне чистая GCR, может быть с некоторыми незначительными косячками (возможно, диск форматировали на одном дисководе, а потом записывали на другом). При этом проги не могли даже определить формат некоторых дорожек (т.е. им не удавалось декодировать ни одного сектора).
Я залез в поток глазками и обнаружил интересное: там были адресные поля обычного агатовского формата, но с какими-то нестандартными эпилогами. Сперва я предположил, что это какой-то вид защиты, но потом, полазив по остальным снятым образам, стал находить странные сочетания: часть треков имеют стандартные эпилоги, часть чередуются между стандартными и нестандартными, а часть имеют только стандартные сектора.
И, наконец, я заметил совсем странное: в потоке, сразу за эпилогом шел интересный байт со значением $80.
Такой байт не может возникнуть "естественным" путём, особенно у Моста3: больше двух нулей подряд запрещено по ограничению спектра дисковода и Мост3 даже не пытается сохранить такие тайминги.
Я сперва подумал о какой-то своей ошибке, но, покопавшись в коде, нашел свою же закладку: код декодера байтового потока умеет вставлять значение $80 в поток если к нему прилетел интервал, превышающий примерно 15 мкс. Фактически, это подсказка о том, что от дисковода слишком долго не было импульсов и получилось что-то вроде сбоя синхронизации.
Почему их не было ? Вероятно потому, что либо форматтер этих дисков выключал запись сразу после записи адресного поля и дисковод затирал несколько бит "по инерции" либо, в момент начала записи поля данных, также возникала пауза в битовом потоке
А почему это не поймали при отладке авторы драйвера или форматтера ? А потому что, очевидно, стандартные драйвера при чтении таких дисков не сталкивались с этой ошибкой.
Я залез в собственные статьи по работе 140-го контроллера и обнаружил, в чём тут дело:
стандартный контроллер 140ки имеет две фазы чтения байта: чтение первых двух бит (D7 и D6) и остальных бит.
Пока он ожидает прихода D7 очередного байта он игнорирует все входящие нули (независимо от их количества).
Но когда единичка D7 пришла, остальные биты он будет хватать с дисковода независимо от их количества и значения.
В моём коде же приход любого семпла с больше чем 2 нулями подряд ломал уже накопленные данные.
Когда я писал этот код я рассуждал так: если пришло больше двух нулей - то данные тут сломаны, байт нет смысла сохранять, нужно синхронизиваться заного.
Но именно при записи эпилога поля происходит следующее: записываются байт $DE, затем $AA, после чего в контроллер закидывается ещё один байт, после чего драйвер выключает режим записи. При этом запись последнего байта не гарантируется (а точнее - от него едва ли успеет записаться хотя бы один бит).
Второй байт ($AA) выглядит как 1010 1010 - дальше идёт неопределённость. Может быть дисковод при выключении записи дёрнет ток в записывающей головке, может быть нет. Может раньше может позже. Это не регламентируется.
Если после 1010 1010 мелькнёт ещё 11 или 01 или 10 - то мой код будет считать его нормальным новым байтом и байт $AA перейдёт от декодера 3 к декодеру 4 (который собирает из отдельных байт поля адреса и данных). Но если после 1010 1010 наступит тишина, то декодер уровня 3 увидит бесконечный ноль и просто заменит уже почти накопленный байт $AA (без одного бита) байтом $80. И уровень 4 не найдёт последний байт эпилога и забракует адресное поле.
Соответственно, я изменил логику таким образом: если накапливаемый байт не равен 0 (ноль означает, что байт уже ушел с уровня 3 на уровень 4 и мы ждём очередную единичку - т.е. байт как бы был прочитан ЦП из контроллера). то при получении бесконечного нуля на входе то, что накоплено в буфере байта, сдвигается максимально влево { while ((obuf & 0x80) == 0) obuf <<= 1; } и отдаётся из уровня 3 на уровень 4, а уже потом в поток добавляется маркер $80 и тоже отдаётся на уровень 4. Он не нужен уровню 4, но он попадёт в промежуточный .eim-файл и, при разборе инцедентов, его можно будет увидеть в редакторе RawEdit.
PS Так как мост2 использует практически оригинальную схему эпловского дешифратора потока, он этой проблемме не подвержен.
Я проверил - он эти диски снял без проблем.
==
Интересность тут в том, что на своих дисках я не сталкивался с этой ошибкой.
Возможно потому, что мост2, которым записано большинство оставшихся у меня дисков, пишет трек за раз, не выключая запись, а те старые диски, которые были записаны ещё в конце 80-х, тоже писались копировщиком ИКП, который, возможно, тоже умеет писать трек за раз.
А может быть дело в дисководах. Может быть даже в экземпляре дисководов. Выключить запись, вероятно, можно по разному или в чуть разный момент. Если контроллер успевает выставить третий байт на запись - хотя бы один бит - ошибка бы уже не проявлялась.
Это может зависеть и от драйвера.