CP/M-68Kを移植していく Part 6
今回は、ディスクドライブの読み書きをするコードです。ドライブを直接扱う部分は、ハードウェアごとに違うので省略します。
セクターリード
下は、1セクターをDMAに読みこむコードです。CP/Mの1セクターは128バイトですが、IDEドライブでは512バイトなので、少し工夫が必要です。
read:
bsr cnvlba
cmp.l bufdsec, d1
beq read1
move.l d1, bufdsec
lea.l secbuf, a0
bsr iderd
read1:
move sector, d0
andi #$0003, d0
lsl #7, d0
lea.l secbuf, a0
lea.l (a0, d0), a0
movea.l dma, a1
moveq #127, d0
read2:
move.b (a0)+, (a1)+
dbf d0, read2
clr.l d0
rts
このコードでは、IDEの1セクターを、CP/Mの4セクター分にまとめて扱います。cnvlbaで、ドライブ番号、セクター番号、トラック番後から対応するLBAをもとめます。iderdで、求めたLBAセクターから512バイト、secbufに読み込みます。secbufには4セクター分のデータが格納されているので、対応する部分のアドレスをもとめて、そこからDMAに転送します。
4セクター分をsecbufにキャッシュすることになるので、前後のセクターは同じLBAの場合もありえます。その場合は、iderdをスキップしてメモリ転送だけをします。
セクターライト
write:
bsr cnvlba
cmp.l bufdsec, d1
beq wr2
wr1:
move.l d1, bufdsec
lea.l secbuf, a0
bsr iderd
wr2:
move sector, d0
andi #$03, d0
lsl #7, d0
lea.l secbuf, a0
lea.l (a0, d0), a0
movea.l dma, a1
moveq #127, d0
wr3:
move.b (a1)+, (a0)+
dbf d0, wr3
bsr flush
clr.l d0
rts
セクターライトは、リードと同じ考え方で実装しています。該当するLBAセクターがsecbufにない場合は、iderdでまず読み出します。その上にDMAからのデータを転送上書きし、IDEドライブに書き戻します。
高速化するため、ドライブに書き戻すのを、違うLBAセクターが必要になるまで遅らす方法も考えられますが、今回は単純化するため見送りました。
これで終わりのはずが…
BIOSの残りの部分は比較的簡単なので、公開されているCP/M-68Kのディスクに入っているERGBIOS.Sを読めば理解できました。フルのBIOSを書いてCPM1500とつなげ、それをメモリに読み込んで実行すればCP/M-68Kが起動します。MC68000でCP/Mを動かすなら、これで終わり…だったのですが。