今回もわりと日記的です。
結論から言うとDMAを使って、倍密度記録をデータの取りこぼしなくメモリにコピーできました。苦労したので、以下愚痴です。
迷走した話
前回、4MHzのZ80 の処理能力の限界を知りました。SORD M68には当時のハイエンドマシン(約80万円)ですので、ダイレクトメモリアクセスコントローラー(DMAC)としてZ80DMAを搭載しています。
Z80DMAの諸元については、WEBで色々見つかりますが、かなり高機能なこともあり複雑です。ここでもおすすめの読本は、「試験に出るX1」になります。非常にわかりやすく1級の資料です。
今更ですが、DMAの機能はCPUからバスを奪い、周辺I/Oやメモリ(今回の場合はFDC)との間で直接データのやり取りをすることです。これによりCPUで処理するよりも速くデータの流れをコントロール できます。
SORD M68では、搭載している5.25インチFDD の倍密度記録の読み書きにDMAが使われています。
BOOT ROMを逆アセンブル すると、DMACのI/Oアドレスが複数あったりして混乱しますが、FDCにリードコマンドを発行する直前のDMAコマンドチェーンの宛先アドレスである(0xCC)をDMACのI/Oアドレスだと推定しました。こんなコマンドチェーンをまず定義しています。
C3,BB,01,BF,6D,C3,FF,00,2C,10,8D,00,00,9A,CF,87
ハマりポイントが複数ありますが、まず、C3の後ろの3つのコマンドはこれだけだと意味がないと思われます。何のために入れているのか不明です。6Dから先が重要です。
ここでハマったのはC3が二回出現しているところです。C3はDMAコマンドでは「DMAのリセット」なのですが、2回リセットしてる?と意味不明な動作に焦りますが、ポートAを定義するコマンドである6Dの直後にあり、これはポートAのアドレスでした(コマンド6Dは、ポートAがI/Oであることを指定しているので、これはI/Oアドレスであることが分かる)。どのDMAでもそうですが、DMAは各チャンネルにポートAとBを持っていて、A、B間の動作を定義して動作させます。それが解決すると、今度はI/Oアドレス0xC3はFDCのデータレジスタ ではないという問題が出ます(これはFDCのアドレスが判明するまで混乱の元凶でした)。しかし、これもリードコマンドの数行前に、0xC3を0xCBに書き換えているコードがあるのです。なので実際には、以下のコマンドチェーンがDMAに送られます。
C3,BB,01,BF,6D,CB,FF,00,2C,10,8D,00,00,9A,CF,87
SORD M68は一つしかFDCを持っていないので、わざわざデフォルトのI/Oアドレスを実装していないアドレスに設定しているとは夢にも思いませんでした。それを正しいI/Oアドレスに書き換えるのは、明らかに無駄です。BOOT ROMのDMA周辺コードは不合理な点が多いです。
自作のコードでDMA仕様のデータ転送ができた
自作コードでは、データのコピー先を、B500にしているので以下のようにコマンドを変更しました。
C3,BB,01,BF,6D,CB,FF,00,2C,10,8D,00,B5,9A,CF,87
これでFDCのデータレジスタ から256バイト(00FF)を、メモリB500にコピーします。実行したのが以下の画面です。
問題なくデータを取得できている。
該当セクタのダンプ。これが正しいデータ。
問題ないようです。これでフロッピーディスク から望みの大きさのプログラムを読み込めるようになりました。