以前にもCP/Mのブロッキング/デブロッキングについて書きましたが、改めてSORD M23の場合について書くことにします。
ここからブロッキング/デブロッキングコードaxg.asmを入手します。これをその1に書いたTOZ.EXEを使って、Z80コードに変換します。ここではファイル名をaxg.z80とします。
cpm2-plmフォルダのCBIOS.Z80(CBIOS.ASMをZ80コードに変換したもの)をベースにしてaxg.asmの内容を適宜コピーします。 基本的には全てコピーすればよいですが、boot:とwboot:は何も書いていないのに等しいので、CBIOS.Z80と対応を取りながらコピーします。具体例は別記事として書きます。
SORD M23のFDCはMB8877A(FD1771)です。このFDCの詳細はネットでも入手できますが、次にあげる2冊を読む方が理解が速いです。1つは、「トランジスタ技術SPECIAL No.11 フロッピ・ディスク・インターフェースの全て」です。これがないとFDCのコードを書くのはかなり困難だと思います。もう1冊は、このブログで何度か触れた「試験に出るX1」です。
話を戻して、ブロッキング/デブロッキングで最も重要なのは具体的にフロッピーディスクコントローラー(FDC)を叩く部分です。axg.z80では以下のようにRETしかありません。
;*****************************************************
;* *
;* WRITEHST performs the physical write to *
;* the host disk, READHST reads the physical *
;* disk. *
;* *
;*****************************************************
writehst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. write "hstsiz" bytes
;from hstbuf and return error flag in erflag.
;return erflag non-zero if error
RET
;
readhst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. read "hstsiz" bytes
;into hstbuf and return error flag in erflag.
RET
SORD M23では、以下のように書きました。writehst:、readhst:ともにほぼ同じ動作です。まず、SEEKして、ホストセクタ番号(CP/Mの論理セクタではない)をセットして、GO_DMA_AND_WRITE0またはGO_DMA_AND_READ0を実行するだけです。セクタ番号に1を足しているのはCP/Mの論理セクタが0オフセットの為です。これはDISKDEFマクロでセクタが1から始まることを指示しても、0から始まります。
writehst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. write "hstsiz" bytes
;from hstbuf and return error flag in erflag.
;return erflag non-zero if error
LD A,(hsttrk)
LD E,A ; E is Track No.
CALL SEEK
LD A,(hstsec)
ADD A,01H
LD C,A ; C is Sector No.
CALL GO_DMA_AND_WRITE0
LD (erflag),A
RET
;
readhst:
;hstdsk = host disk #, hsttrk = host track #,
;hstsec = host sect #. read "hstsiz" bytes
;into hstbuf and return error flag in erflag.
LD A,(hsttrk)
LD E,A ; E is Track No.
CALL SEEK
LD A,(hstsec)
ADD A,01H
LD C,A ; C is Sector No.
CALL GO_DMA_AND_READ0
LD (erflag),A
RET
;
SEEKは以下のように書きました。シークコマンドを発行してエラーチェックをしているだけです。
;
; SEEK subroutine
; E is Track No.
;
SEEK:
LD A,E ; E is Track No.
OUT (FDC_DATA_REG),A
LD A,1CH ; SEEK COMMAND
CALL FDCOUT
AND 98H
RET
GO_DMA_AND_WRITE0:及びGO_DMA_AND_READ0:は以下のように書きました。セクタ番号をFDCのセクタレジスタにセットして、DMAコマンドチェーンを設定して、DMAを起動、FDCにライトコマンド(A0H)、またはリードコマンド(80H)をセットして実行させています。
;
; DMA setting & FDD write FOR SIDE 0
; C is Sector No.
;
GO_DMA_AND_WRITE0:
LD A,C
OUT (FDC_SECTOR_REG),A
LD HL,DMA_WRITE_COMMANDS
CALL DMA_ON
AND 20H
LD A,0A0H ; WRITE DATA COMMAND for Side 0
DO_FDC_WR0:
CALL FDCOUT
AND 0FCH
RET
;
; DMA setting & FDD read FOR SIDE 0
; C is Sector No.
;
GO_DMA_AND_READ0:
LD A,C
OUT (FDC_SECTOR_REG),A
LD HL,DMA_COMMANDS
CALL DMA_ON
AND 20H
LD A,80H ; READ DATA COMMAND for Side 0
DO_FDC0:
CALL FDCOUT
AND 0FCH
RET
;
DAMA_ON:は、単にDMAコマンドチェーンの格納されている先頭アドレスをセットして、コマンドをDMAに渡していくだけの処理です。コードの通り、コマンドチェーンの先頭にはコマンド数が入っています。SORD M23のDMAはZ80DMAです。これはSHARP X1と同じですので、「試験に出るX1」をご覧下さい。
;
; DMA setting & Go
; HL is Address of DMA Command chain
; but top value is No. of DMA Command chain
DMA_ON:
PUSH HL
PUSH BC
LD B,(HL)
INC HL
LD C,DMA_ADDRESS
OTIR
POP BC
POP HL
RET
今回のSORD M23への移植ではコマンドチェーンは以下のように書きました。個々のコマンドは「試験に出るX1」に細かく出ています。
; DMA COMMAND CHAIN
;
DMA_COMMANDS:
DB 15H,0C3H,0C3H,0C3H,0C3H,03CH,0C3H
DB 0BBH,01H,9BFH
DB 6DH
DB 0C3H,0FFH,00H,02CH,010H,08DH
DB 0D7H,0EAH ; this address is hstbuf address !!!!
DB 8AH
DB 0CFH,87H
;
;
DMA_WRITE_COMMANDS:
DB 16H,0C3H,0C3H,0C3H,0C3H,03CH,0C3H
DB 83H ; STOP DMA
DB 79H ; B->A
DB 0D7H,0EAH ; this address is hstbuf address !!!
DB 00H,0FFH ; 256yte transfer
DB 14H,28H,8DH
DB 0C3H,00H ; FDC data register
DB 8AH
DB 0CFH,05H
DB 0CFH,87H
最後に、FDCコマンドアウトコードです。FDCコマンドレジスタにコマンドを入れて、BUSYがクリアされるまで待ちます。
;
; FDC COMMAND OUT subroutine
;
FDCOUT:
OUT (FDC_COMMAND_REG),A
; LD A,30H
LD A,50H
WLOOP: DEC A
JR NZ,WLOOP
LOOP2:
IN A,(FDC_STATUS_REG)
BIT 0,A ; BUSY IS CLEAR?
JR NZ,LOOP2
RET
以上です。