OTN-2:CRC code for MFM FD

MFM記録のフロッピーディスクで使われているCRC(Cyclic Redundancy Check) コードについての考察です。
Macintoshの1.4MBのFD(フロッピーディスク)やMSDOSのFDでは記録変調方式としてMFMが使われています。なおMacintoshの2DDに使われているのはGCRでこれとは異なっています。(OTN-1参照)


(1)CRCコードはどこに使われているのか

まずはFDのフォーマットとして広く使用されているIBMフォーマットの復習から。

IBMフォーマット(3.5インチ、2DDまたは2HD)の1トラックは、次のようになっています。(文献2)

セクタの中のID部とデータ部の最後に1回づつ現われる2バイトのCRCが今回の考察の対象です。これはハードウエア(FDC:フロッピーディスクコントローラーというLSI)で実現されているためか、一般の興味の範囲外とみえ、私が見たどの参考書にも具体的な記述がありませんでした。

なお今回の場合(double density)その他の値は次のように参考書には説明されています。

GAPに書かれる値は"4E"の連続
SYNCに書かれる値は"00"の連続
IM(インデックス・マーク)に書かれる値は"C2C2C2FC"
IAM(IDアドレス・マーク)に書かれる値は"A1A1A1FE"
IDは4バイトでセクタを特定する。1バイト毎にC,H,R,Nと呼ばれ
 C:シリンダ番号(0〜79)
 H:ヘッド番号(0 〜1)
 R:セクタ番号 (1〜18: 1.4MB)(1〜9: 720K)(1〜8: 640K)
 N:セクタ長コード(0〜8)128バイトが0、256バイトが1、512バイトが2、・・・・
DAM(データアドレスマーク)に書かれる値は"A1A1A1FB"
(ただしDDAMと名前が変わり、値が"A1A1A1F8"となる場合がある)


(2)結論(CRCコードの計算法)

CRCコードの計算法は生成多項式と初期値で一意的に規定されます。
今回これを検討した結果、MFMのFDに使われているCRCコードの

生成多項式はP(x) = x^16 + x^12 + x^5 + 1

初期値は0x84CF、ただしIAMまたはDAMを含めて計算する。

であることがわかりました。


(3)推定の過程

CRCが16ビット(2バイト)なので生成多項式は16次となります。16次の多項式でよく使われるのを調べたところ、

(1)CRC-16:x^16 + x^15+ x^2 + 1

(2)CCITT:x^16 + x^12 + x^5 + 1

の2つが推奨されていることがわかりました。たぶん2つの多項式のどちらかが使われているだろうと、まずねらいを絞ることができました。

CRCのハードウエアを実現するのはきわめて簡単で(それだからこそ実用化されている)、下の図(CCITTの例)のように、巡回シフトレジスタからタップを取り出しExculsive-ORを作るだけです。

したがって、これをソフトウエアでシミュレートするのもそれほど難しいことではありません(次節参照)。

RawTrackDumpルーチンを使ってMacintosh 1.4MBのディスクのID部とそれに続くCRCを読み出したところ、次の様になりました。

     C  H  R  N  CRC
(例1)02 00 03 02 41 65 
(例2)02 00 04 02 D8 F2 
6バイト分のCRCを計算したところ、
         CRC-16      CCITT
(例1)  CB73       7C02	
(例2)  F20B       7C02
となり、CCITTの方はどのID部でも同じ値(7C02)でしたが、CRC-16の方はそうはなりませんでした。
このことから、CCITT推奨の生成多項式が使われていることが推測できました。

同じ値ではあるが、CRCの計算結果がゼロにならないということは、ゼロでない初期値が設定されているということになります。初期値を0x0000から0xFFFFまで変化させてCRCを計算し、結果がゼロになる値を探しました。見つかった初期値は0x3775でした。

この多項式と初期値は、MSDOS 1.4MB、MSDOS 720K、NEC 640K等のFDでも全く同じでした。

RawTrackDumpルーチンをもう一度使って、データ部とそれに続くCRCについて調べたところ、次の様になりました。

                DATA                CRC
(例3)  0x00 の512回繰り返し      DA 6E
(例4)  0xF6 の512回繰り返し      2B F6
この例に対し、CCITT推奨の生成多項式でCRC計算結果がゼロになる初期値を探したところ、0x3770が見つかりました。

ID部とデータ部の初期値が違うのは不合理なので、前置のIAMまたはDAMを含めて計算し直しました。この結果、初期値は単一の0x84CFでよいことがわかりました。
(今回はDDAMの入ったFDがなかったので、この場合にどうなるかは不明です。)


(4)ソフトウエアによる実現

前節で説明したCRCを計算するソース・コードはここにあります。

このソースでは16ビットを1ビットづつシフトしながら計算を進めて行きます。今回の目的ではこれで十分でしたが、実はもっと高速の計算アルゴリズムもあります。16回シフトの演算をあらかじめ計算して表として持っておき、1回の索表ですます方法です。

初期値を探索するのに使った、プログラムのソース・コードはここにあります。


(5)残った疑問

私の結論では、初期値は0x84CFで、IAMまたはDAMを含めて計算するとなっています。しかし0x84CFはあまり「きりのいい」数字ではありません。

IAMまたはDAMの2バイト目からの計算だと、初期値は0x5E5Eとなりますが、このほうが「きりがいい」でしょうか?

実際のハードウエアではどうなっているのでしょう?

FDCのハードウエア等をよくご存じの方で、おわかりの方はぜひメールで私に教えて下さい。それに合わせて、すぐにこの稿を改訂したいと思います。


あとがき

このノートは、未発表のメモを整理し、公開用にデータを一部取り直して完成しました。

ルポ/Mac変換のソフトを模索する過程で、CRCコーディングを解読する必要が生じ、追究したのがこの成果です。ちなみに東芝ルポ(1セクタ256バイト)に使用のCRCコーディングはこれと全く同じでした。

Mac内蔵のドライブで異種フォーマットのFDをRawTrackDumpで読み出すときに、これを使えばソフトウエアで誤り検出をすることができます。


参考文献

  1. 『フロッピ・ディスク装置のすべて』高橋昇司著、CQ出版、ISBN4-7898-3664-9(1989初版)
  2. 『PC-8800シリーズ ザ・プロテクト』井上智博著、秀和システムトレーディング(株)(1985年)本棚に残っていた古い本

目次に戻る