CP/M-68Kを移植していく Part 5
DISK I/O を書いていく
CP/Mのディスクアクセスは、ドライブ番号、トラック番号、セクター番号を指定して読み書きするCHS方式です。しかし、最近のATA対応のドライブでは、通しでつけられた32ビットの論理ブロック番号でアクセスするLBA方式です。
更に違うところがセクタサイズです。CP/Mは1セクタ128バイトですが、ATA対応のデイスクドライブでは512バイトです。
CP/Mで最近のディスクドライブを使おうとすると、このあたりの変換作業が必要になります。
どうするか?
CP/M-8000を移植した際、この辺りの知識がなかったので、かなり悩んだのですが、次のGrant氏のWEBページに解決方法が書かれていました。
この方法は、CP/Mの4セクターを、ATAの1セクターとして扱います。
そして、LBAの下位5ビットでセクター番号を表し、続く上位9ビットはトラック番号、さらに上位4ビットでドライブ番号を表します。つまり、32セクター/トラック、512トラック/ドライブということになります。
ATAでは512バイト/セクターなので、1トラックは32セクターで16384バイトになり、CP/Mの128バイト/セクターでは、128セクター/トラックということになります。
1ドライブのサイズは、512トラック × 128セクター × 128バイトで、8Mバイトになります。CP/Mで8Mバイトのディスクだとかなり贅沢な仕様です。
Disk Parameter Block
ディスクドライブのセクタ数やトラック数などパラメータは、DPMに設定します。同じパラメーターのディスクは、DPBを共有できます。
各値の詳細は、CP/M-68k System Guide に書かれています。
SPTは 、1トラックのセクター数で128です。
BSHとBLMは、ブロックサイズで決まります。Grant氏フォーマットでは、ブロックサイズは4096バイトなので、BSHは5 BLMは31になります。
OFFは、CP/Mシステムを保存するためにディスク先頭から確保するトラック数です。今回の移植では、2トラック 32kバイトを確保します。
DSMは、記憶領域のブロック数 - 1 で、OFFで確保したトラック数分8ブロックは除くので、2039になります
EXMはブロックサイズとDSMから決まり、1になります。
CKSは、DRM / 4 + 1 ですが、マウントしっぱなしのハードディスクでは0で良いようです
DRMは、ディレクトリエントリー数 - 1で、Grant氏フォーマットでは511です。
Disk Parameter Header
各ドライブの設定はDPHに書き、接続するドライブの台数分準備します。
XLTには、論理ブロック番号と物理セクター番号を変換するテーブルのアドレスを入れるのですが、変換しないなら値は0です。
DIRBUFには、128バイトのバッファのアドレスをいれます。
DPBは、対応するDPBのアドレスです
CSVは、マウントしっぱなしのディスクの場合は、0に設定します。
ALVは、(DSM / 8 + 1)バイトのバッファのアドレスを設定します。今回は255バイトになりますが、偶数のほうが都合が良いので256バイトにしておきます。
dph0:
dc.l 0 ; XLT
dc.w 0 ; Scratchpad
dc.w 0 ; Scratchpad
dc.w 0 ; Scartchpad
dc.l dirbuf ; DIRBUF
dc.l dpb ; DPB
dc.l 0 ; CSV
dc.l alv0 ; ALV
dpb:
dc.w 128 ; SPT
dc.b 5 ; BSH
dc.b 31 ; BLM
dc.b 1 ; EXM
dc.b 0 ; dummy
dc.w 2039 ; DSM
dc.w 511 ; DRM
dc.w 0 ; Reserved
dc.w 0 ; CKS
dc.w 2 ; OFF
ckv0:
ds.b 128
alv0:
ds.b 256
dirbuf:
ds.b 128