Предлагаю немного освежить тему - Цифровая археология 1801: неудержимое диско 128
Кстати, Alex_K, спасибо Вам за посты в этой теме - они мне очень помогли при реверсе, и очень много из сказанного Вами подтвердилось полностью.
Предлагаю немного освежить тему - Цифровая археология 1801: неудержимое диско 128
Кстати, Alex_K, спасибо Вам за посты в этой теме - они мне очень помогли при реверсе, и очень много из сказанного Вами подтвердилось полностью.
Последний раз редактировалось Vslav; 15.10.2013 в 08:37.
В описании ВП1-128 написано, что CRC вычисляется по формуле: 1 + x^5 + x^12 + x^16.
Но по такой формуле работают несколько разных алгоритмов CRC-16, дающих разные результаты, например:
Есть ли возможность уточнить, какой именно алгоритм у генератора CRC ВП1-128 ?Код:KERMIT ( CCITT ) width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 XMODEM width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31C3 CRC-16 width=16 poly=0x1021 init=0xFFFF refin=false refout=false xorout=0x0000 check=0x29B1 X-25 width=16 poly=0x1021 init=0xFFFF refin=true refout=true xorout=0xFFFF check=0x906E
По идее - он должен перебирать биты каждого записываемого слова от старшего к младшему ( в порядке их расположения на диске ).
Update:
Я тут начал моделировать запись сектора, выявил еще один косяк ВП1-128, она оказывается бит готовности данных ставит сильно заранее (до момента перенесения старшего байта из регистра данных в сдвиговый регистр), и если быстрая шина МПИ (как в используемой сейчас модели процессора - он пишет-читает максимально быстро), то она успевает переписать регистр данных быстрее чем из него успевает переписаться старший байт в сдвиговый регистр (потому что увидела раннюю готовность). Сейчас ввел в транзакции МПИ задержки, будут результаты - отпишу.
Последний раз редактировалось Vslav; 13.12.2013 в 13:50.
Контроллеры DEC и IBM ( если верить документации ) вычисляют CRC так:
1. Начальное значение CRC = 0xFFFF ;
2. Старший бит идёт первым ;
3. Запись вычисленной суммы без инверсии.
Т.е. по сути - это одно и то же, только инверсия результата выполняется до начала вычисления CRC, а не после.
...
Вычисление CRC начинается в момент записи маркера, поэтому возникают два вопроса:
1. Что именно запускает генератор CRC при записи:
1.1. Установка бита WM (9) ;
1.2. То же + байт 0xA1 в сдвиговом регистре.
2. Если генератор CRC в ходе записи не был запущен - будет ли выполнена запись CRC ( 0xFFFF ) в момент пропуска требования ?
---------- Post added at 13:08 ---------- Previous post was at 12:16 ----------
Похоже, что алгоритм такой. Байтовый вариант выглядит так:
Код:unsigned short crc16( unsigned char byte, int step ) { static unsigned short crc = 0; if( step == 0 ) { crc = 0; } crc ^= unsigned short ( byte ) << 8; for( int i = 0 ; i < 8 ; i++ ) { if( crc & 0x8000 ) crc = (crc << 1) ^ 0x1021; else crc = crc << 1; } return crc; }
---------- Post added at 13:27 ---------- Previous post was at 13:08 ----------
Также ( если я правильно понял ) при чтении CRC проверяется так - если требование выполнено, то содержимое регистра данных интерпретируется как данные и включается в расчёт CRC, если же требование не выполнено - содержимое регистра данных интерпретируется как инверсное значение CRC, прибавляется к рассчитанному значению CRC и результат проверяется на равенство 0xFFFF.
Но тогда получается, что если продолжать забирать данные из регистра данных - инверсное значение CRC будет прочитано как обычные данные и чтение пойдёт дальше.
А что в таком случае произойдёт при считывании маркера:
1. Чтение продолжится, но произойдёт сброс генератора CRC и расчёт CRC начнётся заново со считанного байта 0xA1 ;
2. Произойдёт что-то ещё..
Последний раз редактировалось Patron; 14.12.2013 в 12:14.
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Установка бита WM игнорируется, достаточно обнаружения 0xA1 в сдвиговом регистре.
Я сейчас выполил такое моделирование:
На выходе записываемых данных получилось:Код:qbus_write(16'O177130, 16'O000000); qbus_write(16'O177132, 16'H0000); qbus_waitr(); qbus_write(16'O177132, 16'H0000); qbus_waitr(); qbus_write(16'O177132, 16'HA1A1); qbus_waitr(); qbus_write(16'O177132, 16'H3130); qbus_waitr(); qbus_write(16'O177132, 16'H3332); qbus_waitr();
Вот текст программки которая соответствует извлеченному алгоритму:Код:0x00 0x00 0x00 0x00 0xA1 (в этот момент обнулился регистр CRC и началось вычисление с этого маркера, еще я пробовал писать снова 0xA1A1 но сброса боьлше не было - это однократный процесс после перехода от чтения к записи) 0xA1 0x30 (то есть, сначала МЛАДШИЙ байт, старший бит первым) 0x31 (то есть, потом СТАРШИЙ байт, старший бит первым) 0x32 0x33 (после этого байта содержимое регистра CRC = 0x6EE9) 0x91 (инвертированное 0x6E. Сначала пишется СТАРШИЙ байт инвертированной суммы) 0x16 (инвертированное 0xE9. Потом пишется МЛАДШИЙ байт инвертированной суммы)
(она отличается от канонического вида - на инверсию влияет XOR входного бита и выдвигаемого):
Код:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> unsigned short int crc16(unsigned short crc, unsigned char data) { int i, bit; printf("\r\n %02X(%04X,", data, crc); for(i=0; i<8; i++) { bit = (data >> 7) & 1; if (crc & 0x8000) { bit ^= 1; } crc <<= 1; crc |= bit; if (bit == 0) { crc ^= 0x1020; } data <<= 1; } printf("%04X)", crc); return crc; } int main(int argc, char *argv[]) { unsigned short crc, tmp; crc = 0; crc = crc16(crc, 0xA1); crc = crc16(crc, 0xA1); crc = crc16(crc, 0x30); crc = crc16(crc, 0x31); crc = crc16(crc, 0x32); crc = crc16(crc, 0x33); tmp = ~crc; printf("\r\nCRC: %04X", tmp); crc = 0; crc = crc16(crc, 0xA1); crc = crc16(crc, 0xA1); crc = crc16(crc, 0x30); crc = crc16(crc, 0x31); crc = crc16(crc, 0x32); crc = crc16(crc, 0x33); crc = crc16(crc, (tmp >> 8) & 0xFF); crc = crc16(crc, (tmp >> 0) & 0xFF); printf("\r\nTMP: %04X", crc); if (crc == 0xFFFF) printf(" CRC OK"); printf("\r\n"); return 0; }Да (промоделировал, заменил в примере выше A1 на A2), будет выполнена запись, но поскольку регистр CRC не был правильно проинициализирован нулем, запишется два мусорных байта (взависимости что там в регистре CRC было при начале записи)2. Если генератор CRC в ходе записи не был запущен - будет ли выполнена запись CRC ( 0xFFFF ) в момент пропуска требования ?
Похоже что тут ситуация такая - CRC читается как обычные данные, и после того как они прочитаны просто проверяется регистра CRC на 0xFFFF. Невыполнение требования (чтения) просто приводит к защелкиванию признака CRC_VALID и дальнейшее вычисление СRC на потоке вычисляемых данных уже никак на этот признак не влияет. То есть - просто идет поток данных чтения, без разбора - CRC/данные. Как только прекратили выполнять требование чтения - защелкнулся признак VALID (триггер J34) и дальше хранится, а поток продолжает обрабатываться, регистр CRC изменяется итд.Также ( если я правильно понял ) при чтении CRC проверяется так - если требование выполнено, то содержимое регистра данных интерпретируется как данные и включается в расчёт CRC, если же требование не выполнено - содержимое регистра данных интерпретируется как CRC, прибавляется к рассчитанному значению CRC и результат проверяется на равенство 0xFFFF.
Т.е. запуск генератора CRC в режиме записи происходит после первого байта 0xA1 в сдвиговом регистре, перезапуск не происходит никогда, а остановка ( и запись инверсного значения CRC на диск ) происходит при пропуске требования.
---------- Post added at 13:53 ---------- Previous post was at 13:47 ----------
Получается, что:
1. Запуск генератора CRC при чтении происходит в режиме поиска маркера по первому байту 0xA1 в сдвиговом регистре.
2. В процессе чтения признак CRC_VALID непрерывно отражает равенство текущего значения CRC величине 0xFFFF.
3. Повторное чтение маркера не сбрасывает генератор CRC. Чтобы перевести ВП1-128 в режим поиска маркера - нужно записать в регистр статуса бит "начало чтения" ( 8 ).
Последний раз редактировалось Patron; 13.12.2013 в 16:02.
Сообщение от Vslav
Вот и верь после этого описаниям.Я сейчас выполил такое моделирование:На выходе записываемых данных получилось:Код:qbus_write(16'O177132, 16'H3130);
Код:0x30 (то есть, сначала МЛАДШИЙ байт, старший бит первым) 0x31 (то есть, потом СТАРШИЙ байт, старший бит первым)
Значит, хотя в описании ВП1-128 написано:Но на самом деле - первым пишется младший байт регистра данных, а требование выставляется при копировании в сдвиговый регистр старшего байта регистра данных.Код:В режиме 'запись' 7-й разряд РС (TR) устанавливается в единицу после того, как младший байт РДЗ переписался в сдвиговый регистр.
---------- Post added at 14:25 ---------- Previous post was at 14:12 ----------
Здесь написано так:Получается, что и там в описании ошибка и сначала сохраняется младший байт, а затем старший данных.шестнадцатибитный регистр данных чтения принимает два байта данных из сдвигового регистра. В процессе считывания данных с диска сначала сохраняется старший байт, затем младший данных.
Так ?
---------- Post added at 14:35 ---------- Previous post was at 14:25 ----------
Сообщение от VslavНо если слово контрольной суммы пишется в обратном порядке байтов относительно слов данных, то как порядок байтов при чтении получается для всех слов одинаковым ?Код:0x91 (инвертированное 0x6E. Сначала пишется СТАРШИЙ байт инвертированной суммы) 0x16 (инвертированное 0xE9. Потом пишется МЛАДШИЙ байт инвертированной суммы)
Последний раз редактировалось Patron; 13.12.2013 в 15:41.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)