tunozemichanの日記 / tunozemichan's diary

SORD社のコンピューターM68やM68MXの解析についての備忘録です。This blog is a memorandum about the analysis of SORD's computers M68 and M68MX.

SORD M23へのCP/M移植メモ その2(ブロッキング/デブロッキング)

 

SORD M23のブロッキング/デブロッキング

以前にも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」です。

CP/Mの移植で最も参照した資料

 

話を戻して、ブロッキング/デブロッキングで最も重要なのは具体的にフロッピーディスクコントローラー(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
 

以上です。